xserver: Branch 'XACE-SELINUX' - 2 commits

Eamon Walsh ewalsh at kemper.freedesktop.org
Fri Oct 19 13:17:06 PDT 2007


 Xext/xselinux.c |  212 ++++++++++++++++++++++++++++++++++++++++++++------------
 Xext/xselinux.h |    3 
 2 files changed, 170 insertions(+), 45 deletions(-)

New commits:
commit 55a96aa6b0995fda6660b7e78c85b955a62b9735
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Thu Oct 18 14:11:11 2007 -0400

    xselinux: add basic event labeling.

diff --git a/Xext/xselinux.c b/Xext/xselinux.c
index 2e36622..8b1898d 100644
--- a/Xext/xselinux.c
+++ b/Xext/xselinux.c
@@ -95,6 +95,10 @@ static security_id_t unlabeled_sid;
 static security_class_t *knownTypes;
 static unsigned numKnownTypes;
 
+/* Array of event SIDs indexed by event type */
+static security_id_t *knownEvents;
+static unsigned numKnownEvents;
+
 /* dynamically allocated security classes and permissions */
 static struct security_class_mapping map[] = {
     { "x_drawable", { "read", "write", "destroy", "create", "getattr", "setattr", "list_property", "get_property", "set_property", "", "", "list_child", "add_child", "remove_child", "hide", "show", "blend", "override", "", "", "", "", "send", "receive", "", "manage", NULL }},
@@ -109,6 +113,7 @@ static struct security_class_mapping map[] = {
     { "x_device", { "read", "write", "", "", "getattr", "setattr", "", "", "", "getfocus", "setfocus", "", "", "", "", "", "", "grab", "freeze", "force_cursor", "", "", "", "", "", "manage", "", "bell", NULL }},
     { "x_server", { "record", "", "", "", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "grab", "", "", "", "", "", "", "", "manage", "debug", NULL }},
     { "x_extension", { "", "", "", "", "query", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "use", NULL }},
+    { "x_event", { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "send", "receive", NULL }},
     { "x_resource", { "read", "write", "write", "write", "read", "write", "read", "read", "write", "read", "write", "read", "write", "write", "write", "read", "read", "write", "write", "write", "write", "write", "write", "read", "read", "write", "read", "write", NULL }},
     { NULL }
 };
@@ -122,6 +127,43 @@ static void SELinuxScreen(CallbackListPtr *, pointer, pointer);
  */
 
 /*
+ * Looks up the SID corresponding to the given event type
+ */
+static int
+SELinuxEventToSID(int type, SELinuxStateRec *sid_return)
+{
+    const char *name = LookupEventName(type);
+    security_context_t con;
+
+    if (type >= numKnownEvents) {
+	/* Need to increase size of classes array */
+	unsigned size = sizeof(security_id_t);
+	knownEvents = xrealloc(knownEvents, (type + 1) * size);
+	if (!knownEvents)
+	    return BadAlloc;
+	memset(knownEvents + numKnownEvents, 0,
+	       (type - numKnownEvents + 1) * size);
+    }
+
+    if (!knownEvents[type]) {
+	/* Look in the mappings of property names to contexts */
+	if (selabel_lookup(label_hnd, &con, name, SELABEL_X_EVENT) < 0) {
+	    ErrorF("XSELinux: an event label lookup failed!\n");
+	    return BadValue;
+	}
+	/* Get a SID for context */
+	if (avc_context_to_sid(con, knownEvents + type) < 0) {
+	    ErrorF("XSELinux: a context_to_SID call failed!\n");
+	    return BadAlloc;
+	}
+	freecon(con);
+    }
+
+    sid_return->sid = knownEvents[type];
+    return Success;
+}
+
+/*
  * Returns the object class corresponding to the given resource type.
  */
 static security_class_t
@@ -325,7 +367,7 @@ SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata)
     XaceSendAccessRec *rec = calldata;
     SELinuxStateRec *subj, *obj;
     SELinuxAuditRec auditdata = { rec->client, NULL, 0, 0, 0, NULL };
