xselinux: Don't require incoming context strings to be null-terminated.

This commit is contained in:
Eamon Walsh 2009-04-08 15:10:16 -04:00
parent df27b870a8
commit e8b324102f

View File

@ -1258,6 +1258,17 @@ typedef struct {
CARD32 id; CARD32 id;
} SELinuxListItemRec; } 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 static int
ProcSELinuxQueryVersion(ClientPtr client) ProcSELinuxQueryVersion(ClientPtr client)
{ {
@ -1315,29 +1326,34 @@ ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
{ {
PrivateRec **privPtr = &client->devPrivates; PrivateRec **privPtr = &client->devPrivates;
security_id_t *pSid; security_id_t *pSid;
security_context_t ctx; security_context_t ctx = NULL;
char *ptr; char *ptr;
int rc;
REQUEST(SELinuxSetCreateContextReq); REQUEST(SELinuxSetCreateContextReq);
REQUEST_FIXED_SIZE(SELinuxSetCreateContextReq, stuff->context_len); REQUEST_FIXED_SIZE(SELinuxSetCreateContextReq, stuff->context_len);
ctx = (char *)(stuff + 1); if (stuff->context_len > 0) {
if (stuff->context_len > 0 && ctx[stuff->context_len - 1]) ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len);
return BadLength; if (!ctx)
return BadAlloc;
}
if (offset == CTX_DEV) { if (offset == CTX_DEV) {
/* Device create context currently requires manage permission */ /* 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) if (rc != Success)
return rc; goto out;
privPtr = &serverClient->devPrivates; privPtr = &serverClient->devPrivates;
} }
else if (offset == USE_SEL) { else if (offset == USE_SEL) {
/* Selection use context currently requires no selections owned */ /* Selection use context currently requires no selections owned */
Selection *pSel; Selection *pSel;
for (pSel = CurrentSelections; pSel; pSel = pSel->next) for (pSel = CurrentSelections; pSel; pSel = pSel->next)
if (pSel->client == client) if (pSel->client == client) {
return BadMatch; rc = BadMatch;
goto out;
}
} }
ptr = dixLookupPrivate(privPtr, subjectKey); ptr = dixLookupPrivate(privPtr, subjectKey);
@ -1345,13 +1361,15 @@ ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
sidput(*pSid); sidput(*pSid);
*pSid = NULL; *pSid = NULL;
rc = Success;
if (stuff->context_len > 0) { if (stuff->context_len > 0) {
if (security_check_context_raw(ctx) < 0) if (security_check_context_raw(ctx) < 0 ||
return BadValue; avc_context_to_sid_raw(ctx, pSid) < 0)
if (avc_context_to_sid_raw(ctx, pSid) < 0) rc = BadValue;
return BadValue;
} }
return Success; out:
xfree(ctx);
return rc;
} }
static int static int
@ -1384,18 +1402,21 @@ ProcSELinuxSetDeviceContext(ClientPtr client)
REQUEST(SELinuxSetContextReq); REQUEST(SELinuxSetContextReq);
REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len); REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len);
ctx = (char *)(stuff + 1); if (stuff->context_len < 1)
if (stuff->context_len < 1 || ctx[stuff->context_len - 1])
return BadLength; return BadLength;
ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len);
if (!ctx)
return BadAlloc;
rc = dixLookupDevice(&dev, stuff->id, client, DixManageAccess); rc = dixLookupDevice(&dev, stuff->id, client, DixManageAccess);
if (rc != Success) if (rc != Success)
return rc; goto out;
if (security_check_context_raw(ctx) < 0) if (security_check_context_raw(ctx) < 0 ||
return BadValue; avc_context_to_sid_raw(ctx, &sid) < 0) {
if (avc_context_to_sid_raw(ctx, &sid) < 0) rc = BadValue;
return BadValue; goto out;
}
subj = dixLookupPrivate(&dev->devPrivates, subjectKey); subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
sidput(subj->sid); sidput(subj->sid);
@ -1404,7 +1425,10 @@ ProcSELinuxSetDeviceContext(ClientPtr client)
sidput(obj->sid); sidput(obj->sid);
sidget(obj->sid = sid); sidget(obj->sid = sid);
return Success; rc = Success;
out:
xfree(ctx);
return rc;
} }
static int static int