diff --git a/Xext/xselinux.c b/Xext/xselinux.c index 4a1fe004b..399e28ad4 100644 --- a/Xext/xselinux.c +++ b/Xext/xselinux.c @@ -1258,6 +1258,17 @@ typedef struct { CARD32 id; } SELinuxListItemRec; +static security_context_t +SELinuxCopyContext(char *ptr, unsigned len) +{ + security_context_t copy = xalloc(len + 1); + if (!copy) + return NULL; + strncpy(copy, ptr, len); + copy[len] = '\0'; + return copy; +} + static int ProcSELinuxQueryVersion(ClientPtr client) { @@ -1315,29 +1326,34 @@ ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset) { PrivateRec **privPtr = &client->devPrivates; security_id_t *pSid; - security_context_t ctx; + security_context_t ctx = NULL; char *ptr; + int rc; 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 (stuff->context_len > 0) { + ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len); + if (!ctx) + return BadAlloc; + } if (offset == CTX_DEV) { /* Device create context currently requires manage permission */ - int rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess); + rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess); if (rc != Success) - return rc; + goto out; 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; + if (pSel->client == client) { + rc = BadMatch; + goto out; + } } ptr = dixLookupPrivate(privPtr, subjectKey); @@ -1345,13 +1361,15 @@ ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset) sidput(*pSid); *pSid = NULL; + rc = Success; if (stuff->context_len > 0) { - if (security_check_context_raw(ctx) < 0) - return BadValue; - if (avc_context_to_sid_raw(ctx, pSid) < 0) - return BadValue; + if (security_check_context_raw(ctx) < 0 || + avc_context_to_sid_raw(ctx, pSid) < 0) + rc = BadValue; } - return Success; +out: + xfree(ctx); + return rc; } static int @@ -1384,18 +1402,21 @@ ProcSELinuxSetDeviceContext(ClientPtr client) REQUEST(SELinuxSetContextReq); REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len); - ctx = (char *)(stuff + 1); - if (stuff->context_len < 1 || ctx[stuff->context_len - 1]) + 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) - return rc; + goto out; - if (security_check_context_raw(ctx) < 0) - return BadValue; - if (avc_context_to_sid_raw(ctx, &sid) < 0) - return BadValue; + if (security_check_context_raw(ctx) < 0 || + avc_context_to_sid_raw(ctx, &sid) < 0) { + rc = BadValue; + goto out; + } subj = dixLookupPrivate(&dev->devPrivates, subjectKey); sidput(subj->sid); @@ -1404,7 +1425,10 @@ ProcSELinuxSetDeviceContext(ClientPtr client) sidput(obj->sid); sidget(obj->sid = sid); - return Success; + rc = Success; +out: + xfree(ctx); + return rc; } static int