xserver: Branch 'XACE-SELINUX' - 6 commits

Eamon Walsh ewalsh at kemper.freedesktop.org
Tue Oct 23 17:59:58 PDT 2007


 Xext/xace.c     |    1 
 Xext/xacestr.h  |    1 
 Xext/xselinux.c |  424 +++++++++++++++++++++++++++++++++++++++++++++-----------
 Xext/xselinux.h |   37 ++++
 dix/dispatch.c  |   56 ++++---
 dix/events.c    |   18 +-
 dix/registry.c  |    2 
 include/dix.h   |    3 
 8 files changed, 431 insertions(+), 111 deletions(-)

New commits:
commit 0388a59a6ef212c497cc3f64d677b1ca5b410982
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Tue Oct 23 20:59:21 2007 -0400

    Revert "registry: special case minor number when looking up core requests."
    
    This reverts commit 31110d6837ee52fd654729d9e5c4b0c5395abab0.
    
    This is handled properly by StandardMinorOpcode().

diff --git a/dix/registry.c b/dix/registry.c
index 0181858..48e1b5d 100644
--- a/dix/registry.c
+++ b/dix/registry.c
@@ -123,8 +123,6 @@ RegisterResourceName(RESTYPE resource, const char *name)
 const char *
 LookupRequestName(int major, int minor)
 {
-    if (major < 128)
-	minor = 0;
     if (major >= nmajor)
 	return XREGISTRY_UNKNOWN;
     if (minor >= nminor[major])
commit 46521f529841e032e198e5df87974088548a68de
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Tue Oct 23 20:58:48 2007 -0400

    xselinux: Add basic support for selection access control and redirection.
    
    Probably not fully baked yet.  It's difficult to test since so few apps
    actually follow the ICCCM with respect to cut & paste.

diff --git a/Xext/xselinux.c b/Xext/xselinux.c
index ef5be57..f11bc1a 100644
--- a/Xext/xselinux.c
+++ b/Xext/xselinux.c
@@ -65,6 +65,15 @@ typedef struct {
     char *command;
 } SELinuxStateRec;
 
+/* selection manager */
+typedef struct {
+    Atom selection;
+    security_id_t sid;
+} SELinuxSelectionRec;
+
+static ClientPtr selectionManager;
+static Window selectionWindow;
+
 /* audit file descriptor */
 static int audit_fd;
 
@@ -99,6 +108,10 @@ static unsigned numKnownTypes;
 static security_id_t *knownEvents;
 static unsigned numKnownEvents;
 
+/* Array of selection SID structures */
+static SELinuxSelectionRec *knownSelections;
+static unsigned numKnownSelections;
+
 /* 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 }},
@@ -130,6 +143,52 @@ static pointer truep = (pointer)1;
  */
 
 /*
+ * Looks up the SID corresponding to the given selection atom
+ */
+static int
+SELinuxSelectionToSID(Atom selection, SELinuxStateRec *sid_return)
+{
+    const char *name;
+    unsigned i, size;
+
+    for (i = 0; i < numKnownSelections; i++)
+	if (knownSelections[i].selection == selection) {
+	    sid_return->sid = knownSelections[i].sid;
+	    return Success;
+	}
+
+    /* Need to increase size of array */
+    i = numKnownSelections;
+    size = (i + 1) * sizeof(SELinuxSelectionRec);
+    knownSelections = xrealloc(knownSelections, size);
+    if (!knownSelections)
+	return BadAlloc;
+    knownSelections[i].selection = selection;
+
+    /* Look in the mappings of selection names to contexts */
+    name = NameForAtom(selection);
+    if (name) {
+	security_context_t con;
+	security_id_t sid;
+
+	if (selabel_lookup(label_hnd, &con, name, SELABEL_X_SELN) < 0) {
+	    ErrorF("XSELinux: a selection label lookup failed!\n");
+	    return BadValue;
+	}
+	/* Get a SID for context */
+	if (avc_context_to_sid(con, &sid) < 0) {
+	    ErrorF("XSELinux: a context_to_SID call failed!\n");
+	    return BadAlloc;
+	}
+	freecon(con);
+	knownSelections[i].sid = sid_return->sid = sid;
+    } else
+	knownSelections[i].sid = sid_return->sid = unlabeled_sid;
+
+    return Success;
+}
+
+/*
  * Looks up the SID corresponding to the given event type
  */
 static int
@@ -240,10 +299,71 @@ SELinuxDoCheck(int clientIndex, SELinuxStateRec *subj, SELinuxStateRec *obj,
 }
 
 /*
+ * Labels a newly connected client.
+ */
+static void
+SELinuxLabelClient(ClientPtr client)
+{
+    XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn;
+    SELinuxStateRec *state;
+    security_context_t ctx;
+
+    state = dixLookupPrivate(&client->devPrivates, stateKey);
+    sidput(state->sid);
+
+    if (_XSERVTransIsLocal(ci)) {
+	int fd = _XSERVTransGetConnectionNumber(ci);
+	struct ucred creds;
+	socklen_t len = sizeof(creds);
+	char path[PATH_MAX + 1];
+	size_t bytes;
+
+	/* For local clients, can get context from the socket */
+	if (getpeercon(fd, &ctx) < 0)
+	    FatalError("Client %d: couldn't get context from socket\n",
+		       client->index);
+
+	/* Try and determine the client's executable name */
+	memset(&creds, 0, sizeof(creds));
+	if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) < 0)
+	    goto finish;
+
+	snprintf(path, PATH_MAX + 1, "/proc/%d/cmdline", creds.pid);
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+	    goto finish;
+
+	bytes = read(fd, path, PATH_MAX + 1);
+	close(fd);
+	if (bytes <= 0)
+	    goto finish;
+
+	state->command = xalloc(bytes);
+	if (!state->command)
+	    goto finish;
+
+	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)
+	    FatalError("Client %d: couldn't get default remote context\n",
+		       client->index);
+
+finish:
+    /* Get a SID from the context */
+    if (avc_context_to_sid(ctx, &state->sid) < 0)
+	FatalError("Client %d: context_to_sid(%s) failed\n",
+		   client->index, ctx);
+
+    freecon(ctx);
+}
+
+/*
  * Labels initial server objects.
  */
 static void
