diff options
Diffstat (limited to 'Xext/xselinux.c')
-rw-r--r-- | Xext/xselinux.c | 1117 |
1 files changed, 749 insertions, 368 deletions
diff --git a/Xext/xselinux.c b/Xext/xselinux.c index 98e1ec563..1e3b4d66c 100644 --- a/Xext/xselinux.c +++ b/Xext/xselinux.c @@ -37,6 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <libaudit.h> #include <X11/Xatom.h> +#include "globals.h" #include "resource.h" #include "privates.h" #include "registry.h" @@ -60,31 +61,36 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Globals */ -/* private state record */ +/* private state keys */ static DevPrivateKey subjectKey = &subjectKey; static DevPrivateKey objectKey = &objectKey; +static DevPrivateKey dataKey = &dataKey; -/* This is what we store for security state */ +/* subject state (clients and devices only) */ typedef struct { security_id_t sid; + security_id_t dev_create_sid; + security_id_t win_create_sid; + security_id_t sel_create_sid; + security_id_t prp_create_sid; + security_id_t sel_use_sid; + security_id_t prp_use_sid; struct avc_entry_ref aeref; char *command; int privileged; } SELinuxSubjectRec; +/* object state */ typedef struct { security_id_t sid; int poly; } SELinuxObjectRec; -/* selection manager */ +/* selection and property atom cache */ typedef struct { - Atom selection; - security_id_t sid; -} SELinuxSelectionRec; - -static ClientPtr securityManager; -static Window securityWindow; + SELinuxObjectRec prp; + SELinuxObjectRec sel; +} SELinuxAtomRec; /* audit file descriptor */ static int audit_fd; @@ -123,9 +129,9 @@ static unsigned numKnownTypes; static security_id_t *knownEvents; static unsigned numKnownEvents; -/* Array of selection SID structures */ -static SELinuxSelectionRec *knownSelections; -static unsigned numKnownSelections; +/* Array of property and selection SID structures */ +static SELinuxAtomRec *knownAtoms; +static unsigned numKnownAtoms; /* dynamically allocated security classes and permissions */ static struct security_class_mapping map[] = { @@ -134,8 +140,8 @@ static struct security_class_mapping map[] = { { "x_gc", { "", "", "destroy", "create", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "use", NULL }}, { "x_font", { "", "", "destroy", "create", "getattr", "", "", "", "", "", "", "", "add_glyph", "remove_glyph", "", "", "", "", "", "", "", "", "", "", "use", NULL }}, { "x_colormap", { "read", "write", "destroy", "create", "getattr", "", "", "", "", "", "", "", "add_color", "remove_color", "", "", "", "", "", "", "install", "uninstall", "", "", "use", NULL }}, - { "x_property", { "read", "write", "destroy", "create", "getattr", "setattr", NULL }}, - { "x_selection", { "read", "", "", "", "getattr", "setattr", NULL }}, + { "x_property", { "read", "write", "destroy", "create", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "write", NULL }}, + { "x_selection", { "read", "", "", "setattr", "getattr", "setattr", NULL }}, { "x_cursor", { "read", "write", "destroy", "create", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "use", NULL }}, { "x_client", { "", "", "destroy", "", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "manage", NULL }}, { "x_device", { "read", "write", "", "", "getattr", "setattr", "", "", "", "getfocus", "setfocus", "", "", "", "", "", "", "grab", "freeze", "force_cursor", "", "", "", "", "use", "manage", "", "bell", NULL }}, @@ -147,6 +153,12 @@ static struct security_class_mapping map[] = { { NULL } }; +/* x_resource "read" bits from the list above */ +#define SELinuxReadMask (DixReadAccess|DixGetAttrAccess|DixListPropAccess| \ + DixGetPropAccess|DixGetFocusAccess|DixListAccess| \ + DixShowAccess|DixBlendAccess|DixReceiveAccess| \ + DixUseAccess|DixDebugAccess) + /* forward declarations */ static void SELinuxScreen(CallbackListPtr *, pointer, pointer); @@ -159,48 +171,164 @@ static pointer truep = (pointer)1; */ /* - * Looks up the SID corresponding to the given selection atom + * Looks up a name in the selection or property mappings */ static int -SELinuxSelectionToSID(Atom selection, SELinuxObjectRec *sid_return) +SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec *obj, int map, int polymap) { - const char *name; - unsigned i, size; + const char *name = NameForAtom(atom); + security_context_t ctx; + int rc = Success; - for (i = 0; i < numKnownSelections; i++) - if (knownSelections[i].selection == selection) { - sid_return->sid = knownSelections[i].sid; - return Success; - } + obj->poly = 1; - /* Need to increase size of array */ - i = numKnownSelections; - size = (i + 1) * sizeof(SELinuxSelectionRec); - knownSelections = xrealloc(knownSelections, size); - if (!knownSelections) - return BadAlloc; - knownSelections[i].selection = selection; + /* Look in the mappings of names to contexts */ + if (selabel_lookup(label_hnd, &ctx, name, map) == 0) { + obj->poly = 0; + } else if (errno != ENOENT) { + ErrorF("SELinux: a property label lookup failed!\n"); + return BadValue; + } else if (selabel_lookup(label_hnd, &ctx, name, polymap) < 0) { + ErrorF("SELinux: a property label lookup failed!\n"); + return BadValue; + } - /* Look in the mappings of selection names to contexts */ - name = NameForAtom(selection); - if (name) { - security_context_t con; - security_id_t sid; + /* Get a SID for context */ + if (avc_context_to_sid(ctx, &obj->sid) < 0) { + ErrorF("SELinux: a context_to_SID call failed!\n"); + rc = BadAlloc; + } - if (selabel_lookup(label_hnd, &con, name, SELABEL_X_SELN) < 0) { - ErrorF("SELinux: a selection label lookup failed!\n"); - return BadValue; - } - /* Get a SID for context */ - if (avc_context_to_sid(con, &sid) < 0) { - ErrorF("SELinux: a context_to_SID call failed!\n"); + freecon(ctx); + return rc; +} + +/* + * Looks up the SID corresponding to the given property or selection atom + */ +static int +SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn) +{ + SELinuxObjectRec *obj; + int rc, map, polymap; + + if (atom >= numKnownAtoms) { + /* Need to increase size of atoms array */ + unsigned size = sizeof(SELinuxAtomRec); + knownAtoms = xrealloc(knownAtoms, (atom + 1) * size); + if (!knownAtoms) return BadAlloc; + memset(knownAtoms + numKnownAtoms, 0, + (atom - numKnownAtoms + 1) * size); + numKnownAtoms = atom + 1; + } + + if (prop) { + obj = &knownAtoms[atom].prp; + map = SELABEL_X_PROP; + polymap = SELABEL_X_POLYPROP; + } else { + obj = &knownAtoms[atom].sel; + map = SELABEL_X_SELN; + polymap = SELABEL_X_POLYSELN; + } + + if (!obj->sid) { + rc = SELinuxAtomToSIDLookup(atom, obj, map, polymap); + if (rc != Success) + goto out; + } + + *obj_rtn = obj; + rc = Success; +out: + return rc; +} + +/* + * Looks up a SID for a selection/subject pair + */ +static int +SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec *subj, + security_id_t *sid_rtn, int *poly_rtn) +{ + int rc; + SELinuxObjectRec *obj; + security_id_t tsid; + + /* Get the default context and polyinstantiation bit */ + rc = SELinuxAtomToSID(selection, 0, &obj); + if (rc != Success) + return rc; + + /* Check for an override context next */ + if (subj->sel_use_sid) { + sidget(tsid = subj->sel_use_sid); + goto out; + } + + sidget(tsid = obj->sid); + + /* Polyinstantiate if necessary to obtain the final SID */ + if (obj->poly) { + sidput(tsid); + if (avc_compute_member(subj->sid, obj->sid, + SECCLASS_X_SELECTION, &tsid) < 0) { + ErrorF("SELinux: a compute_member call failed!\n"); + return BadValue; } - freecon(con); - knownSelections[i].sid = sid_return->sid = sid; - } else - knownSelections[i].sid = sid_return->sid = unlabeled_sid; + } +out: + *sid_rtn = tsid; + if (poly_rtn) + *poly_rtn = obj->poly; + return Success; +} + +/* + * Looks up a SID for a property/subject pair + */ +static int +SELinuxPropertyToSID(Atom property, SELinuxSubjectRec *subj, + security_id_t *sid_rtn, int *poly_rtn) +{ + int rc; + SELinuxObjectRec *obj; + security_id_t tsid, tsid2; + + /* Get the default context and polyinstantiation bit */ + rc = SELinuxAtomToSID(property, 1, &obj); + if (rc != Success) + return rc; + + /* Check for an override context next */ + if (subj->prp_use_sid) { + sidget(tsid = subj->prp_use_sid); + goto out; + } + /* Perform a transition */ + if (avc_compute_create(subj->sid, obj->sid, + SECCLASS_X_PROPERTY, &tsid) < 0) { + ErrorF("SELinux: a compute_create call failed!\n"); + return BadValue; + } + + /* Polyinstantiate if necessary to obtain the final SID */ + if (obj->poly) { + tsid2 = tsid; + if (avc_compute_member(subj->sid, tsid2, + SECCLASS_X_PROPERTY, &tsid) < 0) { + ErrorF("SELinux: a compute_member call failed!\n"); + sidput(tsid2); + return BadValue; + } + sidput(tsid2); + } +out: + *sid_rtn = tsid; + if (poly_rtn) + *poly_rtn = obj->poly; return Success; } @@ -383,8 +511,7 @@ finish: FatalError("SELinux: client %d: context_to_sid(%s) failed\n", client->index, ctx); - sidget(subj->sid); - obj->sid = subj->sid; + sidget(obj->sid = subj->sid); freecon(ctx); } @@ -415,8 +542,7 @@ SELinuxLabelInitial(void) if (avc_context_to_sid(ctx, &subj->sid) < 0) FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx); - sidget(subj->sid); - obj->sid = subj->sid; + sidget(obj->sid = subj->sid); freecon(ctx); srec.client = serverClient; @@ -434,6 +560,44 @@ SELinuxLabelInitial(void) } } +/* + * Labels new resource objects. + */ +static int +SELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj, + SELinuxObjectRec *obj, security_class_t class) +{ + int offset; + security_id_t tsid; + + /* Check for a create context */ + if (rec->rtype == RT_WINDOW && subj->win_create_sid) { + sidget(obj->sid = subj->win_create_sid); + return Success; + } + + if (rec->parent) + offset = dixLookupPrivateOffset(rec->ptype); + + if (rec->parent && offset >= 0) { + /* Use the SID of the parent object in the labeling operation */ + PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset); + SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey); + tsid = pobj->sid; + } else { + /* Use the SID of the subject */ + tsid = subj->sid; + } + + /* Perform a transition to obtain the final SID */ + if (avc_compute_create(subj->sid, tsid, class, &obj->sid) < 0) { + ErrorF("SELinux: a compute_create call failed!\n"); + return BadValue; + } + + return Success; +} + /* * Libselinux Callbacks @@ -497,6 +661,7 @@ SELinuxLog(int type, const char *fmt, ...) vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap); rc = audit_log_user_avc_message(audit_fd, aut, buf, NULL, NULL, NULL, 0); va_end(ap); + LogMessageVerb(X_WARNING, 0, "%s", buf); return 0; } @@ -524,11 +689,26 @@ SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata) sidput(dsubj->sid); sidput(obj->sid); - /* Label the device directly with the process SID */ - sidget(subj->sid); - obj->sid = subj->sid; - sidget(subj->sid); - dsubj->sid = subj->sid; + if (subj->dev_create_sid) { + /* Label the device with the create context */ + sidget(obj->sid = subj->dev_create_sid); + sidget(dsubj->sid = subj->dev_create_sid); + } else { + /* Label the device directly with the process SID */ + sidget(obj->sid = subj->sid); + sidget(dsubj->sid = subj->sid); + } + } + + /* XXX only check read permission on XQueryKeymap */ + /* This is to allow the numerous apps that call XQueryPointer to work */ + if (rec->access_mode & DixReadAccess) { + ClientPtr client = rec->client; + REQUEST(xReq); + if (stuff && stuff->reqType != X_QueryKeymap) { + rec->access_mode &= ~DixReadAccess; + rec->access_mode |= DixGetAttrAccess; + } } rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DEVICE, rec->access_mode, @@ -673,55 +853,129 @@ SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) } static void +SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceSelectionAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj, *data; + Selection *pSel = *rec->ppSel; + Atom name = pSel->selection; + Mask access_mode = rec->access_mode; + SELinuxAuditRec auditdata = { .client = rec->client, .selection = name }; + security_id_t tsid; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&pSel->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + if (access_mode & DixCreateAccess) { + sidput(obj->sid); + rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly); + if (rc != Success) + obj->sid = unlabeled_sid; + access_mode = DixSetAttrAccess; + } + /* If this is a polyinstantiated object, find the right instance */ + else if (obj->poly) { + rc = SELinuxSelectionToSID(name, subj, &tsid, NULL); + if (rc != Success) { + rec->status = rc; + return; + } + while (pSel->selection != name || obj->sid != tsid) { + if ((pSel = pSel->next) == NULL) + break; + obj = dixLookupPrivate(&pSel->devPrivates, objectKey); + } + sidput(tsid); + + if (pSel) + *rec->ppSel = pSel; + else { + rec->status = BadMatch; + return; + } + } + + /* Perform the security check */ + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; + + /* Label the content (advisory only) */ + if (access_mode & DixSetAttrAccess) { + data = dixLookupPrivate(&pSel->devPrivates, dataKey); + sidput(data->sid); + if (subj->sel_create_sid) + sidget(data->sid = subj->sel_create_sid); + else + sidget(data->sid = obj->sid); + } +} + +static void SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) { XacePropertyAccessRec *rec = calldata; SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; + SELinuxObjectRec *obj, *data; + PropertyPtr pProp = *rec->ppProp; + Atom name = pProp->propertyName; + SELinuxAuditRec auditdata = { .client = rec->client, .property = name }; + security_id_t tsid; int rc; subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->pProp->devPrivates, objectKey); + obj = dixLookupPrivate(&pProp->devPrivates, objectKey); /* If this is a new object that needs labeling, do it now */ if (rec->access_mode & DixCreateAccess) { - const char *name = NameForAtom(rec->pProp->propertyName); - security_context_t con; - security_id_t sid; - - /* Look in the mappings of property names to contexts */ - if (selabel_lookup(label_hnd, &con, name, SELABEL_X_PROP) < 0) { - ErrorF("SELinux: a property label lookup failed!\n"); - rec->status = BadValue; + sidput(obj->sid); + rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly); + if (rc != Success) { + rec->status = rc; return; } - /* Get a SID for context */ - if (avc_context_to_sid(con, &sid) < 0) { - ErrorF("SELinux: a context_to_SID call failed!\n"); - rec->status = BadAlloc; + } + /* If this is a polyinstantiated object, find the right instance */ + else if (obj->poly) { + rc = SELinuxPropertyToSID(name, subj, &tsid, NULL); + if (rc != Success) { + rec->status = rc; return; } + while (pProp->propertyName != name || obj->sid != tsid) { + if ((pProp = pProp->next) == NULL) + break; + obj = dixLookupPrivate(&pProp->devPrivates, objectKey); + } + sidput(tsid); - sidput(obj->sid); - - /* Perform a transition to obtain the final SID */ - if (avc_compute_create(subj->sid, sid, SECCLASS_X_PROPERTY, - &obj->sid) < 0) { - ErrorF("SELinux: a SID transition call failed!\n"); - freecon(con); - rec->status = BadValue; + if (pProp) + *rec->ppProp = pProp; + else { + rec->status = BadMatch; return; } - freecon(con); } /* Perform the security check */ - auditdata.property = rec->pProp->propertyName; rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode, &auditdata); if (rc != Success) rec->status = rc; + + /* Label the content (advisory only) */ + if (rec->access_mode & DixWriteAccess) { + data = dixLookupPrivate(&pProp->devPrivates, dataKey); + sidput(data->sid); + if (subj->prp_create_sid) + sidget(data->sid = subj->prp_create_sid); + else + sidget(data->sid = obj->sid); + } } static void @@ -729,14 +983,14 @@ SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata) { XaceResourceAccessRec *rec = calldata; SELinuxSubjectRec *subj; - SELinuxObjectRec *obj, *sobj, *pobj; + SELinuxObjectRec *obj; SELinuxAuditRec auditdata = { .client = rec->client }; + Mask access_mode = rec->access_mode; PrivateRec **privatePtr; security_class_t class; int rc, offset; subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - sobj = dixLookupPrivate(&rec->client->devPrivates, objectKey); /* Determine if the resource object has a devPrivates field */ offset = dixLookupPrivateOffset(rec->rtype); @@ -753,32 +1007,33 @@ SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata) } /* If this is a new object that needs labeling, do it now */ - if (rec->access_mode & DixCreateAccess && offset >= 0) { - if (rec->parent) - offset = dixLookupPrivateOffset(rec->ptype); - if (rec->parent && offset >= 0) - /* Use the SID of the parent object in the labeling operation */ - pobj = dixLookupPrivate(DEVPRIV_AT(rec->parent, offset), objectKey); - else - /* Use the SID of the subject */ - pobj = sobj; - - sidput(obj->sid); - - /* Perform a transition to obtain the final SID */ - if (avc_compute_create(subj->sid, pobj->sid, class, &obj->sid) < 0) { - ErrorF("SELinux: a compute_create call failed!\n"); - rec->status = BadValue; + if (access_mode & DixCreateAccess && offset >= 0) { + rc = SELinuxLabelResource(rec, subj, obj, class); + if (rc != Success) { + rec->status = rc; return; } } + /* Collapse generic resource permissions down to read/write */ + if (class == SECCLASS_X_RESOURCE) { + access_mode = !!(rec->access_mode & SELinuxReadMask); /* rd */ + access_mode |= !!(rec->access_mode & ~SELinuxReadMask) << 1; /* wr */ + } + /* Perform the security check */ auditdata.restype = rec->rtype; auditdata.id = rec->id; - rc = SELinuxDoCheck(subj, obj, class, rec->access_mode, &auditdata); + rc = SELinuxDoCheck(subj, obj, class, access_mode, &auditdata); if (rc != Success) rec->status = rc; + + /* Perform the background none check on windows */ + if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW) { + rc = SELinuxDoCheck(subj, obj, class, DixBlendAccess, &auditdata); + if (rc != Success) + ((WindowPtr)rec->res)->forcedBG = TRUE; + } } static void @@ -851,30 +1106,6 @@ SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata) rec->status = rc; } -static void -SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceSelectionAccessRec *rec = (XaceSelectionAccessRec *)calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec sel_sid; - SELinuxAuditRec auditdata = { .client = rec->client }; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - - rc = SELinuxSelectionToSID(rec->name, &sel_sid); - if (rc != Success) { - rec->status = rc; - return; - } - - auditdata.selection = rec->name; - rc = SELinuxDoCheck(subj, &sel_sid, SECCLASS_X_SELECTION, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; -} - /* * DIX Callbacks @@ -890,14 +1121,6 @@ SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxLabelClient(pci->client); break; - case ClientStateRetained: - case ClientStateGone: - if (pci->client == securityManager) { - securityManager = NULL; - securityWindow = 0; - } - break; - default: break; } @@ -948,20 +1171,6 @@ SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata) FatalError("SELinux: Unexpected unlabeled window found\n"); } -static void -SELinuxSelectionState(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - SelectionInfoRec *rec = calldata; - - switch (rec->kind) { - case SelectionSetOwner: - case SelectionGetOwner: - case SelectionConvertSelection: - default: - break; - } -} - /* * DevPrivates Callbacks @@ -987,8 +1196,13 @@ SELinuxSubjectFree(CallbackListPtr *pcbl, pointer unused, pointer calldata) xfree(subj->command); - if (avc_active) + if (avc_active) { sidput(subj->sid); + sidput(subj->dev_create_sid); + sidput(subj->win_create_sid); + sidput(subj->sel_create_sid); + sidput(subj->prp_create_sid); + } } static void @@ -1016,6 +1230,21 @@ SELinuxObjectFree(CallbackListPtr *pcbl, pointer unused, pointer calldata) * Extension Dispatch */ +#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; + static int ProcSELinuxQueryVersion(ClientPtr client) { @@ -1038,65 +1267,101 @@ ProcSELinuxQueryVersion(ClientPtr client) } static int -ProcSELinuxSetSecurityManager(ClientPtr client) +SELinuxSendContextReply(ClientPtr client, security_id_t sid) { - WindowPtr pWin; - int rc; - - REQUEST(SELinuxSetSecurityManagerReq); - REQUEST_SIZE_MATCH(SELinuxSetSecurityManagerReq); - - if (stuff->window == None) { - securityManager = NULL; - securityWindow = None; - } else { - rc = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW, - client, DixGetAttrAccess); - if (rc != Success) - return rc; + SELinuxGetContextReply rep; + security_context_t ctx = NULL; + int len = 0; - securityManager = client; - securityWindow = stuff->window; + if (sid) { + if (avc_sid_to_context(sid, &ctx) < 0) + return BadValue; + len = strlen(ctx) + 1; } - return Success; -} - -static int -ProcSELinuxGetSecurityManager(ClientPtr client) -{ - SELinuxGetSecurityManagerReply rep; - rep.type = X_Reply; - rep.length = 0; + rep.length = (len + 3) >> 2; rep.sequenceNumber = client->sequence; - rep.window = securityWindow; + rep.context_len = len; + if (client->swapped) { int n; - swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); - swapl(&rep.window, n); + swaps(&rep.sequenceNumber, n); + swapl(&rep.context_len, n); } - WriteToClient(client, sizeof(rep), (char *)&rep); - return (client->noClientException); + + WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep); + WriteToClient(client, len, ctx); + freecon(ctx); + return client->noClientException; } static int -ProcSELinuxSetDeviceCreateContext(ClientPtr client) +ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset) { + PrivateRec **privPtr = &client->devPrivates; + security_id_t *pSid; + security_context_t ctx; + char *ptr; + + REQUEST(SELinuxSetCreateContextReq); + REQUEST_FIXED_SIZE(SELinuxSetCreateContextReq, stuff->context_len); + + ctx = (char *)(stuff + 1); + if (stuff->context_len > 0 && ctx[stuff->context_len - 1]) + return BadLength; + + if (offset == CTX_DEV) { + /* Device create context currently requires manage permission */ + int rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess); + if (rc != Success) + return rc; + privPtr = &serverClient->devPrivates; + } + else if (offset == USE_SEL) { + /* Selection use context currently requires no selections owned */ + Selection *pSel; + for (pSel = CurrentSelections; pSel; pSel = pSel->next) + if (pSel->client == client) + return BadMatch; + } + + ptr = dixLookupPrivate(privPtr, subjectKey); + pSid = (security_id_t *)(ptr + offset); + sidput(*pSid); + *pSid = NULL; + + if (stuff->context_len > 0) { + if (security_check_context(ctx) < 0) + return BadValue; + if (avc_context_to_sid(ctx, pSid) < 0) + return BadValue; + } return Success; } static int -ProcSELinuxGetDeviceCreateContext(ClientPtr client) +ProcSELinuxGetCreateContext(ClientPtr client, unsigned offset) { - return Success; + 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) { - char *ctx; + security_context_t ctx; security_id_t sid; DeviceIntPtr dev; SELinuxSubjectRec *subj; @@ -1107,15 +1372,16 @@ ProcSELinuxSetDeviceContext(ClientPtr client) REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len); ctx = (char *)(stuff + 1); - if (ctx[stuff->context_len - 1]) + if (stuff->context_len < 1 || ctx[stuff->context_len - 1]) return BadLength; rc = dixLookupDevice(&dev, stuff->id, client, DixManageAccess); if (rc != Success) return rc; - rc = avc_context_to_sid(ctx, &sid); - if (rc != Success) + if (security_check_context(ctx) < 0) + return BadValue; + if (avc_context_to_sid(ctx, &sid) < 0) return BadValue; subj = dixLookupPrivate(&dev->devPrivates, subjectKey); @@ -1123,7 +1389,7 @@ ProcSELinuxSetDeviceContext(ClientPtr client) subj->sid = sid; obj = dixLookupPrivate(&dev->devPrivates, objectKey); sidput(obj->sid); - obj->sid = sid; + sidget(obj->sid = sid); return Success; } @@ -1131,10 +1397,8 @@ ProcSELinuxSetDeviceContext(ClientPtr client) static int ProcSELinuxGetDeviceContext(ClientPtr client) { - char *ctx; DeviceIntPtr dev; SELinuxSubjectRec *subj; - SELinuxGetContextReply rep; int rc; REQUEST(SELinuxGetContextReq); @@ -1145,48 +1409,33 @@ ProcSELinuxGetDeviceContext(ClientPtr client) return rc; subj = dixLookupPrivate(&dev->devPrivates, subjectKey); - rc = avc_sid_to_context(subj->sid, &ctx); - if (rc != Success) - return BadValue; - - rep.type = X_Reply; - rep.length = (strlen(ctx) + 4) >> 2; - rep.sequenceNumber = client->sequence; - rep.context_len = strlen(ctx) + 1; - - if (client->swapped) { - int n; - swapl(&rep.length, n); - swaps(&rep.sequenceNumber, n); - swaps(&rep.context_len, n); - } - - WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep); - WriteToClient(client, rep.context_len, ctx); - free(ctx); - return client->noClientException; + return SELinuxSendContextReply(client, subj->sid); } static int -ProcSELinuxSetPropertyCreateContext(ClientPtr client) +ProcSELinuxGetWindowContext(ClientPtr client) { - return Success; -} + WindowPtr pWin; + SELinuxObjectRec *obj; + int rc; -static int -ProcSELinuxGetPropertyCreateContext(ClientPtr client) -{ - return Success; + REQUEST(SELinuxGetContextReq); + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + + rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + obj = dixLookupPrivate(&pWin->devPrivates, objectKey); + return SELinuxSendContextReply(client, obj->sid); } static int -ProcSELinuxGetPropertyContext(ClientPtr client) +ProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey) { - char *ctx; WindowPtr pWin; PropertyPtr pProp; SELinuxObjectRec *obj; - SELinuxGetContextReply rep; int rc; REQUEST(SELinuxGetPropertyContextReq); @@ -1196,109 +1445,214 @@ ProcSELinuxGetPropertyContext(ClientPtr client) if (rc != Success) return rc; - pProp = wUserProps(pWin); - while (pProp) { - if (pProp->propertyName == stuff->property) - break; - pProp = pProp->next; - } - if (!pProp) - return BadValue; - - rc = XaceHookPropertyAccess(client, pWin, pProp, DixGetAttrAccess); + rc = dixLookupProperty(&pProp, pWin, stuff->property, client, + DixGetAttrAccess); if (rc != Success) return rc; - obj = dixLookupPrivate(&pProp->devPrivates, objectKey); - rc = avc_sid_to_context(obj->sid, &ctx); - if (rc != Success) - return BadValue; - - rep.type = X_Reply; - rep.length = (strlen(ctx) + 4) >> 2; - rep.sequenceNumber = client->sequence; - rep.context_len = strlen(ctx) + 1; - - if (client->swapped) { - int n; - swapl(&rep.length, n); - swaps(&rep.sequenceNumber, n); - swaps(&rep.context_len, n); - } - - WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep); - WriteToClient(client, rep.context_len, ctx); - free(ctx); - return client->noClientException; + obj = dixLookupPrivate(&pProp->devPrivates, privKey); + return SELinuxSendContextReply(client, obj->sid); } static int -ProcSELinuxSetWindowCreateContext(ClientPtr client) +ProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey) { - return Success; -} + Selection *pSel; + SELinuxObjectRec *obj; + int rc; -static int -ProcSELinuxGetWindowCreateContext(ClientPtr client) -{ - return Success; + 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 -ProcSELinuxGetWindowContext(ClientPtr client) +ProcSELinuxGetClientContext(ClientPtr client) { - char *ctx; - WindowPtr pWin; - SELinuxObjectRec *obj; - SELinuxGetContextReply rep; + ClientPtr target; + SELinuxSubjectRec *subj; int rc; REQUEST(SELinuxGetContextReq); REQUEST_SIZE_MATCH(SELinuxGetContextReq); - rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); + rc = dixLookupClient(&target, stuff->id, client, DixGetAttrAccess); if (rc != Success) return rc; - obj = dixLookupPrivate(&pWin->devPrivates, objectKey); - rc = avc_sid_to_context(obj->sid, &ctx); - if (rc != Success) + 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(obj->sid, &i->octx) < 0) return BadValue; + if (avc_sid_to_context(data->sid, &i->dctx) < 0) + return BadValue; + + i->id = id; + i->octx_len = (strlen(i->octx) + 4) >> 2; + i->dctx_len = (strlen(i->dctx) + 4) >> 2; + + *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); + } + xfree(items); +} + +static int +SELinuxSendItemsToClient(ClientPtr client, SELinuxListItemRec *items, + int size, int count) +{ + int rc, k, n, pos = 0; + SELinuxListItemsReply rep; + CARD32 *buf; + + buf = xcalloc(size, sizeof(CARD32)); + if (!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, n); + pos++; + + buf[pos] = items[k].octx_len * 4; + if (client->swapped) + swapl(buf + pos, n); + pos++; + + buf[pos] = items[k].dctx_len * 4; + if (client->swapped) + swapl(buf + pos, n); + 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.type = X_Reply; - rep.length = (strlen(ctx) + 4) >> 2; + rep.length = size; rep.sequenceNumber = client->sequence; - rep.context_len = strlen(ctx) + 1; + rep.count = count; if (client->swapped) { - int n; swapl(&rep.length, n); swaps(&rep.sequenceNumber, n); - swaps(&rep.context_len, n); + swapl(&rep.count, n); } - WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep); - WriteToClient(client, rep.context_len, ctx); - free(ctx); - return client->noClientException; -} + WriteToClient(client, sizeof(SELinuxListItemsReply), (char *)&rep); + WriteToClient(client, size * 4, (char *)buf); -static int -ProcSELinuxSetSelectionCreateContext(ClientPtr client) -{ - return Success; + /* Free stuff and return */ + rc = client->noClientException; + xfree(buf); +out: + SELinuxFreeItems(items, count); + return rc; } static int -ProcSELinuxGetSelectionCreateContext(ClientPtr client) +ProcSELinuxListProperties(ClientPtr client) { - return Success; + 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 = xcalloc(count, sizeof(SELinuxListItemRec)); + if (!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 -ProcSELinuxGetSelectionContext(ClientPtr client) +ProcSELinuxListSelections(ClientPtr client) { - return Success; + 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 = xcalloc(count, sizeof(SELinuxListItemRec)); + if (!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 @@ -1308,36 +1662,50 @@ ProcSELinuxDispatch(ClientPtr client) switch (stuff->data) { case X_SELinuxQueryVersion: return ProcSELinuxQueryVersion(client); - case X_SELinuxSetSecurityManager: - return ProcSELinuxSetSecurityManager(client); - case X_SELinuxGetSecurityManager: - return ProcSELinuxGetSecurityManager(client); case X_SELinuxSetDeviceCreateContext: - return ProcSELinuxSetDeviceCreateContext(client); + return ProcSELinuxSetCreateContext(client, CTX_DEV); case X_SELinuxGetDeviceCreateContext: - return ProcSELinuxGetDeviceCreateContext(client); + return ProcSELinuxGetCreateContext(client, CTX_DEV); case X_SELinuxSetDeviceContext: return ProcSELinuxSetDeviceContext(client); case X_SELinuxGetDeviceContext: return ProcSELinuxGetDeviceContext(client); - case X_SELinuxSetPropertyCreateContext: - return ProcSELinuxSetPropertyCreateContext(client); - case X_SELinuxGetPropertyCreateContext: - return ProcSELinuxGetPropertyCreateContext(client); - case X_SELinuxGetPropertyContext: - return ProcSELinuxGetPropertyContext(client); case X_SELinuxSetWindowCreateContext: - return ProcSELinuxSetWindowCreateContext(client); + return ProcSELinuxSetCreateContext(client, CTX_WIN); case X_SELinuxGetWindowCreateContext: - return ProcSELinuxGetWindowCreateContext(client); + return ProcSELinuxGetCreateContext(client, CTX_WIN); case X_SELinuxGetWindowContext: return ProcSELinuxGetWindowContext(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 ProcSELinuxSetSelectionCreateContext(client); + return ProcSELinuxSetCreateContext(client, CTX_SEL); case X_SELinuxGetSelectionCreateContext: - return ProcSELinuxGetSelectionCreateContext(client); + 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); + 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; } @@ -1356,25 +1724,14 @@ SProcSELinuxQueryVersion(ClientPtr client) } static int -SProcSELinuxSetSecurityManager(ClientPtr client) -{ - REQUEST(SELinuxSetSecurityManagerReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxSetSecurityManagerReq); - swapl(&stuff->window, n); - return ProcSELinuxSetSecurityManager(client); -} - -static int -SProcSELinuxSetDeviceCreateContext(ClientPtr client) +SProcSELinuxSetCreateContext(ClientPtr client, unsigned offset) { REQUEST(SELinuxSetCreateContextReq); int n; REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq); - swaps(&stuff->context_len, n); - return ProcSELinuxSetDeviceCreateContext(client); + swapl(&stuff->context_len, n); + return ProcSELinuxSetCreateContext(client, offset); } static int @@ -1385,7 +1742,7 @@ SProcSELinuxSetDeviceContext(ClientPtr client) REQUEST_AT_LEAST_SIZE(SELinuxSetContextReq); swapl(&stuff->id, n); - swaps(&stuff->context_len, n); + swapl(&stuff->context_len, n); return ProcSELinuxSetDeviceContext(client); } @@ -1401,18 +1758,18 @@ SProcSELinuxGetDeviceContext(ClientPtr client) } static int -SProcSELinuxSetPropertyCreateContext(ClientPtr client) +SProcSELinuxGetWindowContext(ClientPtr client) { - REQUEST(SELinuxSetCreateContextReq); + REQUEST(SELinuxGetContextReq); int n; - REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq); - swaps(&stuff->context_len, n); - return ProcSELinuxSetPropertyCreateContext(client); + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + swapl(&stuff->id, n); + return ProcSELinuxGetWindowContext(client); } static int -SProcSELinuxGetPropertyContext(ClientPtr client) +SProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey) { REQUEST(SELinuxGetPropertyContextReq); int n; @@ -1420,51 +1777,40 @@ SProcSELinuxGetPropertyContext(ClientPtr client) REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq); swapl(&stuff->window, n); swapl(&stuff->property, n); - return ProcSELinuxGetPropertyContext(client); -} - -static int -SProcSELinuxSetWindowCreateContext(ClientPtr client) -{ - REQUEST(SELinuxSetCreateContextReq); - int n; - - REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq); - swaps(&stuff->context_len, n); - return ProcSELinuxSetWindowCreateContext(client); + return ProcSELinuxGetPropertyContext(client, privKey); } static int -SProcSELinuxGetWindowContext(ClientPtr client) +SProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey) { REQUEST(SELinuxGetContextReq); int n; REQUEST_SIZE_MATCH(SELinuxGetContextReq); swapl(&stuff->id, n); - return ProcSELinuxGetWindowContext(client); + return ProcSELinuxGetSelectionContext(client, privKey); } static int -SProcSELinuxSetSelectionCreateContext(ClientPtr client) +SProcSELinuxListProperties(ClientPtr client) { - REQUEST(SELinuxSetCreateContextReq); + REQUEST(SELinuxGetContextReq); int n; - REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq); - swaps(&stuff->context_len, n); - return ProcSELinuxSetSelectionCreateContext(client); + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + swapl(&stuff->id, n); + return ProcSELinuxListProperties(client); } static int -SProcSELinuxGetSelectionContext(ClientPtr client) +SProcSELinuxGetClientContext(ClientPtr client) { REQUEST(SELinuxGetContextReq); int n; REQUEST_SIZE_MATCH(SELinuxGetContextReq); swapl(&stuff->id, n); - return ProcSELinuxGetSelectionContext(client); + return ProcSELinuxGetClientContext(client); } static int @@ -1478,36 +1824,50 @@ SProcSELinuxDispatch(ClientPtr client) switch (stuff->data) { case X_SELinuxQueryVersion: return SProcSELinuxQueryVersion(client); - case X_SELinuxSetSecurityManager: - return SProcSELinuxSetSecurityManager(client); - case X_SELinuxGetSecurityManager: - return ProcSELinuxGetSecurityManager(client); case X_SELinuxSetDeviceCreateContext: - return SProcSELinuxSetDeviceCreateContext(client); + return SProcSELinuxSetCreateContext(client, CTX_DEV); case X_SELinuxGetDeviceCreateContext: - return ProcSELinuxGetDeviceCreateContext(client); + return ProcSELinuxGetCreateContext(client, CTX_DEV); case X_SELinuxSetDeviceContext: return SProcSELinuxSetDeviceContext(client); case X_SELinuxGetDeviceContext: return SProcSELinuxGetDeviceContext(client); - case X_SELinuxSetPropertyCreateContext: - return SProcSELinuxSetPropertyCreateContext(client); - case X_SELinuxGetPropertyCreateContext: - return ProcSELinuxGetPropertyCreateContext(client); - case X_SELinuxGetPropertyContext: - return SProcSELinuxGetPropertyContext(client); case X_SELinuxSetWindowCreateContext: - return SProcSELinuxSetWindowCreateContext(client); + return SProcSELinuxSetCreateContext(client, CTX_WIN); case X_SELinuxGetWindowCreateContext: - return ProcSELinuxGetWindowCreateContext(client); + return ProcSELinuxGetCreateContext(client, CTX_WIN); case X_SELinuxGetWindowContext: return SProcSELinuxGetWindowContext(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 SProcSELinuxSetSelectionCreateContext(client); + return SProcSELinuxSetCreateContext(client, CTX_SEL); case X_SELinuxGetSelectionCreateContext: - return ProcSELinuxGetSelectionCreateContext(client); + 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); + 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; } @@ -1524,7 +1884,6 @@ SELinuxResetProc(ExtensionEntry *extEntry) /* Unregister callbacks */ DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL); DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL); - DeleteCallback(&SelectionCallback, SELinuxSelectionState, NULL); XaceDeleteCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); XaceDeleteCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); @@ -1549,9 +1908,9 @@ SELinuxResetProc(ExtensionEntry *extEntry) avc_active = 0; /* Free local state */ - xfree(knownSelections); - knownSelections = NULL; - numKnownSelections = 0; + xfree(knownAtoms); + knownAtoms = NULL; + numKnownAtoms = 0; xfree(knownEvents); knownEvents = NULL; @@ -1566,16 +1925,36 @@ void SELinuxExtensionInit(INITARGS) { ExtensionEntry *extEntry; - struct selinux_opt options[] = { { SELABEL_OPT_VALIDATE, (char *)1 } }; + struct selinux_opt selabel_option = { SELABEL_OPT_VALIDATE, (char *)1 }; + struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 }; security_context_t con; int ret = TRUE; - /* Setup SELinux stuff */ + /* Check SELinux mode on system */ if (!is_selinux_enabled()) { - ErrorF("SELinux: SELinux not enabled, disabling SELinux support.\n"); + ErrorF("SELinux: Disabled on system, not enabling in X server\n"); return; } + /* Check SELinux mode in configuration file */ + switch(selinuxEnforcingState) { + case SELINUX_MODE_DISABLED: + LogMessage(X_INFO, "SELinux: Disabled in configuration file\n"); + return; + case SELINUX_MODE_ENFORCING: + LogMessage(X_INFO, "SELinux: Configured in enforcing mode\n"); + avc_option.value = (char *)1; + break; + case SELINUX_MODE_PERMISSIVE: + LogMessage(X_INFO, "SELinux: Configured in permissive mode\n"); + avc_option.value = (char *)0; + break; + default: + avc_option.type = AVC_OPT_UNUSED; + break; + } + + /* Set up SELinux stuff */ selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)SELinuxLog); selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)SELinuxAudit); @@ -1587,11 +1966,11 @@ SELinuxExtensionInit(INITARGS) FatalError("SELinux: Failed to set up security class mapping\n"); } - if (avc_open(NULL, 0) < 0) + if (avc_open(&avc_option, 1) < 0) FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n"); avc_active = 1; - label_hnd = selabel_open(SELABEL_CTX_X, options, 1); + label_hnd = selabel_open(SELABEL_CTX_X, &selabel_option, 1); if (!label_hnd) FatalError("SELinux: Failed to open x_contexts mapping in policy\n"); @@ -1608,7 +1987,8 @@ SELinuxExtensionInit(INITARGS) /* Allocate private storage */ if (!dixRequestPrivate(subjectKey, sizeof(SELinuxSubjectRec)) || - !dixRequestPrivate(objectKey, sizeof(SELinuxObjectRec))) + !dixRequestPrivate(objectKey, sizeof(SELinuxObjectRec)) || + !dixRequestPrivate(dataKey, sizeof(SELinuxObjectRec))) FatalError("SELinux: Failed to allocate private storage.\n"); /* Create atoms for doing window labeling */ @@ -1624,10 +2004,11 @@ SELinuxExtensionInit(INITARGS) ret &= dixRegisterPrivateDeleteFunc(subjectKey, SELinuxSubjectFree, NULL); ret &= dixRegisterPrivateInitFunc(objectKey, SELinuxObjectInit, NULL); ret &= dixRegisterPrivateDeleteFunc(objectKey, SELinuxObjectFree, NULL); + ret &= dixRegisterPrivateInitFunc(dataKey, SELinuxObjectInit, NULL); + ret &= dixRegisterPrivateDeleteFunc(dataKey, SELinuxObjectFree, NULL); ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL); ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL); - ret &= AddCallback(&SelectionCallback, SELinuxSelectionState, NULL); ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); |