720 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			720 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
| /************************************************************
 | |
| 
 | |
| Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
 | |
| 
 | |
| Permission to use, copy, modify, distribute, and sell this software and its
 | |
| documentation for any purpose is hereby granted without fee, provided that
 | |
| this permission notice appear in supporting documentation.  This permission
 | |
| notice shall be included in all copies or substantial portions of the
 | |
| Software.
 | |
| 
 | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | |
| AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | |
| AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | |
| CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | |
| 
 | |
| ********************************************************/
 | |
| 
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include "selection.h"
 | |
| #include "inputstr.h"
 | |
| #include "windowstr.h"
 | |
| #include "propertyst.h"
 | |
| #include "extnsionst.h"
 | |
| #include "extinit.h"
 | |
| #include "xselinuxint.h"
 | |
| 
 | |
| #define CTX_DEV offsetof(SELinuxSubjectRec, dev_create_sid)
 | |
| #define CTX_WIN offsetof(SELinuxSubjectRec, win_create_sid)
 | |
| #define CTX_PRP offsetof(SELinuxSubjectRec, prp_create_sid)
 | |
| #define CTX_SEL offsetof(SELinuxSubjectRec, sel_create_sid)
 | |
| #define USE_PRP offsetof(SELinuxSubjectRec, prp_use_sid)
 | |
| #define USE_SEL offsetof(SELinuxSubjectRec, sel_use_sid)
 | |
| 
 | |
| typedef struct {
 | |
|     security_context_t octx;
 | |
|     security_context_t dctx;
 | |
|     CARD32 octx_len;
 | |
|     CARD32 dctx_len;
 | |
|     CARD32 id;
 | |
| } SELinuxListItemRec;
 | |
| 
 | |
| /*
 | |
|  * Extension Dispatch
 | |
|  */
 | |
| 
 | |
| static security_context_t
 | |
| SELinuxCopyContext(char *ptr, unsigned len)
 | |
