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 #include <dix-config.h>
28 #include <sys/socket.h>
32 #include <X11/Xatom.h>
33 #include <X11/Xfuncproto.h>
35 #include "dix/registry_priv.h"
36 #include "os/client_priv.h"
38 #include "selection.h"
40 #include "scrnintstr.h"
41 #include "windowstr.h"
42 #include "propertyst.h"
43 #include "extnsionst.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
*, void *, void *);
79 /* "true" pointer value for use as callback data */
80 static void *truep
= (void *) 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
;
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
;
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 X11_RESTYPE_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
, ...) _X_ATTRIBUTE_PRINTF(2, 3);
301 SELinuxLog(int type
, const char *fmt
, ...)
304 char buf
[MAX_AUDIT_MESSAGE_LENGTH
];
309 aut
= AUDIT_USER_MAC_POLICY_LOAD
;
312 aut
= AUDIT_USER_AVC
;
315 aut
= AUDIT_USER_SELINUX_ERR
;
320 vsnprintf(buf
, MAX_AUDIT_MESSAGE_LENGTH
, fmt
, ap
);
321 rc
= audit_log_user_avc_message(audit_fd
, aut
, buf
, NULL
, NULL
, NULL
, 0);
324 LogMessageVerb(X_WARNING
, 0, "%s", buf
);
333 SELinuxDevice(CallbackListPtr
*pcbl
, void *unused
, void *calldata
)
335 XaceDeviceAccessRec
*rec
= calldata
;
336 SELinuxSubjectRec
*subj
;
337 SELinuxObjectRec
*obj
;
338 SELinuxAuditRec auditdata
= {.client
= rec
->client
,.dev
= rec
->dev
};
339 security_class_t cls
;
342 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
343 obj
= dixLookupPrivate(&rec
->dev
->devPrivates
, objectKey
);
345 /* If this is a new object that needs labeling, do it now */
346 if (rec
->access_mode
& DixCreateAccess
) {
347 SELinuxSubjectRec
*dsubj
;
349 dsubj
= dixLookupPrivate(&rec
->dev
->devPrivates
, subjectKey
);
351 if (subj
->dev_create_sid
) {
352 /* Label the device with the create context */
353 obj
->sid
= subj
->dev_create_sid
;
354 dsubj
->sid
= subj
->dev_create_sid
;
357 /* Label the device directly with the process SID */
358 obj
->sid
= subj
->sid
;
359 dsubj
->sid
= subj
->sid
;
363 cls
= IsPointerDevice(rec
->dev
) ? SECCLASS_X_POINTER
: SECCLASS_X_KEYBOARD
;
364 rc
= SELinuxDoCheck(subj
, obj
, cls
, rec
->access_mode
, &auditdata
);
370 SELinuxSend(CallbackListPtr
*pcbl
, void *unused
, void *calldata
)
372 XaceSendAccessRec
*rec
= calldata
;
373 SELinuxSubjectRec
*subj
;
374 SELinuxObjectRec
*obj
, ev_sid
;
375 SELinuxAuditRec auditdata
= {.client
= rec
->client
,.dev
= rec
->dev
};
376 security_class_t
class;
380 subj
= dixLookupPrivate(&rec
->dev
->devPrivates
, subjectKey
);
382 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
384 obj
= dixLookupPrivate(&rec
->pWin
->devPrivates
, objectKey
);
386 /* Check send permission on window */
387 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_DRAWABLE
, DixSendAccess
,
392 /* Check send permission on specific event types */
393 for (i
= 0; i
< rec
->count
; i
++) {
394 type
= rec
->events
[i
].u
.u
.type
;
395 class = (type
& 128) ? SECCLASS_X_FAKEEVENT
: SECCLASS_X_EVENT
;
397 rc
= SELinuxEventToSID(type
, obj
->sid
, &ev_sid
);
401 auditdata
.event
= type
;
402 rc
= SELinuxDoCheck(subj
, &ev_sid
, class, DixSendAccess
, &auditdata
);
412 SELinuxReceive(CallbackListPtr
*pcbl
, void *unused
, void *calldata
)
414 XaceReceiveAccessRec
*rec
= calldata
;
415 SELinuxSubjectRec
*subj
;
416 SELinuxObjectRec
*obj
, ev_sid
;
417 SELinuxAuditRec auditdata
= {.client
= NULL
};
418 security_class_t
class;
421 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
422 obj
= dixLookupPrivate(&rec
->pWin
->devPrivates
, objectKey
);
424 /* Check receive permission on window */
425 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_DRAWABLE
, DixReceiveAccess
,
430 /* Check receive permission on specific event types */
431 for (i
= 0; i
< rec
->count
; i
++) {
432 type
= rec
->events
[i
].u
.u
.type
;
433 class = (type
& 128) ? SECCLASS_X_FAKEEVENT
: SECCLASS_X_EVENT
;
435 rc
= SELinuxEventToSID(type
, obj
->sid
, &ev_sid
);
439 auditdata
.event
= type
;
440 rc
= SELinuxDoCheck(subj
, &ev_sid
, class, DixReceiveAccess
, &auditdata
);
450 SELinuxExtension(CallbackListPtr
*pcbl
, void *unused
, void *calldata
)
452 XaceExtAccessRec
*rec
= calldata
;
453 SELinuxSubjectRec
*subj
, *serv
;
454 SELinuxObjectRec
*obj
;
455 SELinuxAuditRec auditdata
= {.client
= rec
->client
};
458 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
459 obj
= dixLookupPrivate(&rec
->ext
->devPrivates
, objectKey
);
461 /* If this is a new object that needs labeling, do it now */
462 /* XXX there should be a separate callback for this */
463 if (obj
->sid
== NULL
) {
466 serv
= dixLookupPrivate(&serverClient
->devPrivates
, subjectKey
);
467 rc
= SELinuxExtensionToSID(rec
->ext
->name
, &sid
);
473 /* Perform a transition to obtain the final SID */
474 if (avc_compute_create(serv
->sid
, sid
, SECCLASS_X_EXTENSION
,
476 ErrorF("SELinux: a SID transition call failed!\n");
477 rec
->status
= BadValue
;
482 /* Perform the security check */
483 auditdata
.extension
= (char *) rec
->ext
->name
;
484 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_EXTENSION
, rec
->access_mode
,
491 SELinuxSelection(CallbackListPtr
*pcbl
, void *unused
, void *calldata
)
493 XaceSelectionAccessRec
*rec
= calldata
;
494 SELinuxSubjectRec
*subj
;
495 SELinuxObjectRec
*obj
, *data
;
496 Selection
*pSel
= *rec
->ppSel
;
497 Atom name
= pSel
->selection
;
498 Mask access_mode
= rec
->access_mode
;
499 SELinuxAuditRec auditdata
= {.client
= rec
->client
,.selection
= name
};
503 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
504 obj
= dixLookupPrivate(&pSel
->devPrivates
, objectKey
);
506 /* If this is a new object that needs labeling, do it now */
507 if (access_mode
& DixCreateAccess
) {
508 rc
= SELinuxSelectionToSID(name
, subj
, &obj
->sid
, &obj
->poly
);
510 obj
->sid
= unlabeled_sid
;
511 access_mode
= DixSetAttrAccess
;
513 /* If this is a polyinstantiated object, find the right instance */
514 else if (obj
->poly
) {
515 rc
= SELinuxSelectionToSID(name
, subj
, &tsid
, NULL
);
520 while (pSel
->selection
!= name
|| obj
->sid
!= tsid
) {
521 if ((pSel
= pSel
->next
) == NULL
)
523 obj
= dixLookupPrivate(&pSel
->devPrivates
, objectKey
);
529 rec
->status
= BadMatch
;
534 /* Perform the security check */
535 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_SELECTION
, access_mode
,
540 /* Label the content (advisory only) */
541 if (access_mode
& DixSetAttrAccess
) {
542 data
= dixLookupPrivate(&pSel
->devPrivates
, dataKey
);
543 if (subj
->sel_create_sid
)
544 data
->sid
= subj
->sel_create_sid
;
546 data
->sid
= obj
->sid
;
551 SELinuxProperty(CallbackListPtr
*pcbl
, void *unused
, void *calldata
)
553 XacePropertyAccessRec
*rec
= calldata
;
554 SELinuxSubjectRec
*subj
;
555 SELinuxObjectRec
*obj
, *data
;
556 PropertyPtr pProp
= *rec
->ppProp
;
557 Atom name
= pProp
->propertyName
;
558 SELinuxAuditRec auditdata
= {.client
= rec
->client
,.property
= name
};
562 /* Don't care about the new content check */
563 if (rec
->access_mode
& DixPostAccess
)
566 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
567 obj
= dixLookupPrivate(&pProp
->devPrivates
, objectKey
);
569 /* If this is a new object that needs labeling, do it now */
570 if (rec
->access_mode
& DixCreateAccess
) {
571 rc
= SELinuxPropertyToSID(name
, subj
, &obj
->sid
, &obj
->poly
);
577 /* If this is a polyinstantiated object, find the right instance */
578 else if (obj
->poly
) {
579 rc
= SELinuxPropertyToSID(name
, subj
, &tsid
, NULL
);
584 while (pProp
->propertyName
!= name
|| obj
->sid
!= tsid
) {
585 if ((pProp
= pProp
->next
) == NULL
)
587 obj
= dixLookupPrivate(&pProp
->devPrivates
, objectKey
);
591 *rec
->ppProp
= pProp
;
593 rec
->status
= BadMatch
;
598 /* Perform the security check */
599 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_PROPERTY
, rec
->access_mode
,
604 /* Label the content (advisory only) */
605 if (rec
->access_mode
& DixWriteAccess
) {
606 data
= dixLookupPrivate(&pProp
->devPrivates
, dataKey
);
607 if (subj
->prp_create_sid
)
608 data
->sid
= subj
->prp_create_sid
;
610 data
->sid
= obj
->sid
;
615 SELinuxResource(CallbackListPtr
*pcbl
, void *unused
, void *calldata
)
617 XaceResourceAccessRec
*rec
= calldata
;
618 SELinuxSubjectRec
*subj
;
619 SELinuxObjectRec
*obj
;
620 SELinuxAuditRec auditdata
= {.client
= rec
->client
};
621 Mask access_mode
= rec
->access_mode
;
622 PrivateRec
**privatePtr
;
623 security_class_t
class;
626 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
628 /* Determine if the resource object has a devPrivates field */
629 offset
= dixLookupPrivateOffset(rec
->rtype
);
631 /* No: use the SID of the owning client */
632 class = SECCLASS_X_RESOURCE
;
633 privatePtr
= &clients
[CLIENT_ID(rec
->id
)]->devPrivates
;
634 obj
= dixLookupPrivate(privatePtr
, objectKey
);
637 /* Yes: use the SID from the resource object itself */
638 class = SELinuxTypeToClass(rec
->rtype
);
639 privatePtr
= DEVPRIV_AT(rec
->res
, offset
);
640 obj
= dixLookupPrivate(privatePtr
, objectKey
);
643 /* If this is a new object that needs labeling, do it now */
644 if (access_mode
& DixCreateAccess
&& offset
>= 0) {
645 rc
= SELinuxLabelResource(rec
, subj
, obj
, class);
652 /* Collapse generic resource permissions down to read/write */
653 if (class == SECCLASS_X_RESOURCE
) {
654 access_mode
= ! !(rec
->access_mode
& SELinuxReadMask
); /* rd */
655 access_mode
|= ! !(rec
->access_mode
& ~SELinuxReadMask
) << 1; /* wr */
658 /* Perform the security check */
659 auditdata
.restype
= rec
->rtype
;
660 auditdata
.id
= rec
->id
;
661 rc
= SELinuxDoCheck(subj
, obj
, class, access_mode
, &auditdata
);
665 /* Perform the background none check on windows */
666 if (access_mode
& DixCreateAccess
&& rec
->rtype
== X11_RESTYPE_WINDOW
) {
667 rc
= SELinuxDoCheck(subj
, obj
, class, DixBlendAccess
, &auditdata
);
669 ((WindowPtr
) rec
->res
)->forcedBG
= TRUE
;
674 SELinuxScreen(CallbackListPtr
*pcbl
, void *is_saver
, void *calldata
)
676 XaceScreenAccessRec
*rec
= calldata
;
677 SELinuxSubjectRec
*subj
;
678 SELinuxObjectRec
*obj
;
679 SELinuxAuditRec auditdata
= {.client
= rec
->client
};
680 Mask access_mode
= rec
->access_mode
;
683 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
684 obj
= dixLookupPrivate(&rec
->screen
->devPrivates
, objectKey
);
686 /* If this is a new object that needs labeling, do it now */
687 if (access_mode
& DixCreateAccess
) {
688 /* Perform a transition to obtain the final SID */
689 if (avc_compute_create(subj
->sid
, subj
->sid
, SECCLASS_X_SCREEN
,
691 ErrorF("SELinux: a compute_create call failed!\n");
692 rec
->status
= BadValue
;
700 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_SCREEN
, access_mode
, &auditdata
);
706 SELinuxClient(CallbackListPtr
*pcbl
, void *unused
, void *calldata
)
708 XaceClientAccessRec
*rec
= calldata
;
709 SELinuxSubjectRec
*subj
;
710 SELinuxObjectRec
*obj
;
711 SELinuxAuditRec auditdata
= {.client
= rec
->client
};
714 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
715 obj
= dixLookupPrivate(&rec
->target
->devPrivates
, objectKey
);
717 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_CLIENT
, rec
->access_mode
,
724 SELinuxServer(CallbackListPtr
*pcbl
, void *unused
, void *calldata
)
726 XaceServerAccessRec
*rec
= calldata
;
727 SELinuxSubjectRec
*subj
;
728 SELinuxObjectRec
*obj
;
729 SELinuxAuditRec auditdata
= {.client
= rec
->client
};
732 subj
= dixLookupPrivate(&rec
->client
->devPrivates
, subjectKey
);
733 obj
= dixLookupPrivate(&serverClient
->devPrivates
, objectKey
);
735 rc
= SELinuxDoCheck(subj
, obj
, SECCLASS_X_SERVER
, rec
->access_mode
,
746 SELinuxClientState(CallbackListPtr
*pcbl
, void *unused
, void *calldata
)
748 NewClientInfoRec
*pci
= calldata
;
750 switch (pci
->client
->clientState
) {
751 case ClientStateInitial
:
752 SELinuxLabelClient(pci
->client
);
761 SELinuxResourceState(CallbackListPtr
*pcbl
, void *unused
, void *calldata
)
763 ResourceStateInfoRec
*rec
= calldata
;
764 SELinuxSubjectRec
*subj
;
765 SELinuxObjectRec
*obj
;
768 if (rec
->type
!= X11_RESTYPE_WINDOW
)
770 if (rec
->state
!= ResourceStateAdding
)
773 pWin
= (WindowPtr
) rec
->value
;
774 subj
= dixLookupPrivate(&wClient(pWin
)->devPrivates
, subjectKey
);
778 int rc
= avc_sid_to_context_raw(subj
->sid
, &ctx
);
781 FatalError("SELinux: Failed to get security context!\n");
782 rc
= dixChangeWindowProperty(serverClient
,
783 pWin
, atom_client_ctx
, XA_STRING
, 8,
784 PropModeReplace
, strlen(ctx
), ctx
, FALSE
);
786 FatalError("SELinux: Failed to set label property on window!\n");
790 FatalError("SELinux: Unexpected unlabeled client found\n");
792 obj
= dixLookupPrivate(&pWin
->devPrivates
, objectKey
);
796 int rc
= avc_sid_to_context_raw(obj
->sid
, &ctx
);
799 FatalError("SELinux: Failed to get security context!\n");
800 rc
= dixChangeWindowProperty(serverClient
,
801 pWin
, atom_ctx
, XA_STRING
, 8,
802 PropModeReplace
, strlen(ctx
), ctx
, FALSE
);
804 FatalError("SELinux: Failed to set label property on window!\n");
808 FatalError("SELinux: Unexpected unlabeled window found\n");
811 static int netlink_fd
;
814 SELinuxNetlinkNotify(int fd
, int ready
, void *data
)
816 avc_netlink_check_nb();
820 SELinuxFlaskReset(void)
822 /* Unregister callbacks */
823 DeleteCallback(&ClientStateCallback
, SELinuxClientState
, NULL
);
824 DeleteCallback(&ResourceStateCallback
, SELinuxResourceState
, NULL
);
826 XaceDeleteCallback(XACE_EXT_DISPATCH
, SELinuxExtension
, NULL
);
827 XaceDeleteCallback(XACE_RESOURCE_ACCESS
, SELinuxResource
, NULL
);
828 XaceDeleteCallback(XACE_DEVICE_ACCESS
, SELinuxDevice
, NULL
);
829 XaceDeleteCallback(XACE_PROPERTY_ACCESS
, SELinuxProperty
, NULL
);
830 XaceDeleteCallback(XACE_SEND_ACCESS
, SELinuxSend
, NULL
);
831 XaceDeleteCallback(XACE_RECEIVE_ACCESS
, SELinuxReceive
, NULL
);
832 XaceDeleteCallback(XACE_CLIENT_ACCESS
, SELinuxClient
, NULL
);
833 XaceDeleteCallback(XACE_EXT_ACCESS
, SELinuxExtension
, NULL
);
834 XaceDeleteCallback(XACE_SERVER_ACCESS
, SELinuxServer
, NULL
);
835 XaceDeleteCallback(XACE_SELECTION_ACCESS
, SELinuxSelection
, NULL
);
836 XaceDeleteCallback(XACE_SCREEN_ACCESS
, SELinuxScreen
, NULL
);
837 XaceDeleteCallback(XACE_SCREENSAVER_ACCESS
, SELinuxScreen
, truep
);
839 /* Tear down SELinux stuff */
840 audit_close(audit_fd
);
841 avc_netlink_release_fd();
842 RemoveNotifyFd(netlink_fd
);
848 SELinuxFlaskInit(void)
850 struct selinux_opt avc_option
= { AVC_OPT_SETENFORCE
, (char *) 0 };
854 switch (selinuxEnforcingState
) {
855 case SELINUX_MODE_ENFORCING
:
856 LogMessage(X_INFO
, "SELinux: Configured in enforcing mode\n");
857 avc_option
.value
= (char *) 1;
859 case SELINUX_MODE_PERMISSIVE
:
860 LogMessage(X_INFO
, "SELinux: Configured in permissive mode\n");
861 avc_option
.value
= (char *) 0;
864 avc_option
.type
= AVC_OPT_UNUSED
;
868 /* Set up SELinux stuff */
869 selinux_set_callback(SELINUX_CB_LOG
, (union selinux_callback
) SELinuxLog
);
870 selinux_set_callback(SELINUX_CB_AUDIT
,
871 (union selinux_callback
) SELinuxAudit
);
873 if (selinux_set_mapping(map
) < 0) {
874 if (errno
== EINVAL
) {
876 ("SELinux: Invalid object class mapping, disabling SELinux support.\n");
879 FatalError("SELinux: Failed to set up security class mapping\n");
882 if (avc_open(&avc_option
, 1) < 0)
883 FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n");
885 if (security_get_initial_context_raw("unlabeled", &ctx
) < 0)
886 FatalError("SELinux: Failed to look up unlabeled context\n");
887 if (avc_context_to_sid_raw(ctx
, &unlabeled_sid
) < 0)
888 FatalError("SELinux: a context_to_SID call failed!\n");
891 /* Prepare for auditing */
892 audit_fd
= audit_open();
894 FatalError("SELinux: Failed to open the system audit log\n");
896 /* Allocate private storage */
897 if (!dixRegisterPrivateKey
898 (subjectKey
, PRIVATE_XSELINUX
, sizeof(SELinuxSubjectRec
)) ||
899 !dixRegisterPrivateKey(objectKey
, PRIVATE_XSELINUX
,
900 sizeof(SELinuxObjectRec
)) ||
901 !dixRegisterPrivateKey(dataKey
, PRIVATE_XSELINUX
,
902 sizeof(SELinuxObjectRec
)))
903 FatalError("SELinux: Failed to allocate private storage.\n");
905 /* Create atoms for doing window labeling */
906 atom_ctx
= MakeAtom("_SELINUX_CONTEXT", 16, TRUE
);
907 if (atom_ctx
== BAD_RESOURCE
)
908 FatalError("SELinux: Failed to create atom\n");
909 atom_client_ctx
= MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE
);
910 if (atom_client_ctx
== BAD_RESOURCE
)
911 FatalError("SELinux: Failed to create atom\n");
913 netlink_fd
= avc_netlink_acquire_fd();
914 SetNotifyFd(netlink_fd
, SELinuxNetlinkNotify
, X_NOTIFY_READ
, NULL
);
916 /* Register callbacks */
917 ret
&= AddCallback(&ClientStateCallback
, SELinuxClientState
, NULL
);
918 ret
&= AddCallback(&ResourceStateCallback
, SELinuxResourceState
, NULL
);
920 ret
&= XaceRegisterCallback(XACE_EXT_DISPATCH
, SELinuxExtension
, NULL
);
921 ret
&= XaceRegisterCallback(XACE_RESOURCE_ACCESS
, SELinuxResource
, NULL
);
922 ret
&= XaceRegisterCallback(XACE_DEVICE_ACCESS
, SELinuxDevice
, NULL
);
923 ret
&= XaceRegisterCallback(XACE_PROPERTY_ACCESS
, SELinuxProperty
, NULL
);
924 ret
&= XaceRegisterCallback(XACE_SEND_ACCESS
, SELinuxSend
, NULL
);
925 ret
&= XaceRegisterCallback(XACE_RECEIVE_ACCESS
, SELinuxReceive
, NULL
);
926 ret
&= XaceRegisterCallback(XACE_CLIENT_ACCESS
, SELinuxClient
, NULL
);
927 ret
&= XaceRegisterCallback(XACE_EXT_ACCESS
, SELinuxExtension
, NULL
);
928 ret
&= XaceRegisterCallback(XACE_SERVER_ACCESS
, SELinuxServer
, NULL
);
929 ret
&= XaceRegisterCallback(XACE_SELECTION_ACCESS
, SELinuxSelection
, NULL
);
930 ret
&= XaceRegisterCallback(XACE_SCREEN_ACCESS
, SELinuxScreen
, NULL
);
931 ret
&= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS
, SELinuxScreen
, truep
);
933 FatalError("SELinux: Failed to register one or more callbacks\n");
935 /* Label objects that were created before we could register ourself */
936 SELinuxLabelInitial();