aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/Xext/xselinux.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2009-07-25 19:39:46 +0000
committermarha <marha@users.sourceforge.net>2009-07-25 19:39:46 +0000
commit4a3dbb926ae3f5410198d7cc4f4ebe4f62eebf05 (patch)
treec1e02b9d3509aa97703aa4b540d4cd22ec4600ed /xorg-server/Xext/xselinux.c
parentdc3c299dd0995549e2a6973ca0f25b254afd38a5 (diff)
downloadvcxsrv-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.c187
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);