-    int clientIndex, rc;
+    int rc, i, clientIndex;
 
     if (rec->dev) {
 	subj = dixLookupPrivate(&rec->dev->devPrivates, stateKey);
@@ -337,10 +379,28 @@ SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 
     obj = dixLookupPrivate(&rec->pWin->devPrivates, stateKey);
 
+    /* Check send permission on window */
     rc = SELinuxDoCheck(clientIndex, subj, obj, SECCLASS_X_DRAWABLE,
 			DixSendAccess, &auditdata);
     if (rc != Success)
-	rec->status = rc;
+	goto err;
+
+    /* Check send permission on specific event types */
+    for (i = 0; i < rec->count; i++) {
+	SELinuxStateRec ev_sid;
+
+	rc = SELinuxEventToSID(rec->events[i].u.u.type, &ev_sid);
+	if (rc != Success)
+	    goto err;
+
+	rc = SELinuxDoCheck(clientIndex, subj, &ev_sid, SECCLASS_X_EVENT,
+			    DixSendAccess, &auditdata);
+	if (rc != Success)
+	    goto err;
+    }
+    return;
+err:
+    rec->status = rc;
 }
 
 static void
@@ -349,15 +409,33 @@ SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata)
     XaceReceiveAccessRec *rec = calldata;
     SELinuxStateRec *subj, *obj;
     SELinuxAuditRec auditdata = { rec->client, NULL, 0, 0, 0, NULL };
-    int rc;
+    int rc, i;
 
     subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
     obj = dixLookupPrivate(&rec->pWin->devPrivates, stateKey);
 
+    /* Check receive permission on window */
     rc = SELinuxDoCheck(rec->client->index, subj, obj, SECCLASS_X_DRAWABLE,
 			DixReceiveAccess, &auditdata);
     if (rc != Success)
-	rec->status = rc;
+	goto err;
+
+    /* Check receive permission on specific event types */
+    for (i = 0; i < rec->count; i++) {
+	SELinuxStateRec ev_sid;
+
+	rc = SELinuxEventToSID(rec->events[i].u.u.type, &ev_sid);
+	if (rc != Success)
+	    goto err;
+
+	rc = SELinuxDoCheck(rec->client->index, subj, &ev_sid, SECCLASS_X_EVENT,
+			    DixReceiveAccess, &auditdata);
+	if (rc != Success)
+	    goto err;
+    }
+    return;
+err:
+    rec->status = rc;
 }
 
 static void
@@ -762,6 +840,10 @@ SELinuxResetProc(ExtensionEntry *extEntry)
     avc_destroy();
     avc_active = 0;
 
+    xfree(knownEvents);
+    knownEvents = NULL;
+    numKnownEvents = 0;
+
     xfree(knownTypes);
     knownTypes = NULL;
     numKnownTypes = 0;
diff --git a/Xext/xselinux.h b/Xext/xselinux.h
index 02ec86b..407b81f 100644
--- a/Xext/xselinux.h
+++ b/Xext/xselinux.h
@@ -42,6 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define SECCLASS_X_DEVICE		10
 #define SECCLASS_X_SERVER		11
 #define SECCLASS_X_EXTENSION		12
-#define SECCLASS_X_RESOURCE		13
+#define SECCLASS_X_EVENT		13
+#define SECCLASS_X_RESOURCE		14
 
 #endif /* _XSELINUX_H */
commit e974bc1233608ec09fbd40b12217925e4d2205aa
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Thu Oct 18 12:33:39 2007 -0400

    xselinux: add hooks for send and receive access.

diff --git a/Xext/xselinux.c b/Xext/xselinux.c
index 8bafa1f..2e36622 100644
--- a/Xext/xselinux.c
+++ b/Xext/xselinux.c
@@ -62,7 +62,7 @@ static DevPrivateKey stateKey = &stateKey;
 typedef struct {
     security_id_t sid;
     struct avc_entry_ref aeref;
-    char *client_path;
+    char *command;
 } SELinuxStateRec;
 
 /* audit file descriptor */
