1/************************************************************
2
3Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7this permission notice appear in supporting documentation.  This permission
8notice shall be included in all copies or substantial portions of the
9Software.
10
11THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
14AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
15AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
18********************************************************/
19
20#ifdef HAVE_DIX_CONFIG_H
21#include <dix-config.h>
22#endif
23
24#include "selection.h"
25#include "inputstr.h"
26#include "windowstr.h"
27#include "propertyst.h"
28#include "extnsionst.h"
29#include "modinit.h"
30#include "xselinuxint.h"
31
32#define CTX_DEV offsetof(SELinuxSubjectRec, dev_create_sid)
33#define CTX_WIN offsetof(SELinuxSubjectRec, win_create_sid)
34#define CTX_PRP offsetof(SELinuxSubjectRec, prp_create_sid)
35#define CTX_SEL offsetof(SELinuxSubjectRec, sel_create_sid)
36#define USE_PRP offsetof(SELinuxSubjectRec, prp_use_sid)
37#define USE_SEL offsetof(SELinuxSubjectRec, sel_use_sid)
38
39typedef struct {
40    security_context_t octx;
41    security_context_t dctx;
42    CARD32 octx_len;
43    CARD32 dctx_len;
44    CARD32 id;
45} SELinuxListItemRec;
46
47
48/*
49 * Extension Dispatch
50 */
51
52static security_context_t
53SELinuxCopyContext(char *ptr, unsigned len)
54{
55    security_context_t copy = malloc(len + 1);
56    if (!copy)
57	return NULL;
58    strncpy(copy, ptr, len);
59    copy[len] = '\0';
60    return copy;
61}
62
63static int
64ProcSELinuxQueryVersion(ClientPtr client)
65{
66    SELinuxQueryVersionReply rep;
67
68    rep.type = X_Reply;
69    rep.length = 0;
70    rep.sequenceNumber = client->sequence;
71    rep.server_major = SELINUX_MAJOR_VERSION;
72    rep.server_minor = SELINUX_MINOR_VERSION;
73    if (client->swapped) {
74	int n;
75	swaps(&rep.sequenceNumber, n);
76	swapl(&rep.length, n);
77	swaps(&rep.server_major, n);
78	swaps(&rep.server_minor, n);
79    }
80    WriteToClient(client, sizeof(rep), (char *)&rep);
81    return Success;
82}
83
84static int
85SELinuxSendContextReply(ClientPtr client, security_id_t sid)
86{
87    SELinuxGetContextReply rep;
88    security_context_t ctx = NULL;
89    int len = 0;
90
91    if (sid) {
92	if (avc_sid_to_context_raw(sid, &ctx) < 0)
93	    return BadValue;
94	len = strlen(ctx) + 1;
95    }
96
97    rep.type = X_Reply;
98    rep.length = bytes_to_int32(len);
99    rep.sequenceNumber = client->sequence;
100    rep.context_len = len;
101
102    if (client->swapped) {
103	int n;
104	swapl(&rep.length, n);
105	swaps(&rep.sequenceNumber, n);
106	swapl(&rep.context_len, n);
107    }
108
109    WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep);
110    WriteToClient(client, len, ctx);
111    freecon(ctx);
112    return Success;
113}
114
115static int
116ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
117{
118    PrivateRec **privPtr = &client->devPrivates;
119    security_id_t *pSid;
120    security_context_t ctx = NULL;
121    char *ptr;
122    int rc;
123
124    REQUEST(SELinuxSetCreateContextReq);
125    REQUEST_FIXED_SIZE(SELinuxSetCreateContextReq, stuff->context_len);
126
127    if (stuff->context_len > 0) {
128	ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len);
129	if (!ctx)
130	    return BadAlloc;
131    }
132
133    ptr = dixLookupPrivate(privPtr, subjectKey);
134    pSid = (security_id_t *)(ptr + offset);
135    *pSid = NULL;
136
137    rc = Success;
138    if (stuff->context_len > 0) {
139	if (security_check_context_raw(ctx) < 0 ||
140	    avc_context_to_sid_raw(ctx, pSid) < 0)
141	    rc = BadValue;
142    }
143
144    free(ctx);
145    return rc;
146}
147
148static int
149ProcSELinuxGetCreateContext(ClientPtr client, unsigned offset)
150{
151    security_id_t *pSid;
152    char *ptr;
153
154    REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq);
155
156    if (offset == CTX_DEV)
157	ptr = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
158    else
159	ptr = dixLookupPrivate(&client->devPrivates, subjectKey);
160
161    pSid = (security_id_t *)(ptr + offset);
162    return SELinuxSendContextReply(client, *pSid);
163}
164
165static int
166ProcSELinuxSetDeviceContext(ClientPtr client)
167{
168    security_context_t ctx;
169    security_id_t sid;
170    DeviceIntPtr dev;
171    SELinuxSubjectRec *subj;
172    SELinuxObjectRec *obj;
173    int rc;
174
175    REQUEST(SELinuxSetContextReq);
176    REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len);
177
178    if (stuff->context_len < 1)
179	return BadLength;
180    ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len);
181    if (!ctx)
182	return BadAlloc;
183
184    rc = dixLookupDevice(&dev, stuff->id, client, DixManageAccess);
185    if (rc != Success)
186	goto out;
187
188    if (security_check_context_raw(ctx) < 0 ||
189	avc_context_to_sid_raw(ctx, &sid) < 0) {
190	rc = BadValue;
191	goto out;
192    }
193
194    subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
195    subj->sid = sid;
196    obj = dixLookupPrivate(&dev->devPrivates, objectKey);
197    obj->sid = sid;
198
199    rc = Success;
200out:
201    free(ctx);
202    return rc;
203}
204
205static int
206ProcSELinuxGetDeviceContext(ClientPtr client)
207{
208    DeviceIntPtr dev;
209    SELinuxSubjectRec *subj;
210    int rc;
211
212    REQUEST(SELinuxGetContextReq);
213    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
214
215    rc = dixLookupDevice(&dev, stuff->id, client, DixGetAttrAccess);
216    if (rc != Success)
217	return rc;
218
219    subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
220    return SELinuxSendContextReply(client, subj->sid);
221}
222
223static int
224ProcSELinuxGetDrawableContext(ClientPtr client)
225{
226    DrawablePtr pDraw;
227    PrivateRec **privatePtr;
228    SELinuxObjectRec *obj;
229    int rc;
230
231    REQUEST(SELinuxGetContextReq);
232    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
233
234    rc = dixLookupDrawable(&pDraw, stuff->id, client, 0, DixGetAttrAccess);
235    if (rc != Success)
236	return rc;
237
238    if (pDraw->type == DRAWABLE_PIXMAP)
239	privatePtr = &((PixmapPtr)pDraw)->devPrivates;
240    else
241	privatePtr = &((WindowPtr)pDraw)->devPrivates;
242
243    obj = dixLookupPrivate(privatePtr, objectKey);
244    return SELinuxSendContextReply(client, obj->sid);
245}
246
247static int
248ProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey)
249{
250    WindowPtr pWin;
251    PropertyPtr pProp;
252    SELinuxObjectRec *obj;
253    int rc;
254
255    REQUEST(SELinuxGetPropertyContextReq);
256    REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq);
257
258    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetPropAccess);
259    if (rc != Success)
260	return rc;
261
262    rc = dixLookupProperty(&pProp, pWin, stuff->property, client,
263			   DixGetAttrAccess);
264    if (rc != Success)
265	return rc;
266
267    obj = dixLookupPrivate(&pProp->devPrivates, privKey);
268    return SELinuxSendContextReply(client, obj->sid);
269}
270
271static int
272ProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey)
273{
274    Selection *pSel;
275    SELinuxObjectRec *obj;
276    int rc;
277
278    REQUEST(SELinuxGetContextReq);
279    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
280
281    rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess);
282    if (rc != Success)
283	return rc;
284
285    obj = dixLookupPrivate(&pSel->devPrivates, privKey);
286    return SELinuxSendContextReply(client, obj->sid);
287}
288
289static int
290ProcSELinuxGetClientContext(ClientPtr client)
291{
292    ClientPtr target;
293    SELinuxSubjectRec *subj;
294    int rc;
295
296    REQUEST(SELinuxGetContextReq);
297    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
298
299    rc = dixLookupClient(&target, stuff->id, client, DixGetAttrAccess);
300    if (rc != Success)
301	return rc;
302
303    subj = dixLookupPrivate(&target->devPrivates, subjectKey);
304    return SELinuxSendContextReply(client, subj->sid);
305}
306
307static int
308SELinuxPopulateItem(SELinuxListItemRec *i, PrivateRec **privPtr, CARD32 id,
309		    int *size)
310{
311    SELinuxObjectRec *obj = dixLookupPrivate(privPtr, objectKey);
312    SELinuxObjectRec *data = dixLookupPrivate(privPtr, dataKey);
313
314    if (avc_sid_to_context_raw(obj->sid, &i->octx) < 0)
315	return BadValue;
316    if (avc_sid_to_context_raw(data->sid, &i->dctx) < 0)
317	return BadValue;
318
319    i->id = id;
320    i->octx_len = bytes_to_int32(strlen(i->octx) + 1);
321    i->dctx_len = bytes_to_int32(strlen(i->dctx) + 1);
322
323    *size += i->octx_len + i->dctx_len + 3;
324    return Success;
325}
326
327static void
328SELinuxFreeItems(SELinuxListItemRec *items, int count)
329{
330    int k;
331    for (k = 0; k < count; k++) {
332	freecon(items[k].octx);
333	freecon(items[k].dctx);
334    }
335    free(items);
336}
337
338static int
339SELinuxSendItemsToClient(ClientPtr client, SELinuxListItemRec *items,
340			 int size, int count)
341{
342    int rc, k, n, pos = 0;
343    SELinuxListItemsReply rep;
344    CARD32 *buf;
345
346    buf = calloc(size, sizeof(CARD32));
347    if (size && !buf) {
348	rc = BadAlloc;
349	goto out;
350    }
351
352    /* Fill in the buffer */
353    for (k = 0; k < count; k++) {
354	buf[pos] = items[k].id;
355	if (client->swapped)
356	    swapl(buf + pos, n);
357	pos++;
358
359	buf[pos] = items[k].octx_len * 4;
360	if (client->swapped)
361	    swapl(buf + pos, n);
362	pos++;
363
364	buf[pos] = items[k].dctx_len * 4;
365	if (client->swapped)
366	    swapl(buf + pos, n);
367	pos++;
368
369	memcpy((char *)(buf + pos), items[k].octx, strlen(items[k].octx) + 1);
370	pos += items[k].octx_len;
371	memcpy((char *)(buf + pos), items[k].dctx, strlen(items[k].dctx) + 1);
372	pos += items[k].dctx_len;
373    }
374
375    /* Send reply to client */
376    rep.type = X_Reply;
377    rep.length = size;
378    rep.sequenceNumber = client->sequence;
379    rep.count = count;
380
381    if (client->swapped) {
382	swapl(&rep.length, n);
383	swaps(&rep.sequenceNumber, n);
384	swapl(&rep.count, n);
385    }
386
387    WriteToClient(client, sizeof(SELinuxListItemsReply), (char *)&rep);
388    WriteToClient(client, size * 4, (char *)buf);
389
390    /* Free stuff and return */
391    rc = Success;
392    free(buf);
393out:
394    SELinuxFreeItems(items, count);
395    return rc;
396}
397
398static int
399ProcSELinuxListProperties(ClientPtr client)
400{
401    WindowPtr pWin;
402    PropertyPtr pProp;
403    SELinuxListItemRec *items;
404    int rc, count, size, i;
405    CARD32 id;
406
407    REQUEST(SELinuxGetContextReq);
408    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
409
410    rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
411    if (rc != Success)
412	return rc;
413
414    /* Count the number of properties and allocate items */
415    count = 0;
416    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
417	count++;
418    items = calloc(count, sizeof(SELinuxListItemRec));
419    if (count && !items)
420	return BadAlloc;
421
422    /* Fill in the items and calculate size */
423    i = 0;
424    size = 0;
425    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
426	id = pProp->propertyName;
427	rc = SELinuxPopulateItem(items + i, &pProp->devPrivates, id, &size);
428	if (rc != Success) {
429	    SELinuxFreeItems(items, count);
430	    return rc;
431	}
432	i++;
433    }
434
435    return SELinuxSendItemsToClient(client, items, size, count);
436}
437
438static int
439ProcSELinuxListSelections(ClientPtr client)
440{
441    Selection *pSel;
442    SELinuxListItemRec *items;
443    int rc, count, size, i;
444    CARD32 id;
445
446    REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq);
447
448    /* Count the number of selections and allocate items */
449    count = 0;
450    for (pSel = CurrentSelections; pSel; pSel = pSel->next)
451	count++;
452    items = calloc(count, sizeof(SELinuxListItemRec));
453    if (count && !items)
454	return BadAlloc;
455
456    /* Fill in the items and calculate size */
457    i = 0;
458    size = 0;
459    for (pSel = CurrentSelections; pSel; pSel = pSel->next) {
460	id = pSel->selection;
461	rc = SELinuxPopulateItem(items + i, &pSel->devPrivates, id, &size);
462	if (rc != Success) {
463	    SELinuxFreeItems(items, count);
464	    return rc;
465	}
466	i++;
467    }
468
469    return SELinuxSendItemsToClient(client, items, size, count);
470}
471
472static int
473ProcSELinuxDispatch(ClientPtr client)
474{
475    REQUEST(xReq);
476    switch (stuff->data) {
477    case X_SELinuxQueryVersion:
478	return ProcSELinuxQueryVersion(client);
479    case X_SELinuxSetDeviceCreateContext:
480	return ProcSELinuxSetCreateContext(client, CTX_DEV);
481    case X_SELinuxGetDeviceCreateContext:
482	return ProcSELinuxGetCreateContext(client, CTX_DEV);
483    case X_SELinuxSetDeviceContext:
484	return ProcSELinuxSetDeviceContext(client);
485    case X_SELinuxGetDeviceContext:
486	return ProcSELinuxGetDeviceContext(client);
487    case X_SELinuxSetDrawableCreateContext:
488	return ProcSELinuxSetCreateContext(client, CTX_WIN);
489    case X_SELinuxGetDrawableCreateContext:
490	return ProcSELinuxGetCreateContext(client, CTX_WIN);
491    case X_SELinuxGetDrawableContext:
492	return ProcSELinuxGetDrawableContext(client);
493    case X_SELinuxSetPropertyCreateContext:
494	return ProcSELinuxSetCreateContext(client, CTX_PRP);
495    case X_SELinuxGetPropertyCreateContext:
496	return ProcSELinuxGetCreateContext(client, CTX_PRP);
497    case X_SELinuxSetPropertyUseContext:
498	return ProcSELinuxSetCreateContext(client, USE_PRP);
499    case X_SELinuxGetPropertyUseContext:
500	return ProcSELinuxGetCreateContext(client, USE_PRP);
501    case X_SELinuxGetPropertyContext:
502	return ProcSELinuxGetPropertyContext(client, objectKey);
503    case X_SELinuxGetPropertyDataContext:
504	return ProcSELinuxGetPropertyContext(client, dataKey);
505    case X_SELinuxListProperties:
506	return ProcSELinuxListProperties(client);
507    case X_SELinuxSetSelectionCreateContext:
508	return ProcSELinuxSetCreateContext(client, CTX_SEL);
509    case X_SELinuxGetSelectionCreateContext:
510	return ProcSELinuxGetCreateContext(client, CTX_SEL);
511    case X_SELinuxSetSelectionUseContext:
512	return ProcSELinuxSetCreateContext(client, USE_SEL);
513    case X_SELinuxGetSelectionUseContext:
514	return ProcSELinuxGetCreateContext(client, USE_SEL);
515    case X_SELinuxGetSelectionContext:
516	return ProcSELinuxGetSelectionContext(client, objectKey);
517    case X_SELinuxGetSelectionDataContext:
518	return ProcSELinuxGetSelectionContext(client, dataKey);
519    case X_SELinuxListSelections:
520	return ProcSELinuxListSelections(client);
521    case X_SELinuxGetClientContext:
522	return ProcSELinuxGetClientContext(client);
523    default:
524	return BadRequest;
525    }
526}
527
528static int
529SProcSELinuxQueryVersion(ClientPtr client)
530{
531    return ProcSELinuxQueryVersion(client);
532}
533
534static int
535SProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
536{
537    REQUEST(SELinuxSetCreateContextReq);
538    int n;
539
540    REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq);
541    swapl(&stuff->context_len, n);
542    return ProcSELinuxSetCreateContext(client, offset);
543}
544
545static int
546SProcSELinuxSetDeviceContext(ClientPtr client)
547{
548    REQUEST(SELinuxSetContextReq);
549    int n;
550
551    REQUEST_AT_LEAST_SIZE(SELinuxSetContextReq);
552    swapl(&stuff->id, n);
553    swapl(&stuff->context_len, n);
554    return ProcSELinuxSetDeviceContext(client);
555}
556
557static int
558SProcSELinuxGetDeviceContext(ClientPtr client)
559{
560    REQUEST(SELinuxGetContextReq);
561    int n;
562
563    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
564    swapl(&stuff->id, n);
565    return ProcSELinuxGetDeviceContext(client);
566}
567
568static int
569SProcSELinuxGetDrawableContext(ClientPtr client)
570{
571    REQUEST(SELinuxGetContextReq);
572    int n;
573
574    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
575    swapl(&stuff->id, n);
576    return ProcSELinuxGetDrawableContext(client);
577}
578
579static int
580SProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey)
581{
582    REQUEST(SELinuxGetPropertyContextReq);
583    int n;
584
585    REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq);
586    swapl(&stuff->window, n);
587    swapl(&stuff->property, n);
588    return ProcSELinuxGetPropertyContext(client, privKey);
589}
590
591static int
592SProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey)
593{
594    REQUEST(SELinuxGetContextReq);
595    int n;
596
597    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
598    swapl(&stuff->id, n);
599    return ProcSELinuxGetSelectionContext(client, privKey);
600}
601
602static int
603SProcSELinuxListProperties(ClientPtr client)
604{
605    REQUEST(SELinuxGetContextReq);
606    int n;
607
608    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
609    swapl(&stuff->id, n);
610    return ProcSELinuxListProperties(client);
611}
612
613static int
614SProcSELinuxGetClientContext(ClientPtr client)
615{
616    REQUEST(SELinuxGetContextReq);
617    int n;
618
619    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
620    swapl(&stuff->id, n);
621    return ProcSELinuxGetClientContext(client);
622}
623
624static int
625SProcSELinuxDispatch(ClientPtr client)
626{
627    REQUEST(xReq);
628    int n;
629
630    swaps(&stuff->length, n);
631
632    switch (stuff->data) {
633    case X_SELinuxQueryVersion:
634	return SProcSELinuxQueryVersion(client);
635    case X_SELinuxSetDeviceCreateContext:
636	return SProcSELinuxSetCreateContext(client, CTX_DEV);
637    case X_SELinuxGetDeviceCreateContext:
638	return ProcSELinuxGetCreateContext(client, CTX_DEV);
639    case X_SELinuxSetDeviceContext:
640	return SProcSELinuxSetDeviceContext(client);
641    case X_SELinuxGetDeviceContext:
642	return SProcSELinuxGetDeviceContext(client);
643    case X_SELinuxSetDrawableCreateContext:
644	return SProcSELinuxSetCreateContext(client, CTX_WIN);
645    case X_SELinuxGetDrawableCreateContext:
646	return ProcSELinuxGetCreateContext(client, CTX_WIN);
647    case X_SELinuxGetDrawableContext:
648	return SProcSELinuxGetDrawableContext(client);
649    case X_SELinuxSetPropertyCreateContext:
650	return SProcSELinuxSetCreateContext(client, CTX_PRP);
651    case X_SELinuxGetPropertyCreateContext:
652	return ProcSELinuxGetCreateContext(client, CTX_PRP);
653    case X_SELinuxSetPropertyUseContext:
654	return SProcSELinuxSetCreateContext(client, USE_PRP);
655    case X_SELinuxGetPropertyUseContext:
656	return ProcSELinuxGetCreateContext(client, USE_PRP);
657    case X_SELinuxGetPropertyContext:
658	return SProcSELinuxGetPropertyContext(client, objectKey);
659    case X_SELinuxGetPropertyDataContext:
660	return SProcSELinuxGetPropertyContext(client, dataKey);
661    case X_SELinuxListProperties:
662	return SProcSELinuxListProperties(client);
663    case X_SELinuxSetSelectionCreateContext:
664	return SProcSELinuxSetCreateContext(client, CTX_SEL);
665    case X_SELinuxGetSelectionCreateContext:
666	return ProcSELinuxGetCreateContext(client, CTX_SEL);
667    case X_SELinuxSetSelectionUseContext:
668	return SProcSELinuxSetCreateContext(client, USE_SEL);
669    case X_SELinuxGetSelectionUseContext:
670	return ProcSELinuxGetCreateContext(client, USE_SEL);
671    case X_SELinuxGetSelectionContext:
672	return SProcSELinuxGetSelectionContext(client, objectKey);
673    case X_SELinuxGetSelectionDataContext:
674	return SProcSELinuxGetSelectionContext(client, dataKey);
675    case X_SELinuxListSelections:
676	return ProcSELinuxListSelections(client);
677    case X_SELinuxGetClientContext:
678	return SProcSELinuxGetClientContext(client);
679    default:
680	return BadRequest;
681    }
682}
683
684
685/*
686 * Extension Setup / Teardown
687 */
688
689static void
690SELinuxResetProc(ExtensionEntry *extEntry)
691{
692    SELinuxFlaskReset();
693    SELinuxLabelReset();
694}
695
696void
697SELinuxExtensionInit(INITARGS)
698{
699    ExtensionEntry *extEntry;
700
701    /* Check SELinux mode on system, configuration file, and boolean */
702    if (!is_selinux_enabled()) {
703	LogMessage(X_INFO, "SELinux: Disabled on system\n");
704	return;
705    }
706    if (selinuxEnforcingState == SELINUX_MODE_DISABLED) {
707	LogMessage(X_INFO, "SELinux: Disabled in configuration file\n");
708	return;
709    }
710    if (!security_get_boolean_active("xserver_object_manager")) {
711	LogMessage(X_INFO, "SELinux: Disabled by boolean\n");
712        return;
713    }
714
715    /* Set up XACE hooks */
716    SELinuxLabelInit();
717    SELinuxFlaskInit();
718
719    /* Add extension to server */
720    extEntry = AddExtension(SELINUX_EXTENSION_NAME,
721			    SELinuxNumberEvents, SELinuxNumberErrors,
722			    ProcSELinuxDispatch, SProcSELinuxDispatch,
723			    SELinuxResetProc, StandardMinorOpcode);
724
725    AddExtensionAlias("Flask", extEntry);
726}
727