-SELinuxFixupLabels(void)
+SELinuxLabelInitial(void)
 {
     int i;
     XaceScreenAccessRec srec;
@@ -674,6 +794,28 @@ SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 	rec->status = rc;
 }
 
+static void
+SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+    XaceSelectionAccessRec *rec = (XaceSelectionAccessRec *)calldata;
+    SELinuxStateRec *subj, sel_sid;
+    SELinuxAuditRec auditdata = { rec->client, NULL, 0, 0, 0, NULL };
+    int rc;
+
+    subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+
+    rc = SELinuxSelectionToSID(rec->name, &sel_sid);
+    if (rc != Success) {
+	rec->status = rc;
+	return;
+    }
+
+    rc = SELinuxDoCheck(rec->client->index, subj, &sel_sid,
+			SECCLASS_X_SELECTION, rec->access_mode, &auditdata);
+    if (rc != Success)
+	rec->status = rc;
+}
+
 
 /*
  * DIX Callbacks
@@ -683,63 +825,23 @@ static void
 SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 {
     NewClientInfoRec *pci = calldata;
-    ClientPtr client = pci->client;
-    XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn;
-    SELinuxStateRec *state;
-    security_context_t ctx;
-
-    if (client->clientState != ClientStateInitial)
-	return;
-
-    state = dixLookupPrivate(&client->devPrivates, stateKey);
-    sidput(state->sid);
-
-    if (_XSERVTransIsLocal(ci)) {
-	int fd = _XSERVTransGetConnectionNumber(ci);
-	struct ucred creds;
-	socklen_t len = sizeof(creds);
-	char path[PATH_MAX + 1];
-	size_t bytes;
-
-	/* For local clients, can get context from the socket */
-	if (getpeercon(fd, &ctx) < 0)
-	    FatalError("Client %d: couldn't get context from socket\n",
-		       client->index);
-
-	/* Try and determine the client's executable name */
-	memset(&creds, 0, sizeof(creds));
-	if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) < 0)
-	    goto finish;
-
-	snprintf(path, PATH_MAX + 1, "/proc/%d/cmdline", creds.pid);
-	fd = open(path, O_RDONLY);
-	if (fd < 0)
-	    goto finish;
-
-	bytes = read(fd, path, PATH_MAX + 1);
-	close(fd);
-	if (bytes <= 0)
-	    goto finish;
 
