1 /************************************************************
2 
3 Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
4 
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
9 Software.
10 
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.
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 "extinit.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 
39 typedef 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  * Extension Dispatch
49  */
50 
51 static security_context_t
SELinuxCopyContext(char * ptr,unsigned len)52 SELinuxCopyContext(char *ptr, unsigned len)
53 {
54     security_context_t copy = malloc(len + 1);
55 
56     if (!copy)
57         return NULL;
58     strncpy(copy, ptr, len);
59     copy[len] = '\0';
60     return copy;
61 }
62 
63 static int
ProcSELinuxQueryVersion(ClientPtr client)64 ProcSELinuxQueryVersion(ClientPtr client)
65 {
66     SELinuxQueryVersionReply rep = {
67         .type = X_Reply,
68         .sequenceNumber = client->sequence,
69         .length = 0,
70         .server_major = SELINUX_MAJOR_VERSION,
71         .server_minor = SELINUX_MINOR_VERSION
72     };
73     if (client->swapped) {
74         swaps(&rep.sequenceNumber);
75         swapl(&rep.length);
76         swaps(&rep.server_major);
77         swaps(&rep.server_minor);
78     }
79     WriteToClient(client, sizeof(rep), &rep);
80     return Success;
81 }
82 
83 static int
SELinuxSendContextReply(ClientPtr client,security_id_t sid)84 SELinuxSendContextReply(ClientPtr client, security_id_t sid)
85 {
86     SELinuxGetContextReply rep;
87     security_context_t ctx = NULL;
88     int len = 0;
89 
90     if (sid) {
91         if (avc_sid_to_context_raw(sid, &ctx) < 0)
92             return BadValue;
93         len = strlen(ctx) + 1;
94     }
95 
96     rep = (SELinuxGetContextReply) {
97         .type = X_Reply,
98         .sequenceNumber = client->sequence,
99         .length = bytes_to_int32(len),
100         .context_len = len
101     };
102 
103     if (client->swapped) {
104         swapl(&rep.length);
105         swaps(&rep.sequenceNumber);
106         swapl(&rep.context_len);
107     }
108 
109     WriteToClient(client, sizeof(SELinuxGetContextReply), &rep);
110     WriteToClient(client, len, ctx);
111     freecon(ctx);
112     return Success;
113 }
114 
115 static int
ProcSELinuxSetCreateContext(ClientPtr client,unsigned offset)116 ProcSELinuxSetCreateContext(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 
148 static int
ProcSELinuxGetCreateContext(ClientPtr client,unsigned offset)149 ProcSELinuxGetCreateContext(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 
165 static int
ProcSELinuxSetDeviceContext(ClientPtr client)166 ProcSELinuxSetDeviceContext(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;
200  out:
201     free(ctx);
202     return rc;
203 }
204 
205 static int
ProcSELinuxGetDeviceContext(ClientPtr client)206 ProcSELinuxGetDeviceContext(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 
223 static int
ProcSELinuxGetDrawableContext(ClientPtr client)224 ProcSELinuxGetDrawableContext(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 
247 static int
ProcSELinuxGetPropertyContext(ClientPtr client,void * privKey)248 ProcSELinuxGetPropertyContext(ClientPtr client, void *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 
271 static int
ProcSELinuxGetSelectionContext(ClientPtr client,void * privKey)272 ProcSELinuxGetSelectionContext(ClientPtr client, void *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 
289 static int
ProcSELinuxGetClientContext(ClientPtr client)290 ProcSELinuxGetClientContext(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 
307 static int
SELinuxPopulateItem(SELinuxListItemRec * i,PrivateRec ** privPtr,CARD32 id,int * size)308 SELinuxPopulateItem(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 
327 static void
SELinuxFreeItems(SELinuxListItemRec * items,int count)328 SELinuxFreeItems(SELinuxListItemRec * items, int count)
329 {
330     int k;
331 
332     for (k = 0; k < count; k++) {
333         freecon(items[k].octx);
334         freecon(items[k].dctx);
335     }
336     free(items);
337 }
338 
339 static int
SELinuxSendItemsToClient(ClientPtr client,SELinuxListItemRec * items,int size,int count)340 SELinuxSendItemsToClient(ClientPtr client, SELinuxListItemRec * items,
341                          int size, int count)
342 {
343     int rc, k, pos = 0;
344     SELinuxListItemsReply rep;
345     CARD32 *buf;
346 
347     buf = calloc(size, sizeof(CARD32));
348     if (size && !buf) {
349         rc = BadAlloc;
350         goto out;
351     }
352 
353     /* Fill in the buffer */
354     for (k = 0; k < count; k++) {
355         buf[pos] = items[k].id;
356         if (client->swapped)
357             swapl(buf + pos);
358         pos++;
359 
360         buf[pos] = items[k].octx_len * 4;
361         if (client->swapped)
362             swapl(buf + pos);
363         pos++;
364 
365         buf[pos] = items[k].dctx_len * 4;
366         if (client->swapped)
367             swapl(buf + pos);
368         pos++;
369 
370         memcpy((char *) (buf + pos), items[k].octx, strlen(items[k].octx) + 1);
371         pos += items[k].octx_len;
372         memcpy((char *) (buf + pos), items[k].dctx, strlen(items[k].dctx) + 1);
373         pos += items[k].dctx_len;
374     }
375 
376     /* Send reply to client */
377     rep = (SELinuxListItemsReply) {
378         .type = X_Reply,
379         .sequenceNumber = client->sequence,
380         .length = size,
381         .count = count
382     };
383 
384     if (client->swapped) {
385         swapl(&rep.length);
386         swaps(&rep.sequenceNumber);
387         swapl(&rep.count);
388     }
389 
390     WriteToClient(client, sizeof(SELinuxListItemsReply), &rep);
391     WriteToClient(client, size * 4, buf);
392 
393     /* Free stuff and return */
394     rc = Success;
395     free(buf);
396  out:
397     SELinuxFreeItems(items, count);
398     return rc;
399 }
400 
401 static int
ProcSELinuxListProperties(ClientPtr client)402 ProcSELinuxListProperties(ClientPtr client)
403 {
404     WindowPtr pWin;
405     PropertyPtr pProp;
406     SELinuxListItemRec *items;
407     int rc, count, size, i;
408     CARD32 id;
409 
410     REQUEST(SELinuxGetContextReq);
411     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
412 
413     rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
414     if (rc != Success)
415         return rc;
416 
417     /* Count the number of properties and allocate items */
418     count = 0;
419     for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
420         count++;
421     items = calloc(count, sizeof(SELinuxListItemRec));
422     if (count && !items)
423         return BadAlloc;
424 
425     /* Fill in the items and calculate size */
426     i = 0;
427     size = 0;
428     for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
429         id = pProp->propertyName;
430         rc = SELinuxPopulateItem(items + i, &pProp->devPrivates, id, &size);
431         if (rc != Success) {
432             SELinuxFreeItems(items, count);
433             return rc;
434         }
435         i++;
436     }
437 
438     return SELinuxSendItemsToClient(client, items, size, count);
439 }
440 
441 static int
ProcSELinuxListSelections(ClientPtr client)442 ProcSELinuxListSelections(ClientPtr client)
443 {
444     Selection *pSel;
445     SELinuxListItemRec *items;
446     int rc, count, size, i;
447     CARD32 id;
448 
449     REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq);
450 
451     /* Count the number of selections and allocate items */
452     count = 0;
453     for (pSel = CurrentSelections; pSel; pSel = pSel->next)
454         count++;
455     items = calloc(count, sizeof(SELinuxListItemRec));
456     if (count && !items)
457         return BadAlloc;
458 
459     /* Fill in the items and calculate size */
460     i = 0;
461     size = 0;
462     for (pSel = CurrentSelections; pSel; pSel = pSel->next) {
463         id = pSel->selection;
464         rc = SELinuxPopulateItem(items + i, &pSel->devPrivates, id, &size);
465         if (rc != Success) {
466             SELinuxFreeItems(items, count);
467             return rc;
468         }
469         i++;
470     }
471 
472     return SELinuxSendItemsToClient(client, items, size, count);
473 }
474 
475 static int
ProcSELinuxDispatch(ClientPtr client)476 ProcSELinuxDispatch(ClientPtr client)
477 {
478     REQUEST(xReq);
479     switch (stuff->data) {
480     case X_SELinuxQueryVersion:
481         return ProcSELinuxQueryVersion(client);
482     case X_SELinuxSetDeviceCreateContext:
483         return ProcSELinuxSetCreateContext(client, CTX_DEV);
484     case X_SELinuxGetDeviceCreateContext:
485         return ProcSELinuxGetCreateContext(client, CTX_DEV);
486     case X_SELinuxSetDeviceContext:
487         return ProcSELinuxSetDeviceContext(client);
488     case X_SELinuxGetDeviceContext:
489         return ProcSELinuxGetDeviceContext(client);
490     case X_SELinuxSetDrawableCreateContext:
491         return ProcSELinuxSetCreateContext(client, CTX_WIN);
492     case X_SELinuxGetDrawableCreateContext:
493         return ProcSELinuxGetCreateContext(client, CTX_WIN);
494     case X_SELinuxGetDrawableContext:
495         return ProcSELinuxGetDrawableContext(client);
496     case X_SELinuxSetPropertyCreateContext:
497         return ProcSELinuxSetCreateContext(client, CTX_PRP);
498     case X_SELinuxGetPropertyCreateContext:
499         return ProcSELinuxGetCreateContext(client, CTX_PRP);
500     case X_SELinuxSetPropertyUseContext:
501         return ProcSELinuxSetCreateContext(client, USE_PRP);
502     case X_SELinuxGetPropertyUseContext:
503         return ProcSELinuxGetCreateContext(client, USE_PRP);
504     case X_SELinuxGetPropertyContext:
505         return ProcSELinuxGetPropertyContext(client, objectKey);
506     case X_SELinuxGetPropertyDataContext:
507         return ProcSELinuxGetPropertyContext(client, dataKey);
508     case X_SELinuxListProperties:
509         return ProcSELinuxListProperties(client);
510     case X_SELinuxSetSelectionCreateContext:
511         return ProcSELinuxSetCreateContext(client, CTX_SEL);
512     case X_SELinuxGetSelectionCreateContext:
513         return ProcSELinuxGetCreateContext(client, CTX_SEL);
514     case X_SELinuxSetSelectionUseContext:
515         return ProcSELinuxSetCreateContext(client, USE_SEL);
516     case X_SELinuxGetSelectionUseContext:
517         return ProcSELinuxGetCreateContext(client, USE_SEL);
518     case X_SELinuxGetSelectionContext:
519         return ProcSELinuxGetSelectionContext(client, objectKey);
520     case X_SELinuxGetSelectionDataContext:
521         return ProcSELinuxGetSelectionContext(client, dataKey);
522     case X_SELinuxListSelections:
523         return ProcSELinuxListSelections(client);
524     case X_SELinuxGetClientContext:
525         return ProcSELinuxGetClientContext(client);
526     default:
527         return BadRequest;
528     }
529 }
530 
531 static int _X_COLD
SProcSELinuxQueryVersion(ClientPtr client)532 SProcSELinuxQueryVersion(ClientPtr client)
533 {
534     return ProcSELinuxQueryVersion(client);
535 }
536 
537 static int _X_COLD
SProcSELinuxSetCreateContext(ClientPtr client,unsigned offset)538 SProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
539 {
540     REQUEST(SELinuxSetCreateContextReq);
541 
542     REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq);
543     swapl(&stuff->context_len);
544     return ProcSELinuxSetCreateContext(client, offset);
545 }
546 
547 static int _X_COLD
SProcSELinuxSetDeviceContext(ClientPtr client)548 SProcSELinuxSetDeviceContext(ClientPtr client)
549 {
550     REQUEST(SELinuxSetContextReq);
551 
552     REQUEST_AT_LEAST_SIZE(SELinuxSetContextReq);
553     swapl(&stuff->id);
554     swapl(&stuff->context_len);
555     return ProcSELinuxSetDeviceContext(client);
556 }
557 
558 static int _X_COLD
SProcSELinuxGetDeviceContext(ClientPtr client)559 SProcSELinuxGetDeviceContext(ClientPtr client)
560 {
561     REQUEST(SELinuxGetContextReq);
562 
563     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
564     swapl(&stuff->id);
565     return ProcSELinuxGetDeviceContext(client);
566 }
567 
568 static int _X_COLD
SProcSELinuxGetDrawableContext(ClientPtr client)569 SProcSELinuxGetDrawableContext(ClientPtr client)
570 {
571     REQUEST(SELinuxGetContextReq);
572 
573     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
574     swapl(&stuff->id);
575     return ProcSELinuxGetDrawableContext(client);
576 }
577 
578 static int _X_COLD
SProcSELinuxGetPropertyContext(ClientPtr client,void * privKey)579 SProcSELinuxGetPropertyContext(ClientPtr client, void *privKey)
580 {
581     REQUEST(SELinuxGetPropertyContextReq);
582 
583     REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq);
584     swapl(&stuff->window);
585     swapl(&stuff->property);
586     return ProcSELinuxGetPropertyContext(client, privKey);
587 }
588 
589 static int _X_COLD
SProcSELinuxGetSelectionContext(ClientPtr client,void * privKey)590 SProcSELinuxGetSelectionContext(ClientPtr client, void *privKey)
591 {
592     REQUEST(SELinuxGetContextReq);
593 
594     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
595     swapl(&stuff->id);
596     return ProcSELinuxGetSelectionContext(client, privKey);
597 }
598 
599 static int _X_COLD
SProcSELinuxListProperties(ClientPtr client)600 SProcSELinuxListProperties(ClientPtr client)
601 {
602     REQUEST(SELinuxGetContextReq);
603 
604     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
605     swapl(&stuff->id);
606     return ProcSELinuxListProperties(client);
607 }
608 
609 static int _X_COLD
SProcSELinuxGetClientContext(ClientPtr client)610 SProcSELinuxGetClientContext(ClientPtr client)
611 {
612     REQUEST(SELinuxGetContextReq);
613 
614     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
615     swapl(&stuff->id);
616     return ProcSELinuxGetClientContext(client);
617 }
618 
619 static int _X_COLD
SProcSELinuxDispatch(ClientPtr client)620 SProcSELinuxDispatch(ClientPtr client)
621 {
622     REQUEST(xReq);
623 
624     swaps(&stuff->length);
625 
626     switch (stuff->data) {
627     case X_SELinuxQueryVersion:
628         return SProcSELinuxQueryVersion(client);
629     case X_SELinuxSetDeviceCreateContext:
630         return SProcSELinuxSetCreateContext(client, CTX_DEV);
631     case X_SELinuxGetDeviceCreateContext:
632         return ProcSELinuxGetCreateContext(client, CTX_DEV);
633     case X_SELinuxSetDeviceContext:
634         return SProcSELinuxSetDeviceContext(client);
635     case X_SELinuxGetDeviceContext:
636         return SProcSELinuxGetDeviceContext(client);
637     case X_SELinuxSetDrawableCreateContext:
638         return SProcSELinuxSetCreateContext(client, CTX_WIN);
639     case X_SELinuxGetDrawableCreateContext:
640         return ProcSELinuxGetCreateContext(client, CTX_WIN);
641     case X_SELinuxGetDrawableContext:
642         return SProcSELinuxGetDrawableContext(client);
643     case X_SELinuxSetPropertyCreateContext:
644         return SProcSELinuxSetCreateContext(client, CTX_PRP);
645     case X_SELinuxGetPropertyCreateContext:
646         return ProcSELinuxGetCreateContext(client, CTX_PRP);
647     case X_SELinuxSetPropertyUseContext:
648         return SProcSELinuxSetCreateContext(client, USE_PRP);
649     case X_SELinuxGetPropertyUseContext:
650         return ProcSELinuxGetCreateContext(client, USE_PRP);
651     case X_SELinuxGetPropertyContext:
652         return SProcSELinuxGetPropertyContext(client, objectKey);
653     case X_SELinuxGetPropertyDataContext:
654         return SProcSELinuxGetPropertyContext(client, dataKey);
655     case X_SELinuxListProperties:
656         return SProcSELinuxListProperties(client);
657     case X_SELinuxSetSelectionCreateContext:
658         return SProcSELinuxSetCreateContext(client, CTX_SEL);
659     case X_SELinuxGetSelectionCreateContext:
660         return ProcSELinuxGetCreateContext(client, CTX_SEL);
661     case X_SELinuxSetSelectionUseContext:
662         return SProcSELinuxSetCreateContext(client, USE_SEL);
663     case X_SELinuxGetSelectionUseContext:
664         return ProcSELinuxGetCreateContext(client, USE_SEL);
665     case X_SELinuxGetSelectionContext:
666         return SProcSELinuxGetSelectionContext(client, objectKey);
667     case X_SELinuxGetSelectionDataContext:
668         return SProcSELinuxGetSelectionContext(client, dataKey);
669     case X_SELinuxListSelections:
670         return ProcSELinuxListSelections(client);
671     case X_SELinuxGetClientContext:
672         return SProcSELinuxGetClientContext(client);
673     default:
674         return BadRequest;
675     }
676 }
677 
678 /*
679  * Extension Setup / Teardown
680  */
681 
682 static void
SELinuxResetProc(ExtensionEntry * extEntry)683 SELinuxResetProc(ExtensionEntry * extEntry)
684 {
685     SELinuxFlaskReset();
686     SELinuxLabelReset();
687 }
688 
689 void
SELinuxExtensionInit(void)690 SELinuxExtensionInit(void)
691 {
692     ExtensionEntry *extEntry;
693 
694     /* Check SELinux mode on system, configuration file, and boolean */
695     if (!is_selinux_enabled()) {
696         LogMessage(X_INFO, "SELinux: Disabled on system\n");
697         return;
698     }
699     if (selinuxEnforcingState == SELINUX_MODE_DISABLED) {
700         LogMessage(X_INFO, "SELinux: Disabled in configuration file\n");
701         return;
702     }
703     if (!security_get_boolean_active("xserver_object_manager")) {
704         LogMessage(X_INFO, "SELinux: Disabled by boolean\n");
705         return;
706     }
707 
708     /* Set up XACE hooks */
709     SELinuxLabelInit();
710     SELinuxFlaskInit();
711 
712     /* Add extension to server */
713     extEntry = AddExtension(SELINUX_EXTENSION_NAME,
714                             SELinuxNumberEvents, SELinuxNumberErrors,
715                             ProcSELinuxDispatch, SProcSELinuxDispatch,
716                             SELinuxResetProc, StandardMinorOpcode);
717 }
718