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 ********************************************************/
20 #include <dix-config.h>
22 #include "dix/dix_priv.h"
23 #include "dix/property_priv.h"
25 #include "selection.h"
27 #include "windowstr.h"
28 #include "propertyst.h"
29 #include "extnsionst.h"
30 #include "extinit_priv.h"
31 #include "xselinuxint.h"
33 #define CTX_DEV offsetof(SELinuxSubjectRec, dev_create_sid)
34 #define CTX_WIN offsetof(SELinuxSubjectRec, win_create_sid)
35 #define CTX_PRP offsetof(SELinuxSubjectRec, prp_create_sid)
36 #define CTX_SEL offsetof(SELinuxSubjectRec, sel_create_sid)
37 #define USE_PRP offsetof(SELinuxSubjectRec, prp_use_sid)
38 #define USE_SEL offsetof(SELinuxSubjectRec, sel_use_sid)
48 Bool noSELinuxExtension
= FALSE
;
49 int selinuxEnforcingState
= SELINUX_MODE_DEFAULT
;
56 SELinuxCopyContext(char *ptr
, unsigned len
)
58 char *copy
= malloc(len
+ 1);
62 strncpy(copy
, ptr
, len
);
68 ProcSELinuxQueryVersion(ClientPtr client
)
70 SELinuxQueryVersionReply rep
= {
72 .sequenceNumber
= client
->sequence
,
74 .server_major
= SELINUX_MAJOR_VERSION
,
75 .server_minor
= SELINUX_MINOR_VERSION
77 if (client
->swapped
) {
78 swaps(&rep
.sequenceNumber
);
80 swaps(&rep
.server_major
);
81 swaps(&rep
.server_minor
);
83 WriteToClient(client
, sizeof(rep
), &rep
);
88 SELinuxSendContextReply(ClientPtr client
, security_id_t sid
)
90 SELinuxGetContextReply rep
;
95 if (avc_sid_to_context_raw(sid
, &ctx
) < 0)
97 len
= strlen(ctx
) + 1;
100 rep
= (SELinuxGetContextReply
) {
102 .sequenceNumber
= client
->sequence
,
103 .length
= bytes_to_int32(len
),
107 if (client
->swapped
) {
109 swaps(&rep
.sequenceNumber
);
110 swapl(&rep
.context_len
);
113 WriteToClient(client
, sizeof(SELinuxGetContextReply
), &rep
);
114 WriteToClient(client
, len
, ctx
);
120 ProcSELinuxSetCreateContext(ClientPtr client
, unsigned offset
)
122 PrivateRec
**privPtr
= &client
->devPrivates
;
128 REQUEST(SELinuxSetCreateContextReq
);
129 REQUEST_FIXED_SIZE(SELinuxSetCreateContextReq
, stuff
->context_len
);
131 if (stuff
->context_len
> 0) {
132 ctx
= SELinuxCopyContext((char *) (stuff
+ 1), stuff
->context_len
);
137 ptr
= dixLookupPrivate(privPtr
, subjectKey
);
138 pSid
= (security_id_t
*) (ptr
+ offset
);
142 if (stuff
->context_len
> 0) {
143 if (security_check_context_raw(ctx
) < 0 ||
144 avc_context_to_sid_raw(ctx
, pSid
) < 0)
153 ProcSELinuxGetCreateContext(ClientPtr client
, unsigned offset
)
158 REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq
);
160 if (offset
== CTX_DEV
)
161 ptr
= dixLookupPrivate(&serverClient
->devPrivates
, subjectKey
);
163 ptr
= dixLookupPrivate(&client
->devPrivates
, subjectKey
);
165 pSid
= (security_id_t
*) (ptr
+ offset
);
166 return SELinuxSendContextReply(client
, *pSid
);
170 ProcSELinuxSetDeviceContext(ClientPtr client
)
175 SELinuxSubjectRec
*subj
;
176 SELinuxObjectRec
*obj
;
179 REQUEST(SELinuxSetContextReq
);
180 REQUEST_FIXED_SIZE(SELinuxSetContextReq
, stuff
->context_len
);
182 if (stuff
->context_len
< 1)
184 ctx
= SELinuxCopyContext((char *) (stuff
+ 1), stuff
->context_len
);
188 rc
= dixLookupDevice(&dev
, stuff
->id
, client
, DixManageAccess
);
192 if (security_check_context_raw(ctx
) < 0 ||
193 avc_context_to_sid_raw(ctx
, &sid
) < 0) {
198 subj
= dixLookupPrivate(&dev
->devPrivates
, subjectKey
);
200 obj
= dixLookupPrivate(&dev
->devPrivates
, objectKey
);
210 ProcSELinuxGetDeviceContext(ClientPtr client
)
213 SELinuxSubjectRec
*subj
;
216 REQUEST(SELinuxGetContextReq
);
217 REQUEST_SIZE_MATCH(SELinuxGetContextReq
);
219 rc
= dixLookupDevice(&dev
, stuff
->id
, client
, DixGetAttrAccess
);
223 subj
= dixLookupPrivate(&dev
->devPrivates
, subjectKey
);
224 return SELinuxSendContextReply(client
, subj
->sid
);
228 ProcSELinuxGetDrawableContext(ClientPtr client
)
231 PrivateRec
**privatePtr
;
232 SELinuxObjectRec
*obj
;
235 REQUEST(SELinuxGetContextReq
);
236 REQUEST_SIZE_MATCH(SELinuxGetContextReq
);
238 rc
= dixLookupDrawable(&pDraw
, stuff
->id
, client
, 0, DixGetAttrAccess
);
242 if (pDraw
->type
== DRAWABLE_PIXMAP
)
243 privatePtr
= &((PixmapPtr
) pDraw
)->devPrivates
;
245 privatePtr
= &((WindowPtr
) pDraw
)->devPrivates
;
247 obj
= dixLookupPrivate(privatePtr
, objectKey
);
248 return SELinuxSendContextReply(client
, obj
->sid
);
252 ProcSELinuxGetPropertyContext(ClientPtr client
, void *privKey
)
256 SELinuxObjectRec
*obj
;
259 REQUEST(SELinuxGetPropertyContextReq
);
260 REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq
);
262 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetPropAccess
);
266 rc
= dixLookupProperty(&pProp
, pWin
, stuff
->property
, client
,
271 obj
= dixLookupPrivate(&pProp
->devPrivates
, privKey
);
272 return SELinuxSendContextReply(client
, obj
->sid
);
276 ProcSELinuxGetSelectionContext(ClientPtr client
, void *privKey
)
279 SELinuxObjectRec
*obj
;
282 REQUEST(SELinuxGetContextReq
);
283 REQUEST_SIZE_MATCH(SELinuxGetContextReq
);
285 rc
= dixLookupSelection(&pSel
, stuff
->id
, client
, DixGetAttrAccess
);
289 obj
= dixLookupPrivate(&pSel
->devPrivates
, privKey
);
290 return SELinuxSendContextReply(client
, obj
->sid
);
294 ProcSELinuxGetClientContext(ClientPtr client
)
297 SELinuxSubjectRec
*subj
;
300 REQUEST(SELinuxGetContextReq
);
301 REQUEST_SIZE_MATCH(SELinuxGetContextReq
);
303 rc
= dixLookupClient(&target
, stuff
->id
, client
, DixGetAttrAccess
);
307 subj
= dixLookupPrivate(&target
->devPrivates
, subjectKey
);
308 return SELinuxSendContextReply(client
, subj
->sid
);
312 SELinuxPopulateItem(SELinuxListItemRec
* i
, PrivateRec
** privPtr
, CARD32 id
,
315 SELinuxObjectRec
*obj
= dixLookupPrivate(privPtr
, objectKey
);
316 SELinuxObjectRec
*data
= dixLookupPrivate(privPtr
, dataKey
);
318 if (avc_sid_to_context_raw(obj
->sid
, &i
->octx
) < 0)
320 if (avc_sid_to_context_raw(data
->sid
, &i
->dctx
) < 0)
324 i
->octx_len
= bytes_to_int32(strlen(i
->octx
) + 1);
325 i
->dctx_len
= bytes_to_int32(strlen(i
->dctx
) + 1);
327 *size
+= i
->octx_len
+ i
->dctx_len
+ 3;
332 SELinuxFreeItems(SELinuxListItemRec
* items
, int count
)
336 for (k
= 0; k
< count
; k
++) {
337 freecon(items
[k
].octx
);
338 freecon(items
[k
].dctx
);
344 SELinuxSendItemsToClient(ClientPtr client
, SELinuxListItemRec
* items
,
348 SELinuxListItemsReply rep
;
351 buf
= calloc(size
, sizeof(CARD32
));
357 /* Fill in the buffer */
358 for (k
= 0; k
< count
; k
++) {
359 buf
[pos
] = items
[k
].id
;
364 buf
[pos
] = items
[k
].octx_len
* 4;
369 buf
[pos
] = items
[k
].dctx_len
* 4;
374 memcpy((char *) (buf
+ pos
), items
[k
].octx
, strlen(items
[k
].octx
) + 1);
375 pos
+= items
[k
].octx_len
;
376 memcpy((char *) (buf
+ pos
), items
[k
].dctx
, strlen(items
[k
].dctx
) + 1);
377 pos
+= items
[k
].dctx_len
;
380 /* Send reply to client */
381 rep
= (SELinuxListItemsReply
) {
383 .sequenceNumber
= client
->sequence
,
388 if (client
->swapped
) {
390 swaps(&rep
.sequenceNumber
);
394 WriteToClient(client
, sizeof(SELinuxListItemsReply
), &rep
);
395 WriteToClient(client
, size
* 4, buf
);
397 /* Free stuff and return */
401 SELinuxFreeItems(items
, count
);
406 ProcSELinuxListProperties(ClientPtr client
)
410 SELinuxListItemRec
*items
;
411 int rc
, count
, size
, i
;
414 REQUEST(SELinuxGetContextReq
);
415 REQUEST_SIZE_MATCH(SELinuxGetContextReq
);
417 rc
= dixLookupWindow(&pWin
, stuff
->id
, client
, DixListPropAccess
);
421 /* Count the number of properties and allocate items */
423 for (pProp
= wUserProps(pWin
); pProp
; pProp
= pProp
->next
)
425 items
= calloc(count
, sizeof(SELinuxListItemRec
));
429 /* Fill in the items and calculate size */
432 for (pProp
= wUserProps(pWin
); pProp
; pProp
= pProp
->next
) {
433 id
= pProp
->propertyName
;
434 rc
= SELinuxPopulateItem(items
+ i
, &pProp
->devPrivates
, id
, &size
);
436 SELinuxFreeItems(items
, count
);
442 return SELinuxSendItemsToClient(client
, items
, size
, count
);
446 ProcSELinuxListSelections(ClientPtr client
)
449 SELinuxListItemRec
*items
;
450 int rc
, count
, size
, i
;
453 REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq
);
455 /* Count the number of selections and allocate items */
457 for (pSel
= CurrentSelections
; pSel
; pSel
= pSel
->next
)
459 items
= calloc(count
, sizeof(SELinuxListItemRec
));
463 /* Fill in the items and calculate size */
466 for (pSel
= CurrentSelections
; pSel
; pSel
= pSel
->next
) {
467 id
= pSel
->selection
;
468 rc
= SELinuxPopulateItem(items
+ i
, &pSel
->devPrivates
, id
, &size
);
470 SELinuxFreeItems(items
, count
);
476 return SELinuxSendItemsToClient(client
, items
, size
, count
);
480 ProcSELinuxDispatch(ClientPtr client
)
483 switch (stuff
->data
) {
484 case X_SELinuxQueryVersion
:
485 return ProcSELinuxQueryVersion(client
);
486 case X_SELinuxSetDeviceCreateContext
:
487 return ProcSELinuxSetCreateContext(client
, CTX_DEV
);
488 case X_SELinuxGetDeviceCreateContext
:
489 return ProcSELinuxGetCreateContext(client
, CTX_DEV
);
490 case X_SELinuxSetDeviceContext
:
491 return ProcSELinuxSetDeviceContext(client
);
492 case X_SELinuxGetDeviceContext
:
493 return ProcSELinuxGetDeviceContext(client
);
494 case X_SELinuxSetDrawableCreateContext
:
495 return ProcSELinuxSetCreateContext(client
, CTX_WIN
);
496 case X_SELinuxGetDrawableCreateContext
:
497 return ProcSELinuxGetCreateContext(client
, CTX_WIN
);
498 case X_SELinuxGetDrawableContext
:
499 return ProcSELinuxGetDrawableContext(client
);
500 case X_SELinuxSetPropertyCreateContext
:
501 return ProcSELinuxSetCreateContext(client
, CTX_PRP
);
502 case X_SELinuxGetPropertyCreateContext
:
503 return ProcSELinuxGetCreateContext(client
, CTX_PRP
);
504 case X_SELinuxSetPropertyUseContext
:
505 return ProcSELinuxSetCreateContext(client
, USE_PRP
);
506 case X_SELinuxGetPropertyUseContext
:
507 return ProcSELinuxGetCreateContext(client
, USE_PRP
);
508 case X_SELinuxGetPropertyContext
:
509 return ProcSELinuxGetPropertyContext(client
, objectKey
);
510 case X_SELinuxGetPropertyDataContext
:
511 return ProcSELinuxGetPropertyContext(client
, dataKey
);
512 case X_SELinuxListProperties
:
513 return ProcSELinuxListProperties(client
);
514 case X_SELinuxSetSelectionCreateContext
:
515 return ProcSELinuxSetCreateContext(client
, CTX_SEL
);
516 case X_SELinuxGetSelectionCreateContext
:
517 return ProcSELinuxGetCreateContext(client
, CTX_SEL
);
518 case X_SELinuxSetSelectionUseContext
:
519 return ProcSELinuxSetCreateContext(client
, USE_SEL
);
520 case X_SELinuxGetSelectionUseContext
:
521 return ProcSELinuxGetCreateContext(client
, USE_SEL
);
522 case X_SELinuxGetSelectionContext
:
523 return ProcSELinuxGetSelectionContext(client
, objectKey
);
524 case X_SELinuxGetSelectionDataContext
:
525 return ProcSELinuxGetSelectionContext(client
, dataKey
);
526 case X_SELinuxListSelections
:
527 return ProcSELinuxListSelections(client
);
528 case X_SELinuxGetClientContext
:
529 return ProcSELinuxGetClientContext(client
);
536 SProcSELinuxQueryVersion(ClientPtr client
)
538 return ProcSELinuxQueryVersion(client
);
542 SProcSELinuxSetCreateContext(ClientPtr client
, unsigned offset
)
544 REQUEST(SELinuxSetCreateContextReq
);
546 REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq
);
547 swapl(&stuff
->context_len
);
548 return ProcSELinuxSetCreateContext(client
, offset
);
552 SProcSELinuxSetDeviceContext(ClientPtr client
)
554 REQUEST(SELinuxSetContextReq
);
556 REQUEST_AT_LEAST_SIZE(SELinuxSetContextReq
);
558 swapl(&stuff
->context_len
);
559 return ProcSELinuxSetDeviceContext(client
);
563 SProcSELinuxGetDeviceContext(ClientPtr client
)
565 REQUEST(SELinuxGetContextReq
);
567 REQUEST_SIZE_MATCH(SELinuxGetContextReq
);
569 return ProcSELinuxGetDeviceContext(client
);
573 SProcSELinuxGetDrawableContext(ClientPtr client
)
575 REQUEST(SELinuxGetContextReq
);
577 REQUEST_SIZE_MATCH(SELinuxGetContextReq
);
579 return ProcSELinuxGetDrawableContext(client
);
583 SProcSELinuxGetPropertyContext(ClientPtr client
, void *privKey
)
585 REQUEST(SELinuxGetPropertyContextReq
);
587 REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq
);
588 swapl(&stuff
->window
);
589 swapl(&stuff
->property
);
590 return ProcSELinuxGetPropertyContext(client
, privKey
);
594 SProcSELinuxGetSelectionContext(ClientPtr client
, void *privKey
)
596 REQUEST(SELinuxGetContextReq
);
598 REQUEST_SIZE_MATCH(SELinuxGetContextReq
);
600 return ProcSELinuxGetSelectionContext(client
, privKey
);
604 SProcSELinuxListProperties(ClientPtr client
)
606 REQUEST(SELinuxGetContextReq
);
608 REQUEST_SIZE_MATCH(SELinuxGetContextReq
);
610 return ProcSELinuxListProperties(client
);
614 SProcSELinuxGetClientContext(ClientPtr client
)
616 REQUEST(SELinuxGetContextReq
);
618 REQUEST_SIZE_MATCH(SELinuxGetContextReq
);
620 return ProcSELinuxGetClientContext(client
);
624 SProcSELinuxDispatch(ClientPtr client
)
628 swaps(&stuff
->length
);
630 switch (stuff
->data
) {
631 case X_SELinuxQueryVersion
:
632 return SProcSELinuxQueryVersion(client
);
633 case X_SELinuxSetDeviceCreateContext
:
634 return SProcSELinuxSetCreateContext(client
, CTX_DEV
);
635 case X_SELinuxGetDeviceCreateContext
:
636 return ProcSELinuxGetCreateContext(client
, CTX_DEV
);
637 case X_SELinuxSetDeviceContext
:
638 return SProcSELinuxSetDeviceContext(client
);
639 case X_SELinuxGetDeviceContext
:
640 return SProcSELinuxGetDeviceContext(client
);
641 case X_SELinuxSetDrawableCreateContext
:
642 return SProcSELinuxSetCreateContext(client
, CTX_WIN
);
643 case X_SELinuxGetDrawableCreateContext
:
644 return ProcSELinuxGetCreateContext(client
, CTX_WIN
);
645 case X_SELinuxGetDrawableContext
:
646 return SProcSELinuxGetDrawableContext(client
);
647 case X_SELinuxSetPropertyCreateContext
:
648 return SProcSELinuxSetCreateContext(client
, CTX_PRP
);
649 case X_SELinuxGetPropertyCreateContext
:
650 return ProcSELinuxGetCreateContext(client
, CTX_PRP
);
651 case X_SELinuxSetPropertyUseContext
:
652 return SProcSELinuxSetCreateContext(client
, USE_PRP
);
653 case X_SELinuxGetPropertyUseContext
:
654 return ProcSELinuxGetCreateContext(client
, USE_PRP
);
655 case X_SELinuxGetPropertyContext
:
656 return SProcSELinuxGetPropertyContext(client
, objectKey
);
657 case X_SELinuxGetPropertyDataContext
:
658 return SProcSELinuxGetPropertyContext(client
, dataKey
);
659 case X_SELinuxListProperties
:
660 return SProcSELinuxListProperties(client
);
661 case X_SELinuxSetSelectionCreateContext
:
662 return SProcSELinuxSetCreateContext(client
, CTX_SEL
);
663 case X_SELinuxGetSelectionCreateContext
:
664 return ProcSELinuxGetCreateContext(client
, CTX_SEL
);
665 case X_SELinuxSetSelectionUseContext
:
666 return SProcSELinuxSetCreateContext(client
, USE_SEL
);
667 case X_SELinuxGetSelectionUseContext
:
668 return ProcSELinuxGetCreateContext(client
, USE_SEL
);
669 case X_SELinuxGetSelectionContext
:
670 return SProcSELinuxGetSelectionContext(client
, objectKey
);
671 case X_SELinuxGetSelectionDataContext
:
672 return SProcSELinuxGetSelectionContext(client
, dataKey
);
673 case X_SELinuxListSelections
:
674 return ProcSELinuxListSelections(client
);
675 case X_SELinuxGetClientContext
:
676 return SProcSELinuxGetClientContext(client
);
683 * Extension Setup / Teardown
687 SELinuxResetProc(ExtensionEntry
* extEntry
)
694 SELinuxExtensionInit(void)
696 /* Check SELinux mode on system, configuration file, and boolean */
697 if (!is_selinux_enabled()) {
698 LogMessage(X_INFO
, "SELinux: Disabled on system\n");
701 if (selinuxEnforcingState
== SELINUX_MODE_DISABLED
) {
702 LogMessage(X_INFO
, "SELinux: Disabled in configuration file\n");
705 if (!security_get_boolean_active("xserver_object_manager")) {
706 LogMessage(X_INFO
, "SELinux: Disabled by boolean\n");
710 /* Set up XACE hooks */
714 /* Add extension to server */
715 AddExtension(SELINUX_EXTENSION_NAME
, SELinuxNumberEvents
,
716 SELinuxNumberErrors
, ProcSELinuxDispatch
,
717 SProcSELinuxDispatch
, SELinuxResetProc
, StandardMinorOpcode
);