-	state->command = xalloc(bytes);
-	if (!state->command)
-	    goto finish;
-
-	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)
-	    FatalError("Client %d: couldn't get default remote context\n",
-		       client->index);
+    switch (pci->client->clientState) {
+    case ClientStateInitial:
+	SELinuxLabelClient(pci->client);
+	break;
 
-finish:
-    /* Get a SID from the context */
-    if (avc_context_to_sid(ctx, &state->sid) < 0)
-	FatalError("Client %d: context_to_sid(%s) failed\n",
-		   client->index, ctx);
+    case ClientStateRetained:
+    case ClientStateGone:
+	if (pci->client == selectionManager) {
+	    selectionManager = NULL;
+	    selectionWindow = 0;
+	}
+	break;
 
-    freecon(ctx);
+    default:
+	break;
+    }
 }
 
 static void
@@ -788,6 +890,50 @@ SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 	FatalError("XSELinux: Unexpected unlabeled window found\n");
 }
 
+static void
+SELinuxSelectionState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+    SelectionInfoRec *rec = calldata;
+    SELinuxStateRec *subj, *obj;
+
+    switch (rec->kind) {
+    case SelectionSetOwner:
+	/* save off the "real" owner of the selection */
+	rec->selection->alt_client = rec->selection->client;
+	rec->selection->alt_window = rec->selection->window;
+
+	/* figure out the new label for the content */
+	subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+	obj = dixLookupPrivate(&rec->selection->devPrivates, stateKey);
+	sidput(obj->sid);
+
+	if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SELECTION,
+			       &obj->sid) < 0) {
+	    ErrorF("XSELinux: a compute_create call failed!\n");
+	    obj->sid = unlabeled_sid;
+	}
+	break;
+
+    case SelectionGetOwner:
+	/* restore the real owner */
+	rec->selection->window = rec->selection->alt_window;
+	break;
+
+    case SelectionConvertSelection:
+	/* redirect the convert request if necessary */
+	if (selectionManager && selectionManager != rec->client) {
+	    rec->selection->client = selectionManager;
+	    rec->selection->window = selectionWindow;
+	} else {
+	    rec->selection->client = rec->selection->alt_client;
+	    rec->selection->window = rec->selection->alt_window;
+	}
+	break;
+    default:
+	break;
+    }
+}
+
 
 /*
  * DevPrivates Callbacks
@@ -823,9 +969,108 @@ SELinuxStateFree(CallbackListPtr *pcbl, pointer unused, pointer calldata)
  */
 
 static int
+ProcSELinuxQueryVersion(ClientPtr client)
+{
+    SELinuxQueryVersionReply rep;
+    /*
+      REQUEST(SELinuxQueryVersionReq);
+      REQUEST_SIZE_MATCH (SELinuxQueryVersionReq);
+    */
+
+    rep.type = X_Reply;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.server_major = XSELINUX_MAJOR_VERSION;
+    rep.server_minor = XSELINUX_MINOR_VERSION;
+    if (client->swapped) {
+	int n;
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+	swaps(&rep.server_major, n);
+	swaps(&rep.server_minor, n);
+    }
+    WriteToClient(client, sizeof(rep), (char *)&rep);
+    return (client->noClientException);
+}
+
+static int
+ProcSELinuxSetSelectionManager(ClientPtr client)
+{
+    REQUEST(SELinuxSetSelectionManagerReq);
+    WindowPtr pWin;
+    int rc;
+
+    REQUEST_SIZE_MATCH(SELinuxSetSelectionManagerReq);
+
+    if (stuff->window == None) {
+	selectionManager = NULL;
+	selectionWindow = None;
+    } else {
+	rc = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW,
+			       client, DixGetAttrAccess);
+	if (rc != Success)
+	    return rc;
+
+	selectionManager = client;
+	selectionWindow = stuff->window;
+    }
+
+    return Success;
+}
+
+static int
 ProcSELinuxDispatch(ClientPtr client)
 {
-    return BadRequest;
+    REQUEST(xReq);
+    switch (stuff->data) {
+    case X_SELinuxQueryVersion:
+        return ProcSELinuxQueryVersion(client);
+    case X_SELinuxSetSelectionManager:
+	return ProcSELinuxSetSelectionManager(client);
+    default:
+	return BadRequest;
+    }
+}
+
+static int
+SProcSELinuxQueryVersion(ClientPtr client)
+{
+    REQUEST(SELinuxQueryVersionReq);
+    int n;
+
+    REQUEST_SIZE_MATCH (SELinuxQueryVersionReq);
+    swaps(&stuff->client_major,n);
+    swaps(&stuff->client_minor,n);
+    return ProcSELinuxQueryVersion(client);
+}
+
+static int
+SProcSELinuxSetSelectionManager(ClientPtr client)
+{
+    REQUEST(SELinuxSetSelectionManagerReq);
+    int n;
+
+    REQUEST_SIZE_MATCH (SELinuxSetSelectionManagerReq);
+    swapl(&stuff->window,n);
+    return ProcSELinuxSetSelectionManager(client);
+}
+
+static int
+SProcSELinuxDispatch(ClientPtr client)
+{
+    REQUEST(xReq);
+    int n;
+
+    swaps(&stuff->length, n);
+
+    switch (stuff->data) {
+    case X_SELinuxQueryVersion:
+        return SProcSELinuxQueryVersion(client);
+    case X_SELinuxSetSelectionManager:
+        return SProcSELinuxSetSelectionManager(client);
+    default:
+	return BadRequest;
+    }
 }
 
 