| {
 | |
|     security_context_t copy = malloc(len + 1);
 | |
| 
 | |
|     if (!copy)
 | |
|         return NULL;
 | |
|     strncpy(copy, ptr, len);
 | |
|     copy[len] = '\0';
 | |
|     return copy;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcSELinuxQueryVersion(ClientPtr client)
 | |
| {
 | |
|     SELinuxQueryVersionReply rep = {
 | |
|         .type = X_Reply,
 | |
|         .sequenceNumber = client->sequence,
 | |
|         .length = 0,
 | |
|         .server_major = SELINUX_MAJOR_VERSION,
 | |
|         .server_minor = SELINUX_MINOR_VERSION
 | |
|     };
 | |
|     if (client->swapped) {
 | |
|         swaps(&rep.sequenceNumber);
 | |
|         swapl(&rep.length);
 | |
|         swaps(&rep.server_major);
 | |
|         swaps(&rep.server_minor);
 | |
|     }
 | |
|     WriteToClient(client, sizeof(rep), &rep);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static int
 | |
| SELinuxSendContextReply(ClientPtr client, security_id_t sid)
 | |
| {
 | |
|     SELinuxGetContextReply rep;
 | |
|     security_context_t ctx = NULL;
 | |
|     int len = 0;
 | |
| 
 | |
|     if (sid) {
 | |
|         if (avc_sid_to_context_raw(sid, &ctx) < 0)
 | |
|             return BadValue;
 | |
|         len = strlen(ctx) + 1;
 | |
|     }
 | |
| 
 | |
|     rep = (SELinuxGetContextReply) {
 | |
|         .type = X_Reply,
 | |
|         .sequenceNumber = client->sequence,
 | |
|         .length = bytes_to_int32(len),
 | |
|         .context_len = len
 | |
|     };
 | |
| 
 | |
|     if (client->swapped) {
 | |
|         swapl(&rep.length);
 | |
|         swaps(&rep.sequenceNumber);
 | |
|         swapl(&rep.context_len);
 | |
|     }
 | |
| 
 | |
|     WriteToClient(client, sizeof(SELinuxGetContextReply), &rep);
 | |
|     WriteToClient(client, len, ctx);
 | |
|     freecon(ctx);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
 | |
| {
 | |
|     PrivateRec **privPtr = &client->devPrivates;
 | |
|     security_id_t *pSid;
 | |
|     security_context_t ctx = NULL;
 | |
|     char *ptr;
 | |
|     int rc;
 | |
| 
 | |
|     REQUEST(SELinuxSetCreateContextReq);
 | |
|     REQUEST_FIXED_SIZE(SELinuxSetCreateContextReq, stuff->context_len);
 | |
| 
 | |
|     if (stuff->context_len > 0) {
 | |
|         ctx = SELinuxCopyContext((char *) (stuff + 1), stuff->context_len);
 | |
|         if (!ctx)
 | |
|             return BadAlloc;
 | |
|     }
 | |
| 
 | |
|     ptr = dixLookupPrivate(privPtr, subjectKey);
 | |
|     pSid = (security_id_t *) (ptr + offset);
 | |
|     *pSid = NULL;
 | |
| 
 | |
|     rc = Success;
 | |
|     if (stuff->context_len > 0) {
 | |
|         if (security_check_context_raw(ctx) < 0 ||
 | |
|             avc_context_to_sid_raw(ctx, pSid) < 0)
 | |
|             rc = BadValue;
 | |
|     }
 | |
| 
 | |
|     free(ctx);
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcSELinuxGetCreateContext(ClientPtr client, unsigned offset)
 | |
| {
 | |
|     security_id_t *pSid;
 | |
|     char *ptr;
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq);
 | |
| 
 | |
|     if (offset == CTX_DEV)
 | |
|         ptr = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
 | |
|     else
 | |
|         ptr = dixLookupPrivate(&client->devPrivates, subjectKey);
 | |
| 
 | |
|     pSid = (security_id_t *) (ptr + offset);
 | |
|     return SELinuxSendContextReply(client, *pSid);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcSELinuxSetDeviceContext(ClientPtr client)
 | |
| {
 | |
|     security_context_t ctx;
 | |
|     security_id_t sid;
 | |
|     DeviceIntPtr dev;
 | |
|     SELinuxSubjectRec *subj;
 | |
|     SELinuxObjectRec *obj;
 | |
|     int rc;
 | |
| 
 | |
|     REQUEST(SELinuxSetContextReq);
 | |
|     REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len);
 | |
| 
 | |
|     if (stuff->context_len < 1)
 | |
|         return BadLength;
 | |
|     ctx = SELinuxCopyContext((char *) (stuff + 1), stuff->context_len);
 | |
|     if (!ctx)
 | |
|         return BadAlloc;
 | |
| 
 | |
|     rc = dixLookupDevice(&dev, stuff->id, client, DixManageAccess);
 | |
|     if (rc != Success)
 | |
|         goto out;
 | |
| 
 | |
|     if (security_check_context_raw(ctx) < 0 ||
 | |
|         avc_context_to_sid_raw(ctx, &sid) < 0) {
 | |
|         rc = BadValue;
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
 | |
|     subj->sid = sid;
 | |
|     obj = dixLookupPrivate(&dev->devPrivates, objectKey);
 | |
|     obj->sid = sid;
 | |
| 
 | |
|     rc = Success;
 | |
|  out:
 | |
|     free(ctx);
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcSELinuxGetDeviceContext(ClientPtr client)
 | |
| {
 | |
|     DeviceIntPtr dev;
 | |
|     SELinuxSubjectRec *subj;
 | |
|     int rc;
 | |
| 
 | |
|     REQUEST(SELinuxGetContextReq);
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
 | |
| 
 | |
|     rc = dixLookupDevice(&dev, stuff->id, client, DixGetAttrAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
| 
 | |
|     subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
 | |
|     return SELinuxSendContextReply(client, subj->sid);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcSELinuxGetDrawableContext(ClientPtr client)
 | |
| {
 | |
|     DrawablePtr pDraw;
 | |
|     PrivateRec **privatePtr;
 | |
|     SELinuxObjectRec *obj;
 | |
|     int rc;
 | |
| 
 | |
|     REQUEST(SELinuxGetContextReq);
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
 | |
| 
 | |
|     rc = dixLookupDrawable(&pDraw, stuff->id, client, 0, DixGetAttrAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
| 
 | |
|     if (pDraw->type == DRAWABLE_PIXMAP)
 | |
|         privatePtr = &((PixmapPtr) pDraw)->devPrivates;
 | |
|     else
 | |
|         privatePtr = &((WindowPtr) pDraw)->devPrivates;
 | |
| 
 | |
|     obj = dixLookupPrivate(privatePtr, objectKey);
 | |
|     return SELinuxSendContextReply(client, obj->sid);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcSELinuxGetPropertyContext(ClientPtr client, void *privKey)
 | |
| {
 | |
|     WindowPtr pWin;
 | |
|     PropertyPtr pProp;
 | |
|     SELinuxObjectRec *obj;
 | |
|     int rc;
 | |
| 
 | |
|     REQUEST(SELinuxGetPropertyContextReq);
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq);
 | |
| 
 | |
|     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetPropAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
| 
 | |
|     rc = dixLookupProperty(&pProp, pWin, stuff->property, client,
 | |
|                            DixGetAttrAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
| 
 | |
|     obj = dixLookupPrivate(&pProp->devPrivates, privKey);
 | |
|     return SELinuxSendContextReply(client, obj->sid);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcSELinuxGetSelectionContext(ClientPtr client, void *privKey)
 | |
| {
 | |
|     Selection *pSel;
 | |
|     SELinuxObjectRec *obj;
 | |
|     int rc;
 | |
| 
 | |
|     REQUEST(SELinuxGetContextReq);
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
 | |
| 
 | |
|     rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
| 
 | |
|     obj = dixLookupPrivate(&pSel->devPrivates, privKey);
 | |
|     return SELinuxSendContextReply(client, obj->sid);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcSELinuxGetClientContext(ClientPtr client)
 | |
| {
 | |
|     ClientPtr target;
 | |
|     SELinuxSubjectRec *subj;
 | |
|     int rc;
 | |
| 
 | |
|     REQUEST(SELinuxGetContextReq);
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
 | |
| 
 | |
|     rc = dixLookupClient(&target, stuff->id, client, DixGetAttrAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
| 
 | |
|     subj = dixLookupPrivate(&target->devPrivates, subjectKey);
 | |
|     return SELinuxSendContextReply(client, subj->sid);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SELinuxPopulateItem(SELinuxListItemRec * i, PrivateRec ** privPtr, CARD32 id,
 | |
|                     int *size)
 | |
| {
 | |
|     SELinuxObjectRec *obj = dixLookupPrivate(privPtr, objectKey);
 | |
|     SELinuxObjectRec *data = dixLookupPrivate(privPtr, dataKey);
 | |
| 
 | |
|     if (avc_sid_to_context_raw(obj->sid, &i->octx) < 0)
 | |
|         return BadValue;
 | |
|     if (avc_sid_to_context_raw(data->sid, &i->dctx) < 0)
 | |
|         return BadValue;
 | |
| 
 | |
|     i->id = id;
 | |
|     i->octx_len = bytes_to_int32(strlen(i->octx) + 1);
 | |
|     i->dctx_len = bytes_to_int32(strlen(i->dctx) + 1);
 | |
| 
 | |
|     *size += i->octx_len + i->dctx_len + 3;
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static void
 | |
| SELinuxFreeItems(SELinuxListItemRec * items, int count)
 | |
| {
 | |
|     int k;
 | |
| 
 | |
|     for (k = 0; k < count; k++) {
 | |
|         freecon(items[k].octx);
 | |
|         freecon(items[k].dctx);
 | |
|     }
 | |
|     free(items);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SELinuxSendItemsToClient(ClientPtr client, SELinuxListItemRec * items,
 | |
|                          int size, int count)
 | |
| {
 | |
|     int rc, k, pos = 0;
 | |
|     SELinuxListItemsReply rep;
 | |
|     CARD32 *buf;
 | |
| 
 | |
|     buf = calloc(size, sizeof(CARD32));
 | |
|     if (size && !buf) {
 | |
|         rc = BadAlloc;
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     /* Fill in the buffer */
 | |
|     for (k = 0; k < count; k++) {
 | |
|         buf[pos] = items[k].id;
 | |
|         if (client->swapped)
 | |
|             swapl(buf + pos);
 | |
|         pos++;
 | |
| 
 | |
|         buf[pos] = items[k].octx_len * 4;
 | |
|         if (client->swapped)
 | |
|             swapl(buf + pos);
 | |
|         pos++;
 | |
| 
 | |
|         buf[pos] = items[k].dctx_len * 4;
 | |
|         if (client->swapped)
 | |
|             swapl(buf + pos);
 | |
|         pos++;
 | |
| 
 | |
|         memcpy((char *) (buf + pos), items[k].octx, strlen(items[k].octx) + 1);
 | |
|         pos += items[k].octx_len;
 | |
|         memcpy((char *) (buf + pos), items[k].dctx, strlen(items[k].dctx) + 1);
 | |
|         pos += items[k].dctx_len;
 | |
|     }
 | |
| 
 | |
|     /* Send reply to client */
 | |
|     rep = (SELinuxListItemsReply) {
 | |
|         .type = X_Reply,
 | |
|         .sequenceNumber = client->sequence,
 | |
|         .length = size,
 | |
|         .count = count
 | |
|     };
 | |
| 
 | |
|     if (client->swapped) {
 | |
|         swapl(&rep.length);
 | |
|         swaps(&rep.sequenceNumber);
 | |
|         swapl(&rep.count);
 | |
|     }
 | |
| 
 | |
|     WriteToClient(client, sizeof(SELinuxListItemsReply), &rep);
 | |
|     WriteToClient(client, size * 4, buf);
 | |
| 
 | |
|     /* Free stuff and return */
 | |
|     rc = Success;
 | |
|     free(buf);
 | |
|  out:
 | |
|     SELinuxFreeItems(items, count);
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcSELinuxListProperties(ClientPtr client)
 | |
| {
 | |
|     WindowPtr pWin;
 | |
|     PropertyPtr pProp;
 | |
|     SELinuxListItemRec *items;
 | |
|     int rc, count, size, i;
 | |
|     CARD32 id;
 | |
| 
 | |
|     REQUEST(SELinuxGetContextReq);
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
 | |
| 
 | |
|     rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
| 
 | |
|     /* Count the number of properties and allocate items */
 | |
|     count = 0;
 | |
|     for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
 | |
|         count++;
 | |
|     items = calloc(count, sizeof(SELinuxListItemRec));
 | |
|     if (count && !items)
 | |
|         return BadAlloc;
 | |
| 
 | |
|     /* Fill in the items and calculate size */
 | |
|     i = 0;
 | |
|     size = 0;
 | |
|     for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
 | |
|         id = pProp->propertyName;
 | |
|         rc = SELinuxPopulateItem(items + i, &pProp->devPrivates, id, &size);
 | |
|         if (rc != Success) {
 | |
|             SELinuxFreeItems(items, count);
 | |
|             return rc;
 | |
|         }
 | |
|         i++;
 | |
|     }
 | |
| 
 | |
|     return SELinuxSendItemsToClient(client, items, size, count);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcSELinuxListSelections(ClientPtr client)
 | |
| {
 | |
|     Selection *pSel;
 | |
|     SELinuxListItemRec *items;
 | |
|     int rc, count, size, i;
 | |
|     CARD32 id;
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq);
 | |
| 
 | |
|     /* Count the number of selections and allocate items */
 | |
|     count = 0;
 | |
|     for (pSel = CurrentSelections; pSel; pSel = pSel->next)
 | |
|         count++;
 | |
|     items = calloc(count, sizeof(SELinuxListItemRec));
 | |
|     if (count && !items)
 | |
|         return BadAlloc;
 | |
| 
 | |
|     /* Fill in the items and calculate size */
 | |
|     i = 0;
 | |
|     size = 0;
 | |
|     for (pSel = CurrentSelections; pSel; pSel = pSel->next) {
 | |
|         id = pSel->selection;
 | |
|         rc = SELinuxPopulateItem(items + i, &pSel->devPrivates, id, &size);
 | |
|         if (rc != Success) {
 | |
|             SELinuxFreeItems(items, count);
 | |
|             return rc;
 | |
|         }
 | |
|         i++;
 | |
|     }
 | |
| 
 | |
|     return SELinuxSendItemsToClient(client, items, size, count);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcSELinuxDispatch(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xReq);
 | |
|     switch (stuff->data) {
 | |
|     case X_SELinuxQueryVersion:
 | |
|         return ProcSELinuxQueryVersion(client);
 | |
|     case X_SELinuxSetDeviceCreateContext:
 | |
|         return ProcSELinuxSetCreateContext(client, CTX_DEV);
 | |
|     case X_SELinuxGetDeviceCreateContext:
 | |
|         return ProcSELinuxGetCreateContext(client, CTX_DEV);
 | |
|     case X_SELinuxSetDeviceContext:
 | |
|         return ProcSELinuxSetDeviceContext(client);
 | |
|     case X_SELinuxGetDeviceContext:
 | |
|         return ProcSELinuxGetDeviceContext(client);
 | |
|     case X_SELinuxSetDrawableCreateContext:
 | |
|         return ProcSELinuxSetCreateContext(client, CTX_WIN);
 | |
|     case X_SELinuxGetDrawableCreateContext:
 | |
|         return ProcSELinuxGetCreateContext(client, CTX_WIN);
 | |
|     case X_SELinuxGetDrawableContext:
 | |
|         return ProcSELinuxGetDrawableContext(client);
 | |
|     case X_SELinuxSetPropertyCreateContext:
 | |
|         return ProcSELinuxSetCreateContext(client, CTX_PRP);
 | |
|     case X_SELinuxGetPropertyCreateContext:
 | |
|         return ProcSELinuxGetCreateContext(client, CTX_PRP);
 | |
|     case X_SELinuxSetPropertyUseContext:
 | |
|         return ProcSELinuxSetCreateContext(client, USE_PRP);
 | |
|     case X_SELinuxGetPropertyUseContext:
 | |
|         return ProcSELinuxGetCreateContext(client, USE_PRP);
 | |
|     case X_SELinuxGetPropertyContext:
 | |
|         return ProcSELinuxGetPropertyContext(client, objectKey);
 | |
|     case X_SELinuxGetPropertyDataContext:
 | |
|         return ProcSELinuxGetPropertyContext(client, dataKey);
 | |
|     case X_SELinuxListProperties:
 | |
|         return ProcSELinuxListProperties(client);
 | |
|     case X_SELinuxSetSelectionCreateContext:
 | |
|         return ProcSELinuxSetCreateContext(client, CTX_SEL);
 | |
|     case X_SELinuxGetSelectionCreateContext:
 | |
|         return ProcSELinuxGetCreateContext(client, CTX_SEL);
 | |
|     case X_SELinuxSetSelectionUseContext:
 | |
|         return ProcSELinuxSetCreateContext(client, USE_SEL);
 | |
|     case X_SELinuxGetSelectionUseContext:
 | |
|         return ProcSELinuxGetCreateContext(client, USE_SEL);
 | |
|     case X_SELinuxGetSelectionContext:
 | |
|         return ProcSELinuxGetSelectionContext(client, objectKey);
 | |
|     case X_SELinuxGetSelectionDataContext:
 | |
|         return ProcSELinuxGetSelectionContext(client, dataKey);
 | |
|     case X_SELinuxListSelections:
 | |
|         return ProcSELinuxListSelections(client);
 | |
|     case X_SELinuxGetClientContext:
 | |
|         return ProcSELinuxGetClientContext(client);
 | |
|     default:
 | |
|         return BadRequest;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcSELinuxQueryVersion(ClientPtr client)
 | |
| {
 | |
|     return ProcSELinuxQueryVersion(client);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
 | |
| {
 | |
|     REQUEST(SELinuxSetCreateContextReq);
 | |
| 
 | |
|     REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq);
 | |
|     swapl(&stuff->context_len);
 | |
|     return ProcSELinuxSetCreateContext(client, offset);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcSELinuxSetDeviceContext(ClientPtr client)
 | |
| {
 | |
|     REQUEST(SELinuxSetContextReq);
 | |
| 
 | |
|     REQUEST_AT_LEAST_SIZE(SELinuxSetContextReq);
 | |
|     swapl(&stuff->id);
 | |
|     swapl(&stuff->context_len);
 | |
|     return ProcSELinuxSetDeviceContext(client);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcSELinuxGetDeviceContext(ClientPtr client)
 | |
| {
 | |
|     REQUEST(SELinuxGetContextReq);
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
 | |
|     swapl(&stuff->id);
 | |
|     return ProcSELinuxGetDeviceContext(client);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcSELinuxGetDrawableContext(ClientPtr client)
 | |
| {
 | |
|     REQUEST(SELinuxGetContextReq);
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
 | |
|     swapl(&stuff->id);
 | |
|     return ProcSELinuxGetDrawableContext(client);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcSELinuxGetPropertyContext(ClientPtr client, void *privKey)
 | |
| {
 | |
|     REQUEST(SELinuxGetPropertyContextReq);
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq);
 | |
|     swapl(&stuff->window);
 | |
|     swapl(&stuff->property);
 | |
|     return ProcSELinuxGetPropertyContext(client, privKey);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcSELinuxGetSelectionContext(ClientPtr client, void *privKey)
 | |
| {
 | |
|     REQUEST(SELinuxGetContextReq);
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
 | |
|     swapl(&stuff->id);
 | |
|     return ProcSELinuxGetSelectionContext(client, privKey);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcSELinuxListProperties(ClientPtr client)
 | |
| {
 | |
|     REQUEST(SELinuxGetContextReq);
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
 | |
|     swapl(&stuff->id);
 | |
|     return ProcSELinuxListProperties(client);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcSELinuxGetClientContext(ClientPtr client)
 | |
| {
 | |
|     REQUEST(SELinuxGetContextReq);
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
 | |
|     swapl(&stuff->id);
 | |
|     return ProcSELinuxGetClientContext(client);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcSELinuxDispatch(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xReq);
 | |
| 
 | |
|     swaps(&stuff->length);
 | |
| 
 | |
|     switch (stuff->data) {
 | |
|     case X_SELinuxQueryVersion:
 | |
|         return SProcSELinuxQueryVersion(client);
 | |
|     case X_SELinuxSetDeviceCreateContext:
 | |
|         return SProcSELinuxSetCreateContext(client, CTX_DEV);
 | |
|     case X_SELinuxGetDeviceCreateContext:
 | |
|         return ProcSELinuxGetCreateContext(client, CTX_DEV);
 | |
|     case X_SELinuxSetDeviceContext:
 | |
|         return SProcSELinuxSetDeviceContext(client);
 | |
|     case X_SELinuxGetDeviceContext:
 | |
|         return SProcSELinuxGetDeviceContext(client);
 | |
|     case X_SELinuxSetDrawableCreateContext:
 | |
|         return SProcSELinuxSetCreateContext(client, CTX_WIN);
 | |
|     case X_SELinuxGetDrawableCreateContext:
 | |
|         return ProcSELinuxGetCreateContext(client, CTX_WIN);
 | |
|     case X_SELinuxGetDrawableContext:
 | |
|         return SProcSELinuxGetDrawableContext(client);
 | |
|     case X_SELinuxSetPropertyCreateContext:
 | |
|         return SProcSELinuxSetCreateContext(client, CTX_PRP);
 | |
|     case X_SELinuxGetPropertyCreateContext:
 | |
|         return ProcSELinuxGetCreateContext(client, CTX_PRP);
 | |
|     case X_SELinuxSetPropertyUseContext:
 | |
|         return SProcSELinuxSetCreateContext(client, USE_PRP);
 | |
|     case X_SELinuxGetPropertyUseContext:
 | |
|         return ProcSELinuxGetCreateContext(client, USE_PRP);
 | |
|     case X_SELinuxGetPropertyContext:
 | |
|         return SProcSELinuxGetPropertyContext(client, objectKey);
 | |
|     case X_SELinuxGetPropertyDataContext:
 | |
|         return SProcSELinuxGetPropertyContext(client, dataKey);
 | |
|     case X_SELinuxListProperties:
 | |
|         return SProcSELinuxListProperties(client);
 | |
|     case X_SELinuxSetSelectionCreateContext:
 | |
|         return SProcSELinuxSetCreateContext(client, CTX_SEL);
 | |
|     case X_SELinuxGetSelectionCreateContext:
 | |
|         return ProcSELinuxGetCreateContext(client, CTX_SEL);
 | |
|     case X_SELinuxSetSelectionUseContext:
 | |
|         return SProcSELinuxSetCreateContext(client, USE_SEL);
 | |
|     case X_SELinuxGetSelectionUseContext:
 | |
|         return ProcSELinuxGetCreateContext(client, USE_SEL);
 | |
|     case X_SELinuxGetSelectionContext:
 | |
|         return SProcSELinuxGetSelectionContext(client, objectKey);
 | |
|     case X_SELinuxGetSelectionDataContext:
 | |
|         return SProcSELinuxGetSelectionContext(client, dataKey);
 | |
|     case X_SELinuxListSelections:
 | |
|         return ProcSELinuxListSelections(client);
 | |
|     case X_SELinuxGetClientContext:
 | |
|         return SProcSELinuxGetClientContext(client);
 | |
|     default:
 | |
|         return BadRequest;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Extension Setup / Teardown
 | |
|  */
 | |
| 
 | |
| static void
 | |
| SELinuxResetProc(ExtensionEntry * extEntry)
 | |
| {
 | |
|     SELinuxFlaskReset();
 | |
|     SELinuxLabelReset();
 | |
| }
 | |
| 
 | |
| void
 | |
| SELinuxExtensionInit(void)
 | |
| {
 | |
|     ExtensionEntry *extEntry;
 | |
| 
 | |
|     /* Check SELinux mode on system, configuration file, and boolean */
 | |
|     if (!is_selinux_enabled()) {
 | |
|         LogMessage(X_INFO, "SELinux: Disabled on system\n");
 | |
|         return;
 | |
|     }
 | |
|     if (selinuxEnforcingState == SELINUX_MODE_DISABLED) {
 | |
|         LogMessage(X_INFO, "SELinux: Disabled in configuration file\n");
 | |
|         return;
 | |
|     }
 | |
|     if (!security_get_boolean_active("xserver_object_manager")) {
 | |
|         LogMessage(X_INFO, "SELinux: Disabled by boolean\n");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* Set up XACE hooks */
 | |
|     SELinuxLabelInit();
 | |
|     SELinuxFlaskInit();
 | |
| 
 | |
|     /* Add extension to server */
 | |
|     extEntry = AddExtension(SELINUX_EXTENSION_NAME,
 | |
|                             SELinuxNumberEvents, SELinuxNumberErrors,
 | |
|                             ProcSELinuxDispatch, SProcSELinuxDispatch,
 | |
|                             SELinuxResetProc, StandardMinorOpcode);
 | |
| 
 | |
|     AddExtensionAlias("Flask", extEntry);
 | |
| }
 |