1 /************************************************************
3 Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 this permission notice appear in supporting documentation. This permission
8 notice shall be included in all copies or substantial portions of the
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
15 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 ********************************************************/
21 * Portions of this code copyright (c) 2005 by Trusted Computer Solutions, Inc.
22 * All rights reserved.
25 #ifdef HAVE_DIX_CONFIG_H
26 #include <dix-config.h>
29 #include <sys/socket.h>
35 #include <X11/Xatom.h>
36 #include "selection.h"
38 #include "scrnintstr.h"
39 #include "windowstr.h"
40 #include "propertyst.h"
41 #include "extnsionst.h"
44 #include "../os/osdep.h"
45 #define _XSELINUX_NEED_FLASK_MAP
46 #include "xselinuxint.h"
48 /* structure passed to auditing callback */
50 ClientPtr client
; /* client */
51 DeviceIntPtr dev
; /* device */
52 char *command
; /* client's executable path */
53 unsigned id
; /* resource id, if any */
54 int restype
; /* resource type, if any */
55 int event
; /* event type, if any */
56 Atom property
; /* property name, if any */
57 Atom selection
; /* selection name, if any */
58 char *extension
; /* extension name, if any */
61 /* private state keys */
62 DevPrivateKeyRec subjectKeyRec
;
63 DevPrivateKeyRec objectKeyRec
;
64 DevPrivateKeyRec dataKeyRec
;
66 /* audit file descriptor */
69 /* atoms for window label properties */
71 static Atom atom_client_ctx
;
73 /* The unlabeled SID */
74 static security_id_t unlabeled_sid
;
76 /* forward declarations */
77 static void SELinuxScreen(CallbackListPtr
*, pointer
, pointer
);
79 /* "true" pointer value for use as callback data */
80 static pointer truep
= (pointer
) 1;
83 * Performs an SELinux permission check.
86 SELinuxDoCheck(SELinuxSubjectRec
* subj
, SELinuxObjectRec
* obj
,
87 security_class_t
class, Mask mode
, SELinuxAuditRec
* auditdata
)
89 /* serverClient requests OK */
93 auditdata
->command
= subj
->command
;
96 if (avc_has_perm(subj
->sid
, obj
->sid
, class, mode
, &subj
->aeref
,
98 if (mode
== DixUnknownAccess
)
99 return Success
; /* DixUnknownAccess requests OK ... for now */
102 ErrorF("SELinux: avc_has_perm: unexpected error %d\n", errno
);
110 * Labels a newly connected client.
113 SELinuxLabelClient(ClientPtr client
)
115 int fd
= XaceGetConnectionNumber(client
);
116 SELinuxSubjectRec
*subj
;
117 SELinuxObjectRec
*obj
;
118 security_context_t ctx
;
120 subj
= dixLookupPrivate(&client
->devPrivates
, subjectKey
);
121 obj
= dixLookupPrivate(&client
->devPrivates
, objectKey
);
123 /* Try to get a context from the socket */
124 if (fd
< 0 || getpeercon_raw(fd
, &ctx
) < 0) {
125 /* Otherwise, fall back to a default context */
126 ctx
= SELinuxDefaultClientLabel();
129 /* For local clients, try and determine the executable name */
130 if (XaceIsLocal(client
)) {
131 /* Get cached command name if CLIENTIDS is enabled. */
132 const char *cmdname
= GetClientCmdName(client
);
133 Bool cached
= (cmdname
!= NULL
);
135 /* If CLIENTIDS is disabled, figure out the command name from
138 pid_t pid
= DetermineClientPid(client
);
141 DetermineClientCmd(pid
, &cmdname
, NULL
);
147 strncpy(subj
->command
, cmdname
, COMMAND_LEN
- 1);
150 free((void *) cmdname
); /* const char * */
154 /* Get a SID from the context */
155 if (avc_context_to_sid_raw(ctx
, &subj
->sid
) < 0)
156 FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n",
159 obj
->sid
= subj
->sid
;
164 * Labels initial server objects.
167 SELinuxLabelInitial(void)
170 XaceScreenAccessRec srec
;
171 SELinuxSubjectRec
*subj
;
172 SELinuxObjectRec
*obj
;
173 security_context_t ctx
;
176 /* Do the serverClient */
177 subj
= dixLookupPrivate(&serverClient
->devPrivates
, subjectKey
);
178 obj
= dixLookupPrivate(&serverClient
->devPrivates
, objectKey
);
179 subj
->privileged
= 1;
181 /* Use the context of the X server process for the serverClient */
182 if (getcon_raw(&ctx
) < 0)
183 FatalError("SELinux: couldn't get context of X server process\n");
185 /* Get a SID from the context */
186 if (avc_context_to_sid_raw(ctx
, &subj
->sid
) < 0)
187 FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx
);
189 obj
->sid
= subj
->sid
;
192 srec
.client
= serverClient
;
193 srec
.access_mode
= DixCreateAccess
;
194 srec
.status
= Success
;
196 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
197 /* Do the screen object */
198 srec
.screen
= screenInfo
.screens
[i
];
199 SELinuxScreen(NULL
, NULL
, &srec
);
201 /* Do the default colormap */
202 dixLookupResourceByType(&unused
, screenInfo
.screens
[i
]->defColormap
,
203 RT_COLORMAP
, serverClient
, DixCreateAccess
);
208 * Labels new resource objects.
211 SELinuxLabelResource(XaceResourceAccessRec
* rec
, SELinuxSubjectRec
* subj
,
212 SELinuxObjectRec
* obj
, security_class_t
class)
217 /* Check for a create context */
218 if (rec
->rtype
& RC_DRAWABLE
&& subj
->win_create_sid
) {
219 obj
->sid
= subj
->win_create_sid
;
224 offset
= dixLookupPrivateOffset(rec
->ptype
);
226 if (rec
->parent
&& offset
>= 0) {
227 /* Use the SID of the parent object in the labeling operation */
228 PrivateRec
**privatePtr
= DEVPRIV_AT(rec
->parent
, offset
);
229 SELinuxObjectRec
*pobj
= dixLookupPrivate(privatePtr
, objectKey
);
234 /* Use the SID of the subject */
238 /* Perform a transition to obtain the final SID */
239 if (avc_compute_create(subj
->sid
, tsid
, class, &obj
->sid
) < 0) {
240 ErrorF("SELinux: a compute_create call failed!\n");
248 * Libselinux Callbacks
252 SELinuxAudit(void *auditdata
,
253 security_class_t
class, char *msgbuf
, size_t msgbufsize
)
255 SELinuxAuditRec
*audit
= auditdata
;
256 ClientPtr client
= audit
->client
;
258 const char *propertyName
, *selectionName
;
259 int major
= -1, minor
= -1;
264 major
= client
->majorOp
;
265 minor
= client
->minorOp
;
269 snprintf(idNum
, 16, "%x", audit
->id
);
271 propertyName
= audit
->property
? NameForAtom(audit
->property
) : NULL
;
272 selectionName
= audit
->selection
? NameForAtom(audit
->selection
) : NULL
;
274 return snprintf(msgbuf
, msgbufsize
,
275 "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
276 (major
>= 0) ? "request=" : "",
277 (major
>= 0) ? LookupRequestName(major
, minor
) : "",
278 audit
->command
? " comm=" : "",
279 audit
->command
? audit
->command
: "",
280 audit
->dev
? " xdevice=\"" : "",
281 audit
->dev
? audit
->dev
->name
: "",
282 audit
->dev
? "\"" : "",
283 audit
->id
? " resid=" : "",
284 audit
->id
? idNum
: "",
285 audit
->restype
? " restype=" : "",
286 audit
->restype
? LookupResourceName(audit
->restype
) : "",
287 audit
->event
? " event=" : "",
288 audit
->event
? LookupEventName(audit
->event
& 127) : "",
289 audit
->property
? " property=" : "",
290 audit
->property
? propertyName
: "",
291 audit
->selection
? " selection=" : "",
292 audit
->selection
? selectionName
: "",
293 audit
->extension
? " extension=" : "",
294 audit
->extension
? audit
->extension
: "");
298 SELinuxLog(int type
, const char *fmt
, ...)
301 char buf
[MAX_AUDIT_MESSAGE_LENGTH
];
306 aut
= AUDIT_USER_MAC_POLICY_LOAD
;
309 aut
= AUDIT_USER_AVC
;
312 aut
= AUDIT_USER_SELINUX_ERR
;
317 vsnprintf(buf
, MAX_AUDIT_MESSAGE_LENGTH
, fmt
, ap
);
318 rc
= audit_log_user_avc_message(audit_fd
, aut
, buf
, NULL
, NULL
, NULL
, 0);
320 LogMessageVerb(X_WARNING
, 0, "%s", buf
);
329 SELinuxDevice(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
331 XaceDeviceAccessRec
*rec
= calldata
;
332 SELinuxSubjectRec
*subj
;
333 SELinuxObjectRec
*obj
;
334 SELinuxAuditRec auditdata
= {.client
= rec
->client
,.dev
= rec
->dev
};
335 security_class_t cls
;
338 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
339 obj
= dixLookupPrivate(&rec
->dev
->devPrivates
, objectKey
);
341 /* If this is a new object that needs labeling, do it now */
342 if (rec
->access_mode
& DixCreateAccess
) {
343 SELinuxSubjectRec
*dsubj
;
345 dsubj
= dixLookupPrivate(&rec
->dev
->devPrivates
, subjectKey
);
347 if (subj
->dev_create_sid
) {
348 /* Label the device with the create context */
349 obj
->sid
= subj
->dev_create_sid
;
350 dsubj
->sid
= subj
->dev_create_sid
;
353 /* Label the device directly with the process SID */
354 obj
->sid
= subj
->sid
;
355 dsubj
->sid
= subj
->sid
;
359 cls
= IsPointerDevice(rec
->dev
) ? SECCLASS_X_POINTER
: SECCLASS_X_KEYBOARD
;
360 rc
= SELinuxDoCheck(subj
, obj
, cls
, rec
->access_mode
, &auditdata
);
366 SELinuxSend(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
368 XaceSendAccessRec
*rec
= calldata
;
369 SELinuxSubjectRec
*subj
;
370 SELinuxObjectRec
*obj
, ev_sid
;
371 SELinuxAuditRec auditdata
= {.client
= rec
->client
,.dev
= rec
->dev
};
372 security_class_t
class;
376 subj
= dixLookupPrivate(&rec
->dev
->devPrivates
, subjectKey
);
378 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
380 obj
= dixLookupPrivate(&rec
->pWin
->devPrivates
, objectKey
);
382 /* Check send permission on window */
383 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_DRAWABLE
, DixSendAccess
,
388 /* Check send permission on specific event types */
389 for (i
= 0; i
< rec
->count
; i
++) {
390 type
= rec
->events
[i
].u
.u
.type
;
391 class = (type
& 128) ? SECCLASS_X_FAKEEVENT
: SECCLASS_X_EVENT
;
393 rc
= SELinuxEventToSID(type
, obj
->sid
, &ev_sid
);
397 auditdata
.event
= type
;
398 rc
= SELinuxDoCheck(subj
, &ev_sid
, class, DixSendAccess
, &auditdata
);
408 SELinuxReceive(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
410 XaceReceiveAccessRec
*rec
= calldata
;
411 SELinuxSubjectRec
*subj
;
412 SELinuxObjectRec
*obj
, ev_sid
;
413 SELinuxAuditRec auditdata
= {.client
= NULL
};
414 security_class_t
class;
417 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
418 obj
= dixLookupPrivate(&rec
->pWin
->devPrivates
, objectKey
);
420 /* Check receive permission on window */
421 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_DRAWABLE
, DixReceiveAccess
,
426 /* Check receive permission on specific event types */
427 for (i
= 0; i
< rec
->count
; i
++) {
428 type
= rec
->events
[i
].u
.u
.type
;
429 class = (type
& 128) ? SECCLASS_X_FAKEEVENT
: SECCLASS_X_EVENT
;
431 rc
= SELinuxEventToSID(type
, obj
->sid
, &ev_sid
);
435 auditdata
.event
= type
;
436 rc
= SELinuxDoCheck(subj
, &ev_sid
, class, DixReceiveAccess
, &auditdata
);
446 SELinuxExtension(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
448 XaceExtAccessRec
*rec
= calldata
;
449 SELinuxSubjectRec
*subj
, *serv
;
450 SELinuxObjectRec
*obj
;
451 SELinuxAuditRec auditdata
= {.client
= rec
->client
};
454 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
455 obj
= dixLookupPrivate(&rec
->ext
->devPrivates
, objectKey
);
457 /* If this is a new object that needs labeling, do it now */
458 /* XXX there should be a separate callback for this */
459 if (obj
->sid
== NULL
) {
462 serv
= dixLookupPrivate(&serverClient
->devPrivates
, subjectKey
);
463 rc
= SELinuxExtensionToSID(rec
->ext
->name
, &sid
);
469 /* Perform a transition to obtain the final SID */
470 if (avc_compute_create(serv
->sid
, sid
, SECCLASS_X_EXTENSION
,
472 ErrorF("SELinux: a SID transition call failed!\n");
473 rec
->status
= BadValue
;
478 /* Perform the security check */
479 auditdata
.extension
= rec
->ext
->name
;
480 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_EXTENSION
, rec
->access_mode
,
487 SELinuxSelection(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
489 XaceSelectionAccessRec
*rec
= calldata
;
490 SELinuxSubjectRec
*subj
;
491 SELinuxObjectRec
*obj
, *data
;
492 Selection
*pSel
= *rec
->ppSel
;
493 Atom name
= pSel
->selection
;
494 Mask access_mode
= rec
->access_mode
;
495 SELinuxAuditRec auditdata
= {.client
= rec
->client
,.selection
= name
};
499 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
500 obj
= dixLookupPrivate(&pSel
->devPrivates
, objectKey
);
502 /* If this is a new object that needs labeling, do it now */
503 if (access_mode
& DixCreateAccess
) {
504 rc
= SELinuxSelectionToSID(name
, subj
, &obj
->sid
, &obj
->poly
);
506 obj
->sid
= unlabeled_sid
;
507 access_mode
= DixSetAttrAccess
;
509 /* If this is a polyinstantiated object, find the right instance */
510 else if (obj
->poly
) {
511 rc
= SELinuxSelectionToSID(name
, subj
, &tsid
, NULL
);
516 while (pSel
->selection
!= name
|| obj
->sid
!= tsid
) {
517 if ((pSel
= pSel
->next
) == NULL
)
519 obj
= dixLookupPrivate(&pSel
->devPrivates
, objectKey
);
525 rec
->status
= BadMatch
;
530 /* Perform the security check */
531 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_SELECTION
, access_mode
,
536 /* Label the content (advisory only) */
537 if (access_mode
& DixSetAttrAccess
) {
538 data
= dixLookupPrivate(&pSel
->devPrivates
, dataKey
);
539 if (subj
->sel_create_sid
)
540 data
->sid
= subj
->sel_create_sid
;
542 data
->sid
= obj
->sid
;
547 SELinuxProperty(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
549 XacePropertyAccessRec
*rec
= calldata
;
550 SELinuxSubjectRec
*subj
;
551 SELinuxObjectRec
*obj
, *data
;
552 PropertyPtr pProp
= *rec
->ppProp
;
553 Atom name
= pProp
->propertyName
;
554 SELinuxAuditRec auditdata
= {.client
= rec
->client
,.property
= name
};
558 /* Don't care about the new content check */
559 if (rec
->access_mode
& DixPostAccess
)
562 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
563 obj
= dixLookupPrivate(&pProp
->devPrivates
, objectKey
);
565 /* If this is a new object that needs labeling, do it now */
566 if (rec
->access_mode
& DixCreateAccess
) {
567 rc
= SELinuxPropertyToSID(name
, subj
, &obj
->sid
, &obj
->poly
);
573 /* If this is a polyinstantiated object, find the right instance */
574 else if (obj
->poly
) {
575 rc
= SELinuxPropertyToSID(name
, subj
, &tsid
, NULL
);
580 while (pProp
->propertyName
!= name
|| obj
->sid
!= tsid
) {
581 if ((pProp
= pProp
->next
) == NULL
)
583 obj
= dixLookupPrivate(&pProp
->devPrivates
, objectKey
);
587 *rec
->ppProp
= pProp
;
589 rec
->status
= BadMatch
;
594 /* Perform the security check */
595 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_PROPERTY
, rec
->access_mode
,
600 /* Label the content (advisory only) */
601 if (rec
->access_mode
& DixWriteAccess
) {
602 data
= dixLookupPrivate(&pProp
->devPrivates
, dataKey
);
603 if (subj
->prp_create_sid
)
604 data
->sid
= subj
->prp_create_sid
;
606 data
->sid
= obj
->sid
;
611 SELinuxResource(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
613 XaceResourceAccessRec
*rec
= calldata
;
614 SELinuxSubjectRec
*subj
;
615 SELinuxObjectRec
*obj
;
616 SELinuxAuditRec auditdata
= {.client
= rec
->client
};
617 Mask access_mode
= rec
->access_mode
;
618 PrivateRec
**privatePtr
;
619 security_class_t
class;
622 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
624 /* Determine if the resource object has a devPrivates field */
625 offset
= dixLookupPrivateOffset(rec
->rtype
);
627 /* No: use the SID of the owning client */
628 class = SECCLASS_X_RESOURCE
;
629 privatePtr
= &clients
[CLIENT_ID(rec
->id
)]->devPrivates
;
630 obj
= dixLookupPrivate(privatePtr
, objectKey
);
633 /* Yes: use the SID from the resource object itself */
634 class = SELinuxTypeToClass(rec
->rtype
);
635 privatePtr
= DEVPRIV_AT(rec
->res
, offset
);
636 obj
= dixLookupPrivate(privatePtr
, objectKey
);
639 /* If this is a new object that needs labeling, do it now */
640 if (access_mode
& DixCreateAccess
&& offset
>= 0) {
641 rc
= SELinuxLabelResource(rec
, subj
, obj
, class);
648 /* Collapse generic resource permissions down to read/write */
649 if (class == SECCLASS_X_RESOURCE
) {
650 access_mode
= ! !(rec
->access_mode
& SELinuxReadMask
); /* rd */
651 access_mode
|= ! !(rec
->access_mode
& ~SELinuxReadMask
) << 1; /* wr */
654 /* Perform the security check */
655 auditdata
.restype
= rec
->rtype
;
656 auditdata
.id
= rec
->id
;
657 rc
= SELinuxDoCheck(subj
, obj
, class, access_mode
, &auditdata
);
661 /* Perform the background none check on windows */
662 if (access_mode
& DixCreateAccess
&& rec
->rtype
== RT_WINDOW
) {
663 rc
= SELinuxDoCheck(subj
, obj
, class, DixBlendAccess
, &auditdata
);
665 ((WindowPtr
) rec
->res
)->forcedBG
= TRUE
;
670 SELinuxScreen(CallbackListPtr
*pcbl
, pointer is_saver
, pointer calldata
)
672 XaceScreenAccessRec
*rec
= calldata
;
673 SELinuxSubjectRec
*subj
;
674 SELinuxObjectRec
*obj
;
675 SELinuxAuditRec auditdata
= {.client
= rec
->client
};
676 Mask access_mode
= rec
->access_mode
;
679 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
680 obj
= dixLookupPrivate(&rec
->screen
->devPrivates
, objectKey
);
682 /* If this is a new object that needs labeling, do it now */
683 if (access_mode
& DixCreateAccess
) {
684 /* Perform a transition to obtain the final SID */
685 if (avc_compute_create(subj
->sid
, subj
->sid
, SECCLASS_X_SCREEN
,
687 ErrorF("SELinux: a compute_create call failed!\n");
688 rec
->status
= BadValue
;
696 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_SCREEN
, access_mode
, &auditdata
);
702 SELinuxClient(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
704 XaceClientAccessRec
*rec
= calldata
;
705 SELinuxSubjectRec
*subj
;
706 SELinuxObjectRec
*obj
;
707 SELinuxAuditRec auditdata
= {.client
= rec
->client
};
710 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
711 obj
= dixLookupPrivate(&rec
->target
->devPrivates
, objectKey
);
713 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_CLIENT
, rec
->access_mode
,
720 SELinuxServer(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
722 XaceServerAccessRec
*rec
= calldata
;
723 SELinuxSubjectRec
*subj
;
724 SELinuxObjectRec
*obj
;
725 SELinuxAuditRec auditdata
= {.client
= rec
->client
};
728 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
729 obj
= dixLookupPrivate(&serverClient
->devPrivates
, objectKey
);
731 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_SERVER
, rec
->access_mode
,
742 SELinuxClientState(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
744 NewClientInfoRec
*pci
= calldata
;
746 switch (pci
->client
->clientState
) {
747 case ClientStateInitial
:
748 SELinuxLabelClient(pci
->client
);
757 SELinuxResourceState(CallbackListPtr
*pcbl
, pointer unused
, pointer calldata
)
759 ResourceStateInfoRec
*rec
= calldata
;
760 SELinuxSubjectRec
*subj
;
761 SELinuxObjectRec
*obj
;
764 if (rec
->type
!= RT_WINDOW
)
766 if (rec
->state
!= ResourceStateAdding
)
769 pWin
= (WindowPtr
) rec
->value
;
770 subj
= dixLookupPrivate(&wClient(pWin
)->devPrivates
, subjectKey
);
773 security_context_t ctx
;
774 int rc
= avc_sid_to_context_raw(subj
->sid
, &ctx
);
777 FatalError("SELinux: Failed to get security context!\n");
778 rc
= dixChangeWindowProperty(serverClient
,
779 pWin
, atom_client_ctx
, XA_STRING
, 8,
780 PropModeReplace
, strlen(ctx
), ctx
, FALSE
);
782 FatalError("SELinux: Failed to set label property on window!\n");
786 FatalError("SELinux: Unexpected unlabeled client found\n");
788 obj
= dixLookupPrivate(&pWin
->devPrivates
, objectKey
);
791 security_context_t ctx
;
792 int rc
= avc_sid_to_context_raw(obj
->sid
, &ctx
);
795 FatalError("SELinux: Failed to get security context!\n");
796 rc
= dixChangeWindowProperty(serverClient
,
797 pWin
, atom_ctx
, XA_STRING
, 8,
798 PropModeReplace
, strlen(ctx
), ctx
, FALSE
);
800 FatalError("SELinux: Failed to set label property on window!\n");
804 FatalError("SELinux: Unexpected unlabeled window found\n");
807 static int netlink_fd
;
810 SELinuxBlockHandler(void *data
, struct timeval
**tv
, void *read_mask
)
815 SELinuxWakeupHandler(void *data
, int err
, void *read_mask
)
817 if (FD_ISSET(netlink_fd
, (fd_set
*) read_mask
))
818 avc_netlink_check_nb();
822 SELinuxFlaskReset(void)
824 /* Unregister callbacks */
825 DeleteCallback(&ClientStateCallback
, SELinuxClientState
, NULL
);
826 DeleteCallback(&ResourceStateCallback
, SELinuxResourceState
, NULL
);
828 XaceDeleteCallback(XACE_EXT_DISPATCH
, SELinuxExtension
, NULL
);
829 XaceDeleteCallback(XACE_RESOURCE_ACCESS
, SELinuxResource
, NULL
);
830 XaceDeleteCallback(XACE_DEVICE_ACCESS
, SELinuxDevice
, NULL
);
831 XaceDeleteCallback(XACE_PROPERTY_ACCESS
, SELinuxProperty
, NULL
);
832 XaceDeleteCallback(XACE_SEND_ACCESS
, SELinuxSend
, NULL
);
833 XaceDeleteCallback(XACE_RECEIVE_ACCESS
, SELinuxReceive
, NULL
);
834 XaceDeleteCallback(XACE_CLIENT_ACCESS
, SELinuxClient
, NULL
);
835 XaceDeleteCallback(XACE_EXT_ACCESS
, SELinuxExtension
, NULL
);
836 XaceDeleteCallback(XACE_SERVER_ACCESS
, SELinuxServer
, NULL
);
837 XaceDeleteCallback(XACE_SELECTION_ACCESS
, SELinuxSelection
, NULL
);
838 XaceDeleteCallback(XACE_SCREEN_ACCESS
, SELinuxScreen
, NULL
);
839 XaceDeleteCallback(XACE_SCREENSAVER_ACCESS
, SELinuxScreen
, truep
);
841 /* Tear down SELinux stuff */
842 audit_close(audit_fd
);
843 avc_netlink_release_fd();
844 RemoveBlockAndWakeupHandlers(SELinuxBlockHandler
, SELinuxWakeupHandler
,
846 RemoveGeneralSocket(netlink_fd
);
852 SELinuxFlaskInit(void)
854 struct selinux_opt avc_option
= { AVC_OPT_SETENFORCE
, (char *) 0 };
855 security_context_t ctx
;
858 switch (selinuxEnforcingState
) {
859 case SELINUX_MODE_ENFORCING
:
860 LogMessage(X_INFO
, "SELinux: Configured in enforcing mode\n");
861 avc_option
.value
= (char *) 1;
863 case SELINUX_MODE_PERMISSIVE
:
864 LogMessage(X_INFO
, "SELinux: Configured in permissive mode\n");
865 avc_option
.value
= (char *) 0;
868 avc_option
.type
= AVC_OPT_UNUSED
;
872 /* Set up SELinux stuff */
873 selinux_set_callback(SELINUX_CB_LOG
, (union selinux_callback
) SELinuxLog
);
874 selinux_set_callback(SELINUX_CB_AUDIT
,
875 (union selinux_callback
) SELinuxAudit
);
877 if (selinux_set_mapping(map
) < 0) {
878 if (errno
== EINVAL
) {
880 ("SELinux: Invalid object class mapping, disabling SELinux support.\n");
883 FatalError("SELinux: Failed to set up security class mapping\n");
886 if (avc_open(&avc_option
, 1) < 0)
887 FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n");
889 if (security_get_initial_context_raw("unlabeled", &ctx
) < 0)
890 FatalError("SELinux: Failed to look up unlabeled context\n");
891 if (avc_context_to_sid_raw(ctx
, &unlabeled_sid
) < 0)
892 FatalError("SELinux: a context_to_SID call failed!\n");
895 /* Prepare for auditing */
896 audit_fd
= audit_open();
898 FatalError("SELinux: Failed to open the system audit log\n");
900 /* Allocate private storage */
901 if (!dixRegisterPrivateKey
902 (subjectKey
, PRIVATE_XSELINUX
, sizeof(SELinuxSubjectRec
)) ||
903 !dixRegisterPrivateKey(objectKey
, PRIVATE_XSELINUX
,
904 sizeof(SELinuxObjectRec
)) ||
905 !dixRegisterPrivateKey(dataKey
, PRIVATE_XSELINUX
,
906 sizeof(SELinuxObjectRec
)))
907 FatalError("SELinux: Failed to allocate private storage.\n");
909 /* Create atoms for doing window labeling */
910 atom_ctx
= MakeAtom("_SELINUX_CONTEXT", 16, TRUE
);
911 if (atom_ctx
== BAD_RESOURCE
)
912 FatalError("SELinux: Failed to create atom\n");
913 atom_client_ctx
= MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE
);
914 if (atom_client_ctx
== BAD_RESOURCE
)
915 FatalError("SELinux: Failed to create atom\n");
917 netlink_fd
= avc_netlink_acquire_fd();
918 AddGeneralSocket(netlink_fd
);
919 RegisterBlockAndWakeupHandlers(SELinuxBlockHandler
, SELinuxWakeupHandler
,
922 /* Register callbacks */
923 ret
&= AddCallback(&ClientStateCallback
, SELinuxClientState
, NULL
);
924 ret
&= AddCallback(&ResourceStateCallback
, SELinuxResourceState
, NULL
);
926 ret
&= XaceRegisterCallback(XACE_EXT_DISPATCH
, SELinuxExtension
, NULL
);
927 ret
&= XaceRegisterCallback(XACE_RESOURCE_ACCESS
, SELinuxResource
, NULL
);
928 ret
&= XaceRegisterCallback(XACE_DEVICE_ACCESS
, SELinuxDevice
, NULL
);
929 ret
&= XaceRegisterCallback(XACE_PROPERTY_ACCESS
, SELinuxProperty
, NULL
);
930 ret
&= XaceRegisterCallback(XACE_SEND_ACCESS
, SELinuxSend
, NULL
);
931 ret
&= XaceRegisterCallback(XACE_RECEIVE_ACCESS
, SELinuxReceive
, NULL
);
932 ret
&= XaceRegisterCallback(XACE_CLIENT_ACCESS
, SELinuxClient
, NULL
);
933 ret
&= XaceRegisterCallback(XACE_EXT_ACCESS
, SELinuxExtension
, NULL
);
934 ret
&= XaceRegisterCallback(XACE_SERVER_ACCESS
, SELinuxServer
, NULL
);
935 ret
&= XaceRegisterCallback(XACE_SELECTION_ACCESS
, SELinuxSelection
, NULL
);
936 ret
&= XaceRegisterCallback(XACE_SCREEN_ACCESS
, SELinuxScreen
, NULL
);
937 ret
&= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS
, SELinuxScreen
, truep
);
939 FatalError("SELinux: Failed to register one or more callbacks\n");
941 /* Label objects that were created before we could register ourself */
942 SELinuxLabelInitial();