@@ -71,7 +71,7 @@ static int audit_fd;
 /* structure passed to auditing callback */
 typedef struct {
     ClientPtr client;	/* client */
-    char *client_path;	/* client's executable path */
+    char *command;	/* client's executable path */
     unsigned id;	/* resource id, if any */
     int restype;	/* resource type, if any */
     Atom property;	/* property name, if any */
@@ -170,21 +170,17 @@ SELinuxTypeToClass(RESTYPE type)
  * Performs an SELinux permission check.
  */
 static int
-SELinuxDoCheck(ClientPtr client, SELinuxStateRec *obj, security_class_t class,
-	       Mask access_mode, SELinuxAuditRec *auditdata)
+SELinuxDoCheck(int clientIndex, SELinuxStateRec *subj, SELinuxStateRec *obj,
+	       security_class_t class, Mask mode, SELinuxAuditRec *auditdata)
 {
-    SELinuxStateRec *subj;
-
     /* serverClient requests OK */
-    if (client->index == 0)
+    if (clientIndex == 0)
 	return Success;
 
-    subj = dixLookupPrivate(&client->devPrivates, stateKey);
-    auditdata->client = client;
-    auditdata->client_path = subj->client_path;
+    auditdata->command = subj->command;
     errno = 0;
 
-    if (avc_has_perm(subj->sid, obj->sid, class, access_mode, &subj->aeref,
+    if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref,
 		     auditdata) < 0) {
 	if (errno == EACCES)
 	    return BadAccess;
@@ -250,23 +246,25 @@ SELinuxAudit(void *auditdata,
     SELinuxAuditRec *audit = auditdata;
     ClientPtr client = audit->client;
     char idNum[16], *propertyName;
-    int major = 0, minor = 0;
-    REQUEST(xReq);
+    int major = -1, minor = -1;
 
+    if (client) {
+	REQUEST(xReq);
+	if (stuff) {
+	    major = stuff->reqType;
+	    minor = MinorOpcodeOfRequest(client);
+	}
+    }
     if (audit->id)
 	snprintf(idNum, 16, "%x", audit->id);
-    if (stuff) {
-	major = stuff->reqType;
-	minor = (major < 128) ? 0 : MinorOpcodeOfRequest(client);
-    }
 
     propertyName = audit->property ? NameForAtom(audit->property) : NULL;
 
     return snprintf(msgbuf, msgbufsize, "%s%s%s%s%s%s%s%s%s%s%s%s",
-		    stuff ? "request=" : "",
-		    stuff ? LookupRequestName(major, minor) : "",
-		    audit->client_path ? " comm=" : "",
-		    audit->client_path ? audit->client_path : "",
+		    (major >= 0) ? "request=" : "",
+		    (major >= 0) ? LookupRequestName(major, minor) : "",
+		    audit->command ? " comm=" : "",
+		    audit->command ? audit->command : "",
 		    audit->id ? " resid=" : "",
 		    audit->id ? idNum : "",
 		    audit->restype ? " restype=" : "",
@@ -296,7 +294,7 @@ SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 {
     XaceDeviceAccessRec *rec = calldata;
     SELinuxStateRec *subj, *obj;
-    SELinuxAuditRec auditdata = { NULL, NULL, 0, 0, 0, NULL };
+    SELinuxAuditRec auditdata = { rec->client, NULL, 0, 0, 0, NULL };
     int rc;
 
     subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
@@ -315,18 +313,59 @@ SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 	}
     }
 
-    rc = SELinuxDoCheck(rec->client, obj, SECCLASS_X_DEVICE,
+    rc = SELinuxDoCheck(rec->client->index, subj, obj, SECCLASS_X_DEVICE,
 			rec->access_mode, &auditdata);
     if (rc != Success)
 	rec->status = rc;
 }
 
 static void
+SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+    XaceSendAccessRec *rec = calldata;
+    SELinuxStateRec *subj, *obj;
+    SELinuxAuditRec auditdata = { rec->client, NULL, 0, 0, 0, NULL };
+    int clientIndex, rc;
+
+    if (rec->dev) {
+	subj = dixLookupPrivate(&rec->dev->devPrivates, stateKey);
+	clientIndex = -1; /* some nonzero value */
+    } else {
+	subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+	clientIndex = rec->client->index;
+    }
+
+    obj = dixLookupPrivate(&rec->pWin->devPrivates, stateKey);
+
+    rc = SELinuxDoCheck(clientIndex, subj, obj, SECCLASS_X_DRAWABLE,
+			DixSendAccess, &auditdata);
+    if (rc != Success)
+	rec->status = rc;
+}
+
+static void
+SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+    XaceReceiveAccessRec *rec = calldata;
+    SELinuxStateRec *subj, *obj;
+    SELinuxAuditRec auditdata = { rec->client, NULL, 0, 0, 0, NULL };
+    int rc;
+
+    subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+    obj = dixLookupPrivate(&rec->pWin->devPrivates, stateKey);
+
+    rc = SELinuxDoCheck(rec->client->index, subj, obj, SECCLASS_X_DRAWABLE,
+			DixReceiveAccess, &auditdata);
+    if (rc != Success)
+	rec->status = rc;
+}
+
+static void
 SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 {
     XaceExtAccessRec *rec = calldata;
     SELinuxStateRec *subj, *obj, *serv;
-    SELinuxAuditRec auditdata = { NULL, NULL, 0, 0, 0, NULL };
+    SELinuxAuditRec auditdata = { rec->client, NULL, 0, 0, 0, NULL };
     int rc;
 
     subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
@@ -369,7 +408,7 @@ SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 
     /* Perform the security check */
     auditdata.extension = rec->ext->name;
-    rc = SELinuxDoCheck(rec->client, obj, SECCLASS_X_EXTENSION,
+    rc = SELinuxDoCheck(rec->client->index, subj, obj, SECCLASS_X_EXTENSION,
 			rec->access_mode, &auditdata);
     if (rc != Success)
 	rec->status = rc;
@@ -380,7 +419,7 @@ SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 {
     XacePropertyAccessRec *rec = calldata;
     SELinuxStateRec *subj, *obj;
-    SELinuxAuditRec auditdata = { NULL, NULL, 0, 0, 0, NULL };
+    SELinuxAuditRec auditdata = { rec->client, NULL, 0, 0, 0, NULL };
     int rc;
 
     subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
@@ -421,7 +460,7 @@ SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 
     /* Perform the security check */
     auditdata.property = rec->pProp->propertyName;
-    rc = SELinuxDoCheck(rec->client, obj, SECCLASS_X_PROPERTY,
+    rc = SELinuxDoCheck(rec->client->index, subj, obj, SECCLASS_X_PROPERTY,
 			rec->access_mode, &auditdata);
     if (rc != Success)
 	rec->status = rc;
@@ -432,7 +471,7 @@ SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 {
     XaceResourceAccessRec *rec = calldata;
     SELinuxStateRec *subj, *obj, *pobj;
-    SELinuxAuditRec auditdata = { NULL, NULL, 0, 0, 0, NULL };
+    SELinuxAuditRec auditdata = { rec->client, NULL, 0, 0, 0, NULL };
     PrivateRec **privatePtr;
     security_class_t class;
     int rc, offset;
@@ -477,7 +516,8 @@ SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
     /* Perform the security check */
     auditdata.restype = rec->rtype;
     auditdata.id = rec->id;
-    rc = SELinuxDoCheck(rec->client, obj, class, rec->access_mode, &auditdata);
+    rc = SELinuxDoCheck(rec->client->index, subj, obj, class,
+			rec->access_mode, &auditdata);
     if (rc != Success)
 	rec->status = rc;
 }
@@ -487,7 +527,7 @@ SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata)
 {
     XaceScreenAccessRec *rec = calldata;
     SELinuxStateRec *subj, *obj;
-    SELinuxAuditRec auditdata = { NULL, NULL, 0, 0, 0, NULL };
+    SELinuxAuditRec auditdata = { rec->client, NULL, 0, 0, 0, NULL };
     Mask access_mode = rec->access_mode;
     int rc;
 
@@ -510,7 +550,7 @@ SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata)
     if (is_saver)
 	access_mode <<= 2;
 
-    rc = SELinuxDoCheck(rec->client, obj, SECCLASS_X_SCREEN,
+    rc = SELinuxDoCheck(rec->client->index, subj, obj, SECCLASS_X_SCREEN,
 			access_mode, &auditdata);
     if (rc != Success)
 	rec->status = rc;
@@ -520,13 +560,14 @@ static void
 SELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 {
     XaceClientAccessRec *rec = calldata;
-    SELinuxStateRec *obj;
-    SELinuxAuditRec auditdata = { NULL, NULL, 0, 0, 0, NULL };
+    SELinuxStateRec *subj, *obj;
+    SELinuxAuditRec auditdata = { rec->client, NULL, 0, 0, 0, NULL };
     int rc;
 
+    subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
     obj = dixLookupPrivate(&rec->target->devPrivates, stateKey);
 
-    rc = SELinuxDoCheck(rec->client, obj, SECCLASS_X_CLIENT,
+    rc = SELinuxDoCheck(rec->client->index, subj, obj, SECCLASS_X_CLIENT,
 			rec->access_mode, &auditdata);
     if (rc != Success)
 	rec->status = rc;
@@ -536,13 +577,14 @@ static void
 SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 {
     XaceServerAccessRec *rec = calldata;
-    SELinuxStateRec *obj;
-    SELinuxAuditRec auditdata = { NULL, NULL, 0, 0, 0, NULL };
+    SELinuxStateRec *subj, *obj;
+    SELinuxAuditRec auditdata = { rec->client, NULL, 0, 0, 0, NULL };
     int rc;
 
+    subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
     obj = dixLookupPrivate(&serverClient->devPrivates, stateKey);
 
-    rc = SELinuxDoCheck(rec->client, obj, SECCLASS_X_SERVER,
+    rc = SELinuxDoCheck(rec->client->index, subj, obj, SECCLASS_X_SERVER,
 			rec->access_mode, &auditdata);
     if (rc != Success)
 	rec->status = rc;
@@ -595,12 +637,12 @@ SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 	if (bytes <= 0)
 	    goto finish;
 
-	state->client_path = xalloc(bytes);
-	if (!state->client_path)
+	state->command = xalloc(bytes);
+	if (!state->command)
 	    goto finish;
 
-	memcpy(state->client_path, path, bytes);
-	state->client_path[bytes - 1] = 0;
+	memcpy(state->command, path, bytes);
+	state->command[bytes - 1] = 0;
     } else
 	/* For remote clients, need to use a default context */
 	if (selabel_lookup(label_hnd, &ctx, NULL, SELABEL_X_CLIENT) < 0)
@@ -685,7 +727,7 @@ SELinuxStateFree(CallbackListPtr *pcbl, pointer unused, pointer calldata)
     PrivateCallbackRec *rec = calldata;
     SELinuxStateRec *state = *rec->value;
 
-    xfree(state->client_path);
+    xfree(state->command);
 
     if (avc_active)
 	sidput(state->sid);
@@ -787,8 +829,8 @@ XSELinuxExtensionInit(INITARGS)
     ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, 0);
     ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SELinuxDevice, 0);
     ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, 0);
-//    ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, 0);
-//    ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, 0);
+    ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, 0);
+    ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, 0);
     ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, 0);
     ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, 0);
     ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, 0);


More information about the xorg-commit mailing list