@@ -839,6 +1084,7 @@ SELinuxResetProc(ExtensionEntry *extEntry)
     /* Unregister callbacks */
     DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL);
     DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL);
+    DeleteCallback(&SelectionCallback, SELinuxSelectionState, NULL);
 
     XaceDeleteCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL);
     XaceDeleteCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL);
@@ -849,7 +1095,7 @@ SELinuxResetProc(ExtensionEntry *extEntry)
     XaceDeleteCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL);
     XaceDeleteCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL);
     XaceDeleteCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL);
-//    XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
+    XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
     XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL);
     XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep);
 
@@ -863,6 +1109,10 @@ SELinuxResetProc(ExtensionEntry *extEntry)
     avc_active = 0;
 
     /* Free local state */
+    xfree(knownSelections);
+    knownSelections = NULL;
+    numKnownSelections = 0;
+
     xfree(knownEvents);
     knownEvents = NULL;
     numKnownEvents = 0;
@@ -929,6 +1179,7 @@ XSELinuxExtensionInit(INITARGS)
 
     ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL);
     ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL);
+    ret &= AddCallback(&SelectionCallback, SELinuxSelectionState, NULL);
 
     ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL);
     ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL);
@@ -939,7 +1190,7 @@ XSELinuxExtensionInit(INITARGS)
     ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL);
     ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL);
     ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL);
-//    ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
+    ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
     ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL);
     ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep);
     if (!ret)
@@ -948,9 +1199,9 @@ XSELinuxExtensionInit(INITARGS)
     /* Add extension to server */
     extEntry = AddExtension(XSELINUX_EXTENSION_NAME,
 			    XSELinuxNumberEvents, XSELinuxNumberErrors,
-			    ProcSELinuxDispatch, ProcSELinuxDispatch,
+			    ProcSELinuxDispatch, SProcSELinuxDispatch,
 			    SELinuxResetProc, StandardMinorOpcode);
 
     /* Label objects that were created before we could register ourself */
-    SELinuxFixupLabels();
+    SELinuxLabelInitial();
 }
diff --git a/Xext/xselinux.h b/Xext/xselinux.h
index 407b81f..691154d 100644
--- a/Xext/xselinux.h
+++ b/Xext/xselinux.h
@@ -29,6 +29,43 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define XSELinuxNumberEvents		0
 #define XSELinuxNumberErrors		0
 
+/* Extension protocol */
+#define X_SELinuxQueryVersion		0
+#define X_SELinuxSetSelectionManager	1
+
+typedef struct _SELinuxQueryVersion {
+    CARD8   reqType;
+    CARD8   SELinuxReqType;
+    CARD16  length;
+    CARD8   client_major;
+    CARD8   client_minor;
+    CARD16  unused;
+} SELinuxQueryVersionReq;
+#define sz_SELinuxQueryVersionReq 8
+
+typedef struct {
+    CARD8   type;
+    CARD8   pad1;
+    CARD16  sequenceNumber;
+    CARD32  length;
+    CARD16  server_major;
+    CARD16  server_minor;
+    CARD32  pad2;
+    CARD32  pad3;
+    CARD32  pad4;
+    CARD32  pad5;
+    CARD32  pad6; 
+} SELinuxQueryVersionReply;
+#define sz_SELinuxQueryVersionReply  32
+
+typedef struct _SELinuxSetSelectionManager {
+    CARD8   reqType;
+    CARD8   SELinuxReqType;
+    CARD16  length;
+    CARD32  window;
+} SELinuxSetSelectionManagerReq;
+#define sz_SELinuxSetSelectionManagerReq 8
+
 /* Private Flask definitions */
 #define SECCLASS_X_DRAWABLE		1
 #define SECCLASS_X_SCREEN		2
