diff options
author | marha <marha@users.sourceforge.net> | 2009-07-25 19:39:46 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2009-07-25 19:39:46 +0000 |
commit | 4a3dbb926ae3f5410198d7cc4f4ebe4f62eebf05 (patch) | |
tree | c1e02b9d3509aa97703aa4b540d4cd22ec4600ed /xorg-server/Xext/xselinux.c | |
parent | dc3c299dd0995549e2a6973ca0f25b254afd38a5 (diff) | |
download | vcxsrv-4a3dbb926ae3f5410198d7cc4f4ebe4f62eebf05.tar.gz vcxsrv-4a3dbb926ae3f5410198d7cc4f4ebe4f62eebf05.tar.bz2 vcxsrv-4a3dbb926ae3f5410198d7cc4f4ebe4f62eebf05.zip |
Added xorg-server-1.6.2.tar.gz
Diffstat (limited to 'xorg-server/Xext/xselinux.c')
-rw-r--r-- | xorg-server/Xext/xselinux.c | 187 |
1 files changed, 124 insertions, 63 deletions
diff --git a/xorg-server/Xext/xselinux.c b/xorg-server/Xext/xselinux.c index 1d3449b9a..6c99c2944 100644 --- a/xorg-server/Xext/xselinux.c +++ b/xorg-server/Xext/xselinux.c @@ -62,9 +62,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* private state keys */ -static DevPrivateKey subjectKey = &subjectKey; -static DevPrivateKey objectKey = &objectKey; -static DevPrivateKey dataKey = &dataKey; +static int subjectKeyIndex; +static DevPrivateKey subjectKey = &subjectKeyIndex; +static int objectKeyIndex; +static DevPrivateKey objectKey = &objectKeyIndex; +static int dataKeyIndex; +static DevPrivateKey dataKey = &dataKeyIndex; /* subject state (clients and devices only) */ typedef struct { @@ -183,19 +186,19 @@ SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec *obj, int map, int polymap) obj->poly = 1; /* Look in the mappings of names to contexts */ - if (selabel_lookup(label_hnd, &ctx, name, map) == 0) { + if (selabel_lookup_raw(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) { + } else if (selabel_lookup_raw(label_hnd, &ctx, name, polymap) < 0) { ErrorF("SELinux: a property label lookup failed!\n"); return BadValue; } /* Get a SID for context */ - if (avc_context_to_sid(ctx, &obj->sid) < 0) { - ErrorF("SELinux: a context_to_SID call failed!\n"); + if (avc_context_to_sid_raw(ctx, &obj->sid) < 0) { + ErrorF("SELinux: a context_to_SID_raw call failed!\n"); rc = BadAlloc; } @@ -340,7 +343,7 @@ SELinuxEventToSID(unsigned type, security_id_t sid_of_window, SELinuxObjectRec *sid_return) { const char *name = LookupEventName(type); - security_context_t con; + security_context_t ctx; type &= 127; if (type >= numKnownEvents) { @@ -356,16 +359,16 @@ SELinuxEventToSID(unsigned type, security_id_t sid_of_window, if (!knownEvents[type]) { /* Look in the mappings of event names to contexts */ - if (selabel_lookup(label_hnd, &con, name, SELABEL_X_EVENT) < 0) { + if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EVENT) < 0) { ErrorF("SELinux: an event label lookup failed!\n"); return BadValue; } /* Get a SID for context */ - if (avc_context_to_sid(con, knownEvents + type) < 0) { - ErrorF("SELinux: a context_to_SID call failed!\n"); + if (avc_context_to_sid_raw(ctx, knownEvents + type) < 0) { + ErrorF("SELinux: a context_to_SID_raw call failed!\n"); return BadAlloc; } - freecon(con); + freecon(ctx); } /* Perform a transition to obtain the final SID */ @@ -469,9 +472,9 @@ SELinuxLabelClient(ClientPtr client) sidput(obj->sid); /* Try to get a context from the socket */ - if (fd < 0 || getpeercon(fd, &ctx) < 0) { + if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) { /* Otherwise, fall back to a default context */ - if (selabel_lookup(label_hnd, &ctx, NULL, SELABEL_X_CLIENT) < 0) + if (selabel_lookup_raw(label_hnd, &ctx, "remote", SELABEL_X_CLIENT) < 0) FatalError("SELinux: failed to look up remote-client context\n"); } @@ -506,8 +509,8 @@ SELinuxLabelClient(ClientPtr client) finish: /* Get a SID from the context */ - if (avc_context_to_sid(ctx, &subj->sid) < 0) - FatalError("SELinux: client %d: context_to_sid(%s) failed\n", + if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) + FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n", client->index, ctx); sidget(obj->sid = subj->sid); @@ -534,11 +537,11 @@ SELinuxLabelInitial(void) sidput(subj->sid); /* Use the context of the X server process for the serverClient */ - if (getcon(&ctx) < 0) + if (getcon_raw(&ctx) < 0) FatalError("SELinux: couldn't get context of X server process\n"); /* Get a SID from the context */ - if (avc_context_to_sid(ctx, &subj->sid) < 0) + if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx); sidget(obj->sid = subj->sid); @@ -654,7 +657,19 @@ SELinuxLog(int type, const char *fmt, ...) { va_list ap; char buf[MAX_AUDIT_MESSAGE_LENGTH]; - int rc, aut = AUDIT_USER_AVC; + int rc, aut; + + switch (type) { + case SELINUX_INFO: + aut = AUDIT_USER_MAC_POLICY_LOAD; + break; + case SELINUX_AVC: + aut = AUDIT_USER_AVC; + break; + default: + aut = AUDIT_USER_SELINUX_ERR; + break; + } va_start(ap, fmt); vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap); @@ -812,20 +827,20 @@ SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) /* XXX there should be a separate callback for this */ if (obj->sid == unlabeled_sid) { const char *name = rec->ext->name; - security_context_t con; + security_context_t ctx; security_id_t sid; serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey); /* Look in the mappings of extension names to contexts */ - if (selabel_lookup(label_hnd, &con, name, SELABEL_X_EXT) < 0) { + if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EXT) < 0) { ErrorF("SELinux: a property label lookup failed!\n"); rec->status = BadValue; return; } /* Get a SID for context */ - if (avc_context_to_sid(con, &sid) < 0) { - ErrorF("SELinux: a context_to_SID call failed!\n"); + if (avc_context_to_sid_raw(ctx, &sid) < 0) { + ErrorF("SELinux: a context_to_SID_raw call failed!\n"); rec->status = BadAlloc; return; } @@ -836,11 +851,11 @@ SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION, &obj->sid) < 0) { ErrorF("SELinux: a SID transition call failed!\n"); - freecon(con); + freecon(ctx); rec->status = BadValue; return; } - freecon(con); + freecon(ctx); } /* Perform the security check */ @@ -1135,13 +1150,15 @@ SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata) if (rec->type != RT_WINDOW) return; + if (rec->state != ResourceStateAdding) + return; pWin = (WindowPtr)rec->value; subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey); if (subj->sid) { security_context_t ctx; - int rc = avc_sid_to_context(subj->sid, &ctx); + int rc = avc_sid_to_context_raw(subj->sid, &ctx); if (rc < 0) FatalError("SELinux: Failed to get security context!\n"); rc = dixChangeWindowProperty(serverClient, @@ -1157,7 +1174,7 @@ SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata) if (obj->sid) { security_context_t ctx; - int rc = avc_sid_to_context(obj->sid, &ctx); + int rc = avc_sid_to_context_raw(obj->sid, &ctx); if (rc < 0) FatalError("SELinux: Failed to get security context!\n"); rc = dixChangeWindowProperty(serverClient, @@ -1244,6 +1261,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) { @@ -1273,7 +1301,7 @@ SELinuxSendContextReply(ClientPtr client, security_id_t sid) int len = 0; if (sid) { - if (avc_sid_to_context(sid, &ctx) < 0) + if (avc_sid_to_context_raw(sid, &ctx) < 0) return BadValue; len = strlen(ctx) + 1; } @@ -1301,43 +1329,41 @@ 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; - } ptr = dixLookupPrivate(privPtr, subjectKey); pSid = (security_id_t *)(ptr + offset); sidput(*pSid); *pSid = NULL; + rc = Success; if (stuff->context_len > 0) { - if (security_check_context(ctx) < 0) - return BadValue; - if (avc_context_to_sid(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 @@ -1370,18 +1396,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(ctx) < 0) - return BadValue; - if (avc_context_to_sid(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); @@ -1390,7 +1419,10 @@ ProcSELinuxSetDeviceContext(ClientPtr client) sidput(obj->sid); sidget(obj->sid = sid); - return Success; + rc = Success; +out: + xfree(ctx); + return rc; } static int @@ -1496,9 +1528,9 @@ SELinuxPopulateItem(SELinuxListItemRec *i, PrivateRec **privPtr, CARD32 id, SELinuxObjectRec *obj = dixLookupPrivate(privPtr, objectKey); SELinuxObjectRec *data = dixLookupPrivate(privPtr, dataKey); - if (avc_sid_to_context(obj->sid, &i->octx) < 0) + if (avc_sid_to_context_raw(obj->sid, &i->octx) < 0) return BadValue; - if (avc_sid_to_context(data->sid, &i->dctx) < 0) + if (avc_sid_to_context_raw(data->sid, &i->dctx) < 0) return BadValue; i->id = id; @@ -1529,7 +1561,7 @@ SELinuxSendItemsToClient(ClientPtr client, SELinuxListItemRec *items, CARD32 *buf; buf = xcalloc(size, sizeof(CARD32)); - if (!buf) { + if (size && !buf) { rc = BadAlloc; goto out; } @@ -1601,7 +1633,7 @@ ProcSELinuxListProperties(ClientPtr client) for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) count++; items = xcalloc(count, sizeof(SELinuxListItemRec)); - if (!items) + if (count && !items) return BadAlloc; /* Fill in the items and calculate size */ @@ -1635,7 +1667,7 @@ ProcSELinuxListSelections(ClientPtr client) for (pSel = CurrentSelections; pSel; pSel = pSel->next) count++; items = xcalloc(count, sizeof(SELinuxListItemRec)); - if (!items) + if (count && !items) return BadAlloc; /* Fill in the items and calculate size */ @@ -1872,6 +1904,22 @@ SProcSELinuxDispatch(ClientPtr client) } } +#ifdef HAVE_AVC_NETLINK_ACQUIRE_FD +static int netlink_fd; + +static void +SELinuxBlockHandler(void *data, struct timeval **tv, void *read_mask) +{ +} + +static void +SELinuxWakeupHandler(void *data, int err, void *read_mask) +{ + if (FD_ISSET(netlink_fd, (fd_set *)read_mask)) + avc_netlink_check_nb(); +} +#endif + /* * Extension Setup / Teardown @@ -1902,6 +1950,12 @@ SELinuxResetProc(ExtensionEntry *extEntry) label_hnd = NULL; audit_close(audit_fd); +#ifdef HAVE_AVC_NETLINK_ACQUIRE_FD + avc_netlink_release_fd(); + RemoveBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, + NULL); + RemoveGeneralSocket(netlink_fd); +#endif avc_destroy(); avc_active = 0; @@ -1926,7 +1980,7 @@ SELinuxExtensionInit(INITARGS) ExtensionEntry *extEntry; struct selinux_opt selabel_option = { SELABEL_OPT_VALIDATE, (char *)1 }; struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 }; - security_context_t con; + security_context_t ctx; int ret = TRUE; /* Check SELinux mode on system */ @@ -1973,11 +2027,11 @@ SELinuxExtensionInit(INITARGS) if (!label_hnd) FatalError("SELinux: Failed to open x_contexts mapping in policy\n"); - if (security_get_initial_context("unlabeled", &con) < 0) + if (security_get_initial_context_raw("unlabeled", &ctx) < 0) FatalError("SELinux: Failed to look up unlabeled context\n"); - if (avc_context_to_sid(con, &unlabeled_sid) < 0) + if (avc_context_to_sid_raw(ctx, &unlabeled_sid) < 0) FatalError("SELinux: a context_to_SID call failed!\n"); - freecon(con); + freecon(ctx); /* Prepare for auditing */ audit_fd = audit_open(); @@ -1998,6 +2052,13 @@ SELinuxExtensionInit(INITARGS) if (atom_client_ctx == BAD_RESOURCE) FatalError("SELinux: Failed to create atom\n"); +#ifdef HAVE_AVC_NETLINK_ACQUIRE_FD + netlink_fd = avc_netlink_acquire_fd(); + AddGeneralSocket(netlink_fd); + RegisterBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, + NULL); +#endif + /* Register callbacks */ ret &= dixRegisterPrivateInitFunc(subjectKey, SELinuxSubjectInit, NULL); ret &= dixRegisterPrivateDeleteFunc(subjectKey, SELinuxSubjectFree, NULL); |