commit 825f09dffd94cfcd0562a01c5181998503851461
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Tue Oct 23 17:12:57 2007 -0400

    xace: Still more changes to selection code.  Removed the SelectionPtr from
    the hook - the hook only needs the Atom to control access to the selection
    object.  Upgraded the SelectionCallback to take a client argument and
    additional type codes so that it can be used for redirection.

diff --git a/Xext/xace.c b/Xext/xace.c
index b126661..7b27ecd 100644
--- a/Xext/xace.c
+++ b/Xext/xace.c
@@ -177,7 +177,6 @@ int XaceHook(int hook, ...)
 	    XaceSelectionAccessRec rec = {
 		va_arg(ap, ClientPtr),
 		va_arg(ap, Atom),
-		va_arg(ap, Selection*),
 		va_arg(ap, Mask),
 		Success /* default allow */
 	    };
diff --git a/Xext/xacestr.h b/Xext/xacestr.h
index 1c61543..045f836 100644
--- a/Xext/xacestr.h
+++ b/Xext/xacestr.h
@@ -112,7 +112,6 @@ typedef struct {
 typedef struct {
     ClientPtr client;
     Atom name;
-    Selection *selection;
     Mask access_mode;
     int status;
 } XaceSelectionAccessRec;
diff --git a/dix/dispatch.c b/dix/dispatch.c
index 2cfeb2d..814c2a8 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -1005,6 +1005,11 @@ ProcSetSelectionOwner(ClientPtr client)
     {
 	int i = 0;
 
+	rc = XaceHook(XACE_SELECTION_ACCESS, client, stuff->selection,
+		      DixSetAttrAccess);
+	if (rc != Success)
+	    return rc;
+
 	/*
 	 * First, see if the selection is already set... 
 	 */
@@ -1022,12 +1027,6 @@ ProcSetSelectionOwner(ClientPtr client)
             if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged)
 		== EARLIER)
 		return Success;
-
-	    rc = XaceHook(XACE_SELECTION_ACCESS, client, stuff->selection,
-			  CurrentSelections + i, DixSetAttrAccess);
-	    if (rc != Success)
-		return rc;
-
 	    if (CurrentSelections[i].client &&
 		(!pWin || (CurrentSelections[i].client != client)))
 	    {
@@ -1058,10 +1057,6 @@ ProcSetSelectionOwner(ClientPtr client)
 	    CurrentSelections = newsels;
 	    CurrentSelections[i].selection = stuff->selection;
 	    CurrentSelections[i].devPrivates = NULL;
-	    rc = XaceHook(XACE_SELECTION_ACCESS, client, stuff->selection,
-			  CurrentSelections + i, DixSetAttrAccess);
-	    if (rc != Success)
-		return rc;
 	}
         CurrentSelections[i].lastTimeChanged = time;
 	CurrentSelections[i].window = stuff->window;
@@ -1072,6 +1067,7 @@ ProcSetSelectionOwner(ClientPtr client)
 	    SelectionInfoRec	info;
 
 	    info.selection = &CurrentSelections[i];
+	    info.client = client;
 	    info.kind= SelectionSetOwner;
 	    CallCallbacks(&SelectionCallback, &info);
 	}
@@ -1095,23 +1091,29 @@ ProcGetSelectionOwner(ClientPtr client)
 	int rc, i;
         xGetSelectionOwnerReply reply;
 
-	i = 0;
-        while ((i < NumCurrentSelections) && 
-	       CurrentSelections[i].selection != stuff->id) i++;
-
 	rc = XaceHook(XACE_SELECTION_ACCESS, client, stuff->id,
-		      CurrentSelections + i, DixGetAttrAccess);
+		      DixGetAttrAccess);
 	if (rc != Success)
 	    return rc;
 
+	i = 0;
+        while ((i < NumCurrentSelections) && 
+	       CurrentSelections[i].selection != stuff->id) i++;
         reply.type = X_Reply;
 	reply.length = 0;
 	reply.sequenceNumber = client->sequence;
-        if (i < NumCurrentSelections)
+	if (i < NumCurrentSelections) {
+	    if (SelectionCallback) {
+		SelectionInfoRec info;
+
+		info.selection = &CurrentSelections[i];
+		info.client = client;
+		info.kind= SelectionGetOwner;
+		CallCallbacks(&SelectionCallback, &info);
+	    }
             reply.owner = CurrentSelections[i].window;
-        else
+	} else
             reply.owner = None;
-
         WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply);
         return(client->noClientException);
     }
@@ -1135,6 +1137,10 @@ ProcConvertSelection(ClientPtr client)
     rc = dixLookupWindow(&pWin, stuff->requestor, client, DixSetAttrAccess);
     if (rc != Success)
         return rc;
+    rc = XaceHook(XACE_SELECTION_ACCESS, client, stuff->selection,
+		  DixReadAccess);
+    if (rc != Success)
+	return rc;
 
     paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target));
     if (stuff->property != None)
@@ -1146,11 +1152,15 @@ ProcConvertSelection(ClientPtr client)
 	i = 0;
 	while ((i < NumCurrentSelections) && 
 	       CurrentSelections[i].selection != stuff->selection) i++;
-	if ((i < NumCurrentSelections) &&
-	    (CurrentSelections[i].window != None) &&
-	    XaceHook(XACE_SELECTION_ACCESS, client, stuff->selection,
-		     CurrentSelections + i, DixReadAccess) == Success)
-	{        
+	if (i < NumCurrentSelections && CurrentSelections[i].window != None) {
+	    if (SelectionCallback) {
+		SelectionInfoRec info;
+
+		info.selection = &CurrentSelections[i];
+		info.client = client;
+		info.kind= SelectionConvertSelection;
+		CallCallbacks(&SelectionCallback, &info);
+	    }
 	    event.u.u.type = SelectionRequest;
 	    event.u.selectionRequest.time = stuff->time;
 	    event.u.selectionRequest.owner = CurrentSelections[i].window;
diff --git a/include/dix.h b/include/dix.h
index 09ed6d9..30fdc45 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -594,12 +594,15 @@ extern CallbackListPtr SelectionCallback;
 
 typedef enum {
     SelectionSetOwner,
+    SelectionGetOwner,
+    SelectionConvertSelection,
     SelectionWindowDestroy,
     SelectionClientClose
 } SelectionCallbackKind;
 
 typedef struct {
     struct _Selection	    *selection;
+    ClientPtr		    client;
     SelectionCallbackKind   kind;
 } SelectionInfoRec;
 
commit 660557593ea961948722298ea8ffba83891c9914
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Tue Oct 23 14:46:37 2007 -0400

    xselinux: Remove synthetic bit when looking up event type.

diff --git a/Xext/xselinux.c b/Xext/xselinux.c
index 183a047..ef5be57 100644
--- a/Xext/xselinux.c
+++ b/Xext/xselinux.c
@@ -133,10 +133,11 @@ static pointer truep = (pointer)1;
  * Looks up the SID corresponding to the given event type
  */
 static int
-SELinuxEventToSID(int type, SELinuxStateRec *sid_return)
+SELinuxEventToSID(unsigned type, SELinuxStateRec *sid_return)
 {
     const char *name = LookupEventName(type);
     security_context_t con;
+    type &= 127;
 
     if (type >= numKnownEvents) {
 	/* Need to increase size of classes array */
commit d7db549db41a27aef28cff9bfb7973bc741f88b2
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Tue Oct 23 14:08:54 2007 -0400

    xselinux: Unregister callbacks on server reset.

diff --git a/Xext/xselinux.c b/Xext/xselinux.c
index 14a2270..183a047 100644
--- a/Xext/xselinux.c
+++ b/Xext/xselinux.c
@@ -121,6 +121,9 @@ static struct security_class_mapping map[] = {
 /* forward declarations */
 static void SELinuxScreen(CallbackListPtr *, pointer, pointer);
 
+/* "true" pointer value for use as callback data */
+static pointer truep = (pointer)1;
+
 
 /*
  * Support Routines
@@ -832,8 +835,24 @@ ProcSELinuxDispatch(ClientPtr client)
 static void
 SELinuxResetProc(ExtensionEntry *extEntry)
 {
-    /* XXX unregister all callbacks here */
-
+    /* Unregister callbacks */
+    DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL);
+    DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL);
+
+    XaceDeleteCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL);
+    XaceDeleteCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL);
+    XaceDeleteCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL);
+    XaceDeleteCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL);
+    XaceDeleteCallback(XACE_SEND_ACCESS, SELinuxSend, NULL);
+    XaceDeleteCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL);
+    XaceDeleteCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL);
+    XaceDeleteCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL);
+    XaceDeleteCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL);
+//    XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
+    XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL);
+    XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep);
+
+    /* Tear down SELinux stuff */
     selabel_close(label_hnd);
     label_hnd = NULL;
 
@@ -842,6 +861,7 @@ SELinuxResetProc(ExtensionEntry *extEntry)
     avc_destroy();
     avc_active = 0;
 
+    /* Free local state */
     xfree(knownEvents);
     knownEvents = NULL;
     numKnownEvents = 0;
@@ -906,21 +926,21 @@ XSELinuxExtensionInit(INITARGS)
     ret &= dixRegisterPrivateInitFunc(stateKey, SELinuxStateInit, NULL);
     ret &= dixRegisterPrivateDeleteFunc(stateKey, SELinuxStateFree, NULL);
 
-    ret &= AddCallback(&ClientStateCallback, SELinuxClientState, 0);
-    ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, 0);
-
-    ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, 0);
-    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_CLIENT_ACCESS, SELinuxClient, 0);
-    ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, 0);
-    ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, 0);
-//    ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, 0);
-    ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, 0);
-    ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, &ret);
+    ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL);
+    ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL);
+
+    ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL);
+    ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL);
+    ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL);
+    ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL);
+    ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, NULL);
+    ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL);
+    ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL);
+    ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL);
+    ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL);
+//    ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
+    ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL);
+    ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep);
     if (!ret)
 	FatalError("XSELinux: Failed to register one or more callbacks\n");
 
commit 9e0a468af19d8e46330bcff37c9adc5e11d3aee7
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Tue Oct 23 13:35:30 2007 -0400

    xace: try to pretend events were sent when a denial occurs.
    
    Probably need to redo the error return paths in these functions
    at some point.

diff --git a/dix/events.c b/dix/events.c
index 246220f..24de947 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1754,7 +1754,7 @@ DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count,
 	    !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
 	    return 0;
 	if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
-	    nondeliveries--;
+	    /* do nothing */;
 	else if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
 					     pWin->eventMask, filter, grab)) )
 	{
@@ -1785,7 +1785,7 @@ DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count,
 	{
 	    if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
 			 count))
-		nondeliveries--;
+		/* do nothing */;
 	    else if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
 					  other->mask[mskidx], filter, grab)) )
 	    {
@@ -1884,7 +1884,7 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
 			wClient(pWin), NullGrab, pWin->eventMask, filter);
 #endif
 	if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
-	    return 0;
+	    return 1; /* don't send, but pretend we did */
 	return TryClientEvents(wClient(pWin), pEvents, count,
 			       pWin->eventMask, filter, NullGrab);
     }
@@ -1901,7 +1901,7 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
 #endif
 	    if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
 			 count))
-		return 0;
+		return 1; /* don't send, but pretend we did */
 	    return TryClientEvents(rClient(other), pEvents, count,
 				   other->mask, filter, NullGrab);
 	}
@@ -2896,9 +2896,9 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
 	if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count))
 	    return;
     }
-    /* just deliver it to the focus window */
     if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count))
 	return;
+    /* just deliver it to the focus window */
     FixUpEventFromWindow(xE, focus, None, FALSE);
     if (xE->u.u.type & EXTENSION_EVENT_BASE)
 	mskidx = keybd->id;
@@ -2947,9 +2947,11 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
     if (!deliveries)
     {
 	FixUpEventFromWindow(xE, grab->window, None, TRUE);
-	if (!XaceHook(XACE_SEND_ACCESS, 0, thisDev, grab->window, xE, count) &&
-	    !XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), grab->window, xE,
-		      count))
+	if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, grab->window, xE, count) ||
+	    XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), grab->window, xE,
+		     count))
+	    deliveries = 1; /* don't send, but pretend we did */
+	else
 	    deliveries = TryClientEvents(rClient(grab), xE, count,
 					 (Mask)grab->eventMask,
 					 filters[xE->u.u.type], grab);


More information about the xorg-commit mailing list