xserver: Branch 'master'

Eamon Walsh ewalsh at kemper.freedesktop.org
Tue Mar 4 19:41:05 PST 2008


 Xext/xselinux.c | 1016 ++++++++++++++++++++++++++++++++++++--------------------
 Xext/xselinux.h |  102 ++---
 2 files changed, 695 insertions(+), 423 deletions(-)

New commits:
commit d4101140f4e569f18554cf0cbf43138d08bd1277
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Tue Mar 4 22:39:41 2008 -0500

    xselinux: Implement polyinstantiation support and related protocol.

diff --git a/Xext/xselinux.c b/Xext/xselinux.c
index a7d3999..18c6526 100644
--- a/Xext/xselinux.c
+++ b/Xext/xselinux.c
@@ -60,31 +60,36 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * Globals
  */
 
-/* private state record */
+/* private state keys */
 static DevPrivateKey subjectKey = &subjectKey;
 static DevPrivateKey objectKey = &objectKey;
+static DevPrivateKey dataKey = &dataKey;
 
-/* This is what we store for security state */
+/* subject state (clients and devices only) */
 typedef struct {
     security_id_t sid;
+    security_id_t dev_create_sid;
+    security_id_t win_create_sid;
+    security_id_t sel_create_sid;
+    security_id_t prp_create_sid;
+    security_id_t sel_use_sid;
+    security_id_t prp_use_sid;
     struct avc_entry_ref aeref;
     char *command;
     int privileged;
 } SELinuxSubjectRec;
 
+/* object state */
 typedef struct {
     security_id_t sid;
     int poly;
 } SELinuxObjectRec;
 
-/* selection manager */
+/* selection and property atom cache */
 typedef struct {
-    Atom selection;
-    security_id_t sid;
-} SELinuxSelectionRec;
-
-static ClientPtr securityManager;
-static Window securityWindow;
+    SELinuxObjectRec prp;
+    SELinuxObjectRec sel;
+} SELinuxAtomRec;
 
 /* audit file descriptor */
 static int audit_fd;
@@ -123,9 +128,9 @@ static unsigned numKnownTypes;
 static security_id_t *knownEvents;
 static unsigned numKnownEvents;
 
-/* Array of selection SID structures */
-static SELinuxSelectionRec *knownSelections;
-static unsigned numKnownSelections;
+/* Array of property and selection SID structures */
+static SELinuxAtomRec *knownAtoms;
+static unsigned numKnownAtoms;
 
 /* dynamically allocated security classes and permissions */
 static struct security_class_mapping map[] = {
@@ -135,7 +140,7 @@ static struct security_class_mapping map[] = {
     { "x_font", { "", "", "destroy", "create", "getattr", "", "", "", "", "", "", "", "add_glyph", "remove_glyph", "", "", "", "", "", "", "", "", "", "", "use", NULL }},
     { "x_colormap", { "read", "write", "destroy", "create", "getattr", "", "", "", "", "", "", "", "add_color", "remove_color", "", "", "", "", "", "", "install", "uninstall", "", "", "use", NULL }},
     { "x_property", { "read", "write", "destroy", "create", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "write", NULL }},
-    { "x_selection", { "read", "", "", "", "getattr", "setattr", NULL }},
+    { "x_selection", { "read", "", "", "setattr", "getattr", "setattr", NULL }},
     { "x_cursor", { "read", "write", "destroy", "create", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "use", NULL }},
     { "x_client", { "", "", "destroy", "", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "manage", NULL }},
     { "x_device", { "read", "write", "", "", "getattr", "setattr", "", "", "", "getfocus", "setfocus", "", "", "", "", "", "", "grab", "freeze", "force_cursor", "", "", "", "", "use", "manage", "", "bell", NULL }},
@@ -159,48 +164,164 @@ static pointer truep = (pointer)1;
  */
 
 /*
- * Looks up the SID corresponding to the given selection atom
+ * Looks up a name in the selection or property mappings
  */
 static int
-SELinuxSelectionToSID(Atom selection, SELinuxObjectRec *sid_return)
+SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec *obj, int map, int polymap)
 {
-    const char *name;
-    unsigned i, size;
+    const char *name = NameForAtom(atom);
+    security_context_t ctx;
+    int rc = Success;
 
-    for (i = 0; i < numKnownSelections; i++)
-	if (knownSelections[i].selection == selection) {
-	    sid_return->sid = knownSelections[i].sid;
-	    return Success;
-	}
+    obj->poly = 1;
 
-    /* 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 names to contexts */
+    if (selabel_lookup(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) {
+	ErrorF("SELinux: a property label lookup failed!\n");
+	return BadValue;
+    }
 
-    /* Look in the mappings of selection names to contexts */
-    name = NameForAtom(selection);
-    if (name) {
-	security_context_t con;
-	security_id_t sid;
+    /* Get a SID for context */
+    if (avc_context_to_sid(ctx, &obj->sid) < 0) {
+	ErrorF("SELinux: a context_to_SID call failed!\n");
+	rc = BadAlloc;
+    }
 
-	if (selabel_lookup(label_hnd, &con, name, SELABEL_X_SELN) < 0) {
-	    ErrorF("SELinux: a selection label lookup failed!\n");
-	    return BadValue;
-	}
-	/* Get a SID for context */
-	if (avc_context_to_sid(con, &sid) < 0) {
-	    ErrorF("SELinux: a context_to_SID call failed!\n");
+    freecon(ctx);
+    return rc;
+}
+
+/*
+ * Looks up the SID corresponding to the given property or selection atom
+ */
+static int
+SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn)
+{
+    SELinuxObjectRec *obj;
+    int rc, map, polymap;
+
+    if (atom >= numKnownAtoms) {
+	/* Need to increase size of atoms array */
+	unsigned size = sizeof(SELinuxAtomRec);
+	knownAtoms = xrealloc(knownAtoms, (atom + 1) * size);
+	if (!knownAtoms)
 	    return BadAlloc;
+	memset(knownAtoms + numKnownAtoms, 0,
+	       (atom - numKnownAtoms + 1) * size);
+	numKnownAtoms = atom + 1;
+    }
+
+    if (prop) {
+	obj = &knownAtoms[atom].prp;
+	map = SELABEL_X_PROP;
+	polymap = SELABEL_X_POLYPROP;
+    } else {
+	obj = &knownAtoms[atom].sel;
+	map = SELABEL_X_SELN;
+	polymap = SELABEL_X_POLYSELN;
+    }
+
+    if (!obj->sid) {
+	rc = SELinuxAtomToSIDLookup(atom, obj, map, polymap);
+	if (rc != Success)
+	    goto out;
+    }
+
+    *obj_rtn = obj;
+    rc = Success;
+out:
+    return rc;
+}
+
+/*
+ * Looks up a SID for a selection/subject pair
+ */
+static int
+SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec *subj,
+		      security_id_t *sid_rtn, int *poly_rtn)
+{
+    int rc;
+    SELinuxObjectRec *obj;
+    security_id_t tsid;
+
+    /* Get the default context and polyinstantiation bit */
+    rc = SELinuxAtomToSID(selection, 0, &obj);
+    if (rc != Success)
+	return rc;
+
+    /* Check for an override context next */
+    if (subj->sel_use_sid) {
+	sidget(tsid = subj->sel_use_sid);
+	goto out;
+    }
+
+    sidget(tsid = obj->sid);
+
+    /* Polyinstantiate if necessary to obtain the final SID */
+    if (obj->poly) {
+	sidput(tsid);
+	if (avc_compute_member(subj->sid, obj->sid,
+			       SECCLASS_X_SELECTION, &tsid) < 0) {
+	    ErrorF("SELinux: a compute_member call failed!\n");
+	    return BadValue;
 	}
-	freecon(con);
-	knownSelections[i].sid = sid_return->sid = sid;
-    } else
-	knownSelections[i].sid = sid_return->sid = unlabeled_sid;
+    }
+out:
+    *sid_rtn = tsid;
+    if (poly_rtn)
+	*poly_rtn = obj->poly;
+    return Success;
+}
 
+/*
+ * Looks up a SID for a property/subject pair
+ */
+static int
+SELinuxPropertyToSID(Atom property, SELinuxSubjectRec *subj,
+		     security_id_t *sid_rtn, int *poly_rtn)
+{
+    int rc;
+    SELinuxObjectRec *obj;
+    security_id_t tsid, tsid2;
+
+    /* Get the default context and polyinstantiation bit */
+    rc = SELinuxAtomToSID(property, 1, &obj);
+    if (rc != Success)
+	return rc;
+
+    /* Check for an override context next */
+    if (subj->prp_use_sid) {
+	sidget(tsid = subj->prp_use_sid);
+	goto out;
+    }
+
+    /* Perform a transition */
+    if (avc_compute_create(subj->sid, obj->sid,
+			   SECCLASS_X_PROPERTY, &tsid) < 0) {
+	ErrorF("SELinux: a compute_create call failed!\n");
+	return BadValue;
+    }
+
+    /* Polyinstantiate if necessary to obtain the final SID */
+    if (obj->poly) {
+	tsid2 = tsid;
+	if (avc_compute_member(subj->sid, tsid2,
+			       SECCLASS_X_PROPERTY, &tsid) < 0) {
+	    ErrorF("SELinux: a compute_member call failed!\n");
+	    sidput(tsid2);
+	    return BadValue;
+	}
+	sidput(tsid2);
+    }
+out:
+    *sid_rtn = tsid;
+    if (poly_rtn)
+	*poly_rtn = obj->poly;
     return Success;
 }
 
@@ -383,8 +504,7 @@ finish:
 	FatalError("SELinux: client %d: context_to_sid(%s) failed\n",
 		   client->index, ctx);
 
-    sidget(subj->sid);
-    obj->sid = subj->sid;
+    sidget(obj->sid = subj->sid);
     freecon(ctx);
 }
 
@@ -415,8 +535,7 @@ SELinuxLabelInitial(void)
     if (avc_context_to_sid(ctx, &subj->sid) < 0)
 	FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx);
 
-    sidget(subj->sid);
-    obj->sid = subj->sid;
+    sidget(obj->sid = subj->sid);
     freecon(ctx);
 
     srec.client = serverClient;
@@ -434,6 +553,44 @@ SELinuxLabelInitial(void)
     }
 }
 
+/*
+ * Labels new resource objects.
+ */
+static int
+SELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj,
+		     SELinuxObjectRec *obj, security_class_t class)
+{
+    int offset;
+    security_id_t tsid;
+
+    /* Check for a create context */
+    if (rec->rtype == RT_WINDOW && subj->win_create_sid) {
+	sidget(obj->sid = subj->win_create_sid);
+	return Success;
+    }
+
+    if (rec->parent)
+	offset = dixLookupPrivateOffset(rec->ptype);
+
+    if (rec->parent && offset >= 0) {
+	/* Use the SID of the parent object in the labeling operation */
+	PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset);
+	SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey);
+	tsid = pobj->sid;
+    } else {
+	/* Use the SID of the subject */
+	tsid = subj->sid;
+    }
+
+    /* Perform a transition to obtain the final SID */
+    if (avc_compute_create(subj->sid, tsid, class, &obj->sid) < 0) {
+	ErrorF("SELinux: a compute_create call failed!\n");
+	return BadValue;
+    }
+
+    return Success;
+}
+
 
 /*
  * Libselinux Callbacks
@@ -525,11 +682,15 @@ SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 	sidput(dsubj->sid);
 	sidput(obj->sid);
 
-	/* Label the device directly with the process SID */
-	sidget(subj->sid);
-	obj->sid = subj->sid;
-	sidget(subj->sid);
-	dsubj->sid = subj->sid;
+	if (subj->dev_create_sid) {
+	    /* Label the device with the create context */
+	    sidget(obj->sid = subj->dev_create_sid);
+	    sidget(dsubj->sid = subj->dev_create_sid);
+	} else {
+	    /* Label the device directly with the process SID */
+	    sidget(obj->sid = subj->sid);
+	    sidget(dsubj->sid = subj->sid);
+	}
     }
 
     /* XXX only check read permission on XQueryKeymap */
@@ -685,13 +846,76 @@ SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 }
 
 static void
+SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+    XaceSelectionAccessRec *rec = calldata;
+    SELinuxSubjectRec *subj;
+    SELinuxObjectRec *obj, *data;
+    Selection *pSel = *rec->ppSel;
+    Atom name = pSel->selection;
+    SELinuxAuditRec auditdata = { .client = rec->client, .selection = name };
+    security_id_t tsid;
+    int rc;
+
+    subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+    obj = dixLookupPrivate(&pSel->devPrivates, objectKey);
+
+    /* If this is a new object that needs labeling, do it now */
+    if (rec->access_mode & DixCreateAccess) {
+	sidput(obj->sid);
+	rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly);
+	if (rc != Success)
+	    obj->sid = unlabeled_sid;
+    }
+    /* If this is a polyinstantiated object, find the right instance */
+    else if (obj->poly) {
+	rc = SELinuxSelectionToSID(name, subj, &tsid, NULL);
+	if (rc != Success) {
+	    rec->status = rc;
+	    return;
+	}
+	while (pSel->selection != name || obj->sid != tsid) {
+	    if ((pSel = pSel->next) == NULL)
+		break;
+	    obj = dixLookupPrivate(&pSel->devPrivates, objectKey);
+	}
+	sidput(tsid);
+	
+	if (pSel)
+	    *rec->ppSel = pSel;
+	else {
+	    rec->status = BadMatch;
+	    return;
+	}
+    }
+
+    /* Perform the security check */
+    rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, rec->access_mode,
+			&auditdata);
+    if (rc != Success)
+	rec->status = rc;
+
+    /* Label the content (advisory only) */
+    if (rec->access_mode & DixSetAttrAccess) {
+	data = dixLookupPrivate(&pSel->devPrivates, dataKey);
+	sidput(data->sid);
+	if (subj->sel_create_sid)
+	    sidget(data->sid = subj->sel_create_sid);
+	else
+	    sidget(data->sid = obj->sid);
+    }
+}
+
+static void
 SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 {
     XacePropertyAccessRec *rec = calldata;
     SELinuxSubjectRec *subj;
-    SELinuxObjectRec *obj;
-    SELinuxAuditRec auditdata = { .client = rec->client };
+    SELinuxObjectRec *obj, *data;
     PropertyPtr pProp = *rec->ppProp;
+    Atom name = pProp->propertyName;
+    SELinuxAuditRec auditdata = { .client = rec->client, .property = name };
+    security_id_t tsid;
     int rc;
 
     subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
@@ -699,42 +923,50 @@ SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 
     /* If this is a new object that needs labeling, do it now */
     if (rec->access_mode & DixCreateAccess) {
-	const char *name = NameForAtom(pProp->propertyName);
-	security_context_t con;
-	security_id_t sid;
-
-	/* Look in the mappings of property names to contexts */
-	if (selabel_lookup(label_hnd, &con, name, SELABEL_X_PROP) < 0) {
-	    ErrorF("SELinux: a property label lookup failed!\n");
-	    rec->status = BadValue;
+	sidput(obj->sid);
+	rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly);
+	if (rc != Success) {
+	    rec->status = rc;
 	    return;
 	}
-	/* Get a SID for context */
-	if (avc_context_to_sid(con, &sid) < 0) {
-	    ErrorF("SELinux: a context_to_SID call failed!\n");
-	    rec->status = BadAlloc;
+    }
+    /* If this is a polyinstantiated object, find the right instance */
+    else if (obj->poly) {
+	rc = SELinuxPropertyToSID(name, subj, &tsid, NULL);
+	if (rc != Success) {
+	    rec->status = rc;
 	    return;
 	}
+	while (pProp->propertyName != name || obj->sid != tsid) {
+	    if ((pProp = pProp->next) == NULL)
+		break;
+	    obj = dixLookupPrivate(&pProp->devPrivates, objectKey);
+	}
+	sidput(tsid);
 
-	sidput(obj->sid);
-
-	/* Perform a transition to obtain the final SID */
-	if (avc_compute_create(subj->sid, sid, SECCLASS_X_PROPERTY,
-			       &obj->sid) < 0) {
-	    ErrorF("SELinux: a SID transition call failed!\n");
-	    freecon(con);
-	    rec->status = BadValue;
+	if (pProp)
+	    *rec->ppProp = pProp;
+	else {
+	    rec->status = BadMatch;
 	    return;
 	}
-	freecon(con);
     }
 
     /* Perform the security check */
-    auditdata.property = pProp->propertyName;
     rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode,
 			&auditdata);
     if (rc != Success)
 	rec->status = rc;
+
+    /* Label the content (advisory only) */
+    if (rec->access_mode & DixWriteAccess) {
+	data = dixLookupPrivate(&pProp->devPrivates, dataKey);
+	sidput(data->sid);
+	if (subj->prp_create_sid)
+	    sidget(data->sid = subj->prp_create_sid);
+	else
+	    sidget(data->sid = obj->sid);
+    }
 }
 
 static void
@@ -742,14 +974,13 @@ SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 {
     XaceResourceAccessRec *rec = calldata;
     SELinuxSubjectRec *subj;
-    SELinuxObjectRec *obj, *sobj, *pobj;
+    SELinuxObjectRec *obj;
     SELinuxAuditRec auditdata = { .client = rec->client };
     PrivateRec **privatePtr;
     security_class_t class;
     int rc, offset;
 
     subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
-    sobj = dixLookupPrivate(&rec->client->devPrivates, objectKey);
 
     /* Determine if the resource object has a devPrivates field */
     offset = dixLookupPrivateOffset(rec->rtype);
@@ -767,21 +998,9 @@ SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 
     /* If this is a new object that needs labeling, do it now */
     if (rec->access_mode & DixCreateAccess && offset >= 0) {
-	if (rec->parent)
-	    offset = dixLookupPrivateOffset(rec->ptype);
-	if (rec->parent && offset >= 0)
-	    /* Use the SID of the parent object in the labeling operation */
-	    pobj = dixLookupPrivate(DEVPRIV_AT(rec->parent, offset), objectKey);
-	else
-	    /* Use the SID of the subject */
-	    pobj = sobj;
-
-	sidput(obj->sid);
-
-	/* Perform a transition to obtain the final SID */
-	if (avc_compute_create(subj->sid, pobj->sid, class, &obj->sid) < 0) {
-	    ErrorF("SELinux: a compute_create call failed!\n");
-	    rec->status = BadValue;
+	rc = SELinuxLabelResource(rec, subj, obj, class);
+	if (rc != Success) {
+	    rec->status = rc;
 	    return;
 	}
     }
@@ -864,34 +1083,6 @@ SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 	rec->status = rc;
 }
 
-static void
-SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata)
-{
-    XaceSelectionAccessRec *rec = (XaceSelectionAccessRec *)calldata;
-    SELinuxSubjectRec *subj;
-    SELinuxObjectRec sel_sid;
-    SELinuxAuditRec auditdata = { .client = rec->client };
-    Selection *pSel = *rec->ppSel;
-    int rc;
-
-    if (rec->access_mode & DixCreateAccess)
-	return; /* don't use create currently */
-
-    subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
-
-    rc = SELinuxSelectionToSID(pSel->selection, &sel_sid);
-    if (rc != Success) {
-	rec->status = rc;
-	return;
-    }
-
-    auditdata.selection = pSel->selection;
-    rc = SELinuxDoCheck(subj, &sel_sid, SECCLASS_X_SELECTION, rec->access_mode,
-			&auditdata);
-    if (rc != Success)
-	rec->status = rc;
-}
-
 
 /*
  * DIX Callbacks
@@ -907,14 +1098,6 @@ SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 	SELinuxLabelClient(pci->client);
 	break;
 
-    case ClientStateRetained:
-    case ClientStateGone:
-	if (pci->client == securityManager) {
-	    securityManager = NULL;
-	    securityWindow = 0;
-	}
-	break;
-
     default:
 	break;
     }
@@ -965,18 +1148,6 @@ SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 	FatalError("SELinux: Unexpected unlabeled window found\n");
 }
 
-static void
-SELinuxSelectionState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
-{
-    SelectionInfoRec *rec = calldata;
-
-    switch (rec->kind) {
-    case SelectionSetOwner:
-    default:
-	break;
-    }
-}
-
 
 /*
  * DevPrivates Callbacks
@@ -1002,8 +1173,13 @@ SELinuxSubjectFree(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 
     xfree(subj->command);
 
-    if (avc_active)
+    if (avc_active) {
 	sidput(subj->sid);
+	sidput(subj->dev_create_sid);
+	sidput(subj->win_create_sid);
+	sidput(subj->sel_create_sid);
+	sidput(subj->prp_create_sid);
+    }
 }
 
 static void
@@ -1031,6 +1207,21 @@ SELinuxObjectFree(CallbackListPtr *pcbl, pointer unused, pointer calldata)
  * Extension Dispatch
  */
 
+#define CTX_DEV offsetof(SELinuxSubjectRec, dev_create_sid)
+#define CTX_WIN offsetof(SELinuxSubjectRec, win_create_sid)
+#define CTX_PRP offsetof(SELinuxSubjectRec, prp_create_sid)
+#define CTX_SEL offsetof(SELinuxSubjectRec, sel_create_sid)
+#define USE_PRP offsetof(SELinuxSubjectRec, prp_use_sid)
+#define USE_SEL offsetof(SELinuxSubjectRec, sel_use_sid)
+
+typedef struct {
+    security_context_t octx;
+    security_context_t dctx;
+    CARD32 octx_len;
+    CARD32 dctx_len;
+    CARD32 id;
+} SELinuxListItemRec;
+
 static int
 ProcSELinuxQueryVersion(ClientPtr client)
 {
@@ -1053,65 +1244,101 @@ ProcSELinuxQueryVersion(ClientPtr client)
 }
 
 static int
-ProcSELinuxSetSecurityManager(ClientPtr client)
+SELinuxSendContextReply(ClientPtr client, security_id_t sid)
 {
-    WindowPtr pWin;
-    int rc;
-
-    REQUEST(SELinuxSetSecurityManagerReq);
-    REQUEST_SIZE_MATCH(SELinuxSetSecurityManagerReq);
-
-    if (stuff->window == None) {
-	securityManager = NULL;
-	securityWindow = None;
-    } else {
-	rc = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW,
-			       client, DixGetAttrAccess);
-	if (rc != Success)
-	    return rc;
+    SELinuxGetContextReply rep;
+    security_context_t ctx = NULL;
+    int len = 0;
 
-	securityManager = client;
-	securityWindow = stuff->window;
+    if (sid) {
+	if (avc_sid_to_context(sid, &ctx) < 0)
+	    return BadValue;
+	len = strlen(ctx) + 1;
     }
 
-    return Success;
-}
-
-static int
-ProcSELinuxGetSecurityManager(ClientPtr client)
-{
-    SELinuxGetSecurityManagerReply rep;
-
     rep.type = X_Reply;
-    rep.length = 0;
+    rep.length = (len + 3) >> 2;
     rep.sequenceNumber = client->sequence;
-    rep.window = securityWindow;
+    rep.context_len = len;
+
     if (client->swapped) {
 	int n;
-	swaps(&rep.sequenceNumber, n);
 	swapl(&rep.length, n);
-	swapl(&rep.window, n);
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.context_len, n);
     }
-    WriteToClient(client, sizeof(rep), (char *)&rep);
-    return (client->noClientException);
+
+    WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep);
+    WriteToClient(client, len, ctx);
+    freecon(ctx);
+    return client->noClientException;
 }
 
 static int
-ProcSELinuxSetDeviceCreateContext(ClientPtr client)
+ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
 {
+    PrivateRec **privPtr = &client->devPrivates;
+    security_id_t *pSid;
+    security_context_t ctx;
+    char *ptr;
+
+    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 (offset == CTX_DEV) {
+	/* Device create context currently requires manage permission */
+	int rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
+	if (rc != Success)
+	    return rc;
+	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;
+
+    if (stuff->context_len > 0) {
+	if (security_check_context(ctx) < 0)
+	    return BadValue;
+	if (avc_context_to_sid(ctx, pSid) < 0)
+	    return BadValue;
+    }
     return Success;
 }
 
 static int
-ProcSELinuxGetDeviceCreateContext(ClientPtr client)
+ProcSELinuxGetCreateContext(ClientPtr client, unsigned offset)
 {
-    return Success;
+    security_id_t *pSid;
+    char *ptr;
+
+    REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq);
+
+    if (offset == CTX_DEV)
+	ptr = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
+    else
+	ptr = dixLookupPrivate(&client->devPrivates, subjectKey);
+
+    pSid = (security_id_t *)(ptr + offset);
+    return SELinuxSendContextReply(client, *pSid);
 }
 
 static int
 ProcSELinuxSetDeviceContext(ClientPtr client)
 {
-    char *ctx;
+    security_context_t ctx;
     security_id_t sid;
     DeviceIntPtr dev;
     SELinuxSubjectRec *subj;
@@ -1122,15 +1349,16 @@ ProcSELinuxSetDeviceContext(ClientPtr client)
     REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len);
 
     ctx = (char *)(stuff + 1);
-    if (ctx[stuff->context_len - 1])
+    if (stuff->context_len < 1 || ctx[stuff->context_len - 1])
 	return BadLength;
 
     rc = dixLookupDevice(&dev, stuff->id, client, DixManageAccess);
     if (rc != Success)
 	return rc;
 
-    rc = avc_context_to_sid(ctx, &sid);
-    if (rc != Success)
+    if (security_check_context(ctx) < 0)
+	return BadValue;
+    if (avc_context_to_sid(ctx, &sid) < 0)
 	return BadValue;
 
     subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
@@ -1138,7 +1366,7 @@ ProcSELinuxSetDeviceContext(ClientPtr client)
     subj->sid = sid;
     obj = dixLookupPrivate(&dev->devPrivates, objectKey);
     sidput(obj->sid);
-    obj->sid = sid;
+    sidget(obj->sid = sid);
 
     return Success;
 }
@@ -1146,10 +1374,8 @@ ProcSELinuxSetDeviceContext(ClientPtr client)
 static int
 ProcSELinuxGetDeviceContext(ClientPtr client)
 {
-    char *ctx;
     DeviceIntPtr dev;
     SELinuxSubjectRec *subj;
-    SELinuxGetContextReply rep;
     int rc;
 
     REQUEST(SELinuxGetContextReq);
@@ -1160,48 +1386,33 @@ ProcSELinuxGetDeviceContext(ClientPtr client)
 	return rc;
 
     subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
-    rc = avc_sid_to_context(subj->sid, &ctx);
-    if (rc != Success)
-	return BadValue;
-
-    rep.type = X_Reply;
-    rep.length = (strlen(ctx) + 4) >> 2;
-    rep.sequenceNumber = client->sequence;
-    rep.context_len = strlen(ctx) + 1;
-
-    if (client->swapped) {
-	int n;
-	swapl(&rep.length, n);
-	swaps(&rep.sequenceNumber, n);
-	swaps(&rep.context_len, n);
-    }
-
-    WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep);
-    WriteToClient(client, rep.context_len, ctx);
-    free(ctx);
-    return client->noClientException;
+    return SELinuxSendContextReply(client, subj->sid);
 }
 
 static int
-ProcSELinuxSetPropertyCreateContext(ClientPtr client)
+ProcSELinuxGetWindowContext(ClientPtr client)
 {
-    return Success;
-}
+    WindowPtr pWin;
+    SELinuxObjectRec *obj;
+    int rc;
 
-static int
-ProcSELinuxGetPropertyCreateContext(ClientPtr client)
-{
-    return Success;
+    REQUEST(SELinuxGetContextReq);
+    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+
+    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
+    if (rc != Success)
+	return rc;
+
+    obj = dixLookupPrivate(&pWin->devPrivates, objectKey);
+    return SELinuxSendContextReply(client, obj->sid);
 }
 
 static int
-ProcSELinuxGetPropertyContext(ClientPtr client)
+ProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey)
 {
-    char *ctx;
     WindowPtr pWin;
     PropertyPtr pProp;
     SELinuxObjectRec *obj;
-    SELinuxGetContextReply rep;
     int rc;
 
     REQUEST(SELinuxGetPropertyContextReq);
@@ -1216,96 +1427,191 @@ ProcSELinuxGetPropertyContext(ClientPtr client)
     if (rc != Success)
 	return rc;
 
-    obj = dixLookupPrivate(&pProp->devPrivates, objectKey);
-    rc = avc_sid_to_context(obj->sid, &ctx);
-    if (rc != Success)
-	return BadValue;
+    obj = dixLookupPrivate(&pProp->devPrivates, privKey);
+    return SELinuxSendContextReply(client, obj->sid);
+}
 
-    rep.type = X_Reply;
-    rep.length = (strlen(ctx) + 4) >> 2;
-    rep.sequenceNumber = client->sequence;
-    rep.context_len = strlen(ctx) + 1;
+static int
+ProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey)
+{
+    Selection *pSel;
+    SELinuxObjectRec *obj;
+    int rc;
 
-    if (client->swapped) {
-	int n;
-	swapl(&rep.length, n);
-	swaps(&rep.sequenceNumber, n);
-	swaps(&rep.context_len, n);
-    }
+    REQUEST(SELinuxGetContextReq);
+    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
 
-    WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep);
-    WriteToClient(client, rep.context_len, ctx);
-    free(ctx);
-    return client->noClientException;
+    rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess);
+    if (rc != Success)
+	return rc;
+
+    obj = dixLookupPrivate(&pSel->devPrivates, privKey);
+    return SELinuxSendContextReply(client, obj->sid);
 }
 
 static int
-ProcSELinuxSetWindowCreateContext(ClientPtr client)
+SELinuxPopulateItem(SELinuxListItemRec *i, PrivateRec **privPtr, CARD32 id,
+		    int *size)
 {
+    SELinuxObjectRec *obj = dixLookupPrivate(privPtr, objectKey);
+    SELinuxObjectRec *data = dixLookupPrivate(privPtr, dataKey);
+
+    if (avc_sid_to_context(obj->sid, &i->octx) < 0)
+	return BadValue;
+    if (avc_sid_to_context(data->sid, &i->dctx) < 0)
+	return BadValue;
+
+    i->id = id;
+    i->octx_len = (strlen(i->octx) + 4) >> 2;
+    i->dctx_len = (strlen(i->dctx) + 4) >> 2;
+
+    *size += i->octx_len + i->dctx_len + 3;
     return Success;
 }
 
-static int
-ProcSELinuxGetWindowCreateContext(ClientPtr client)
+static void
+SELinuxFreeItems(SELinuxListItemRec *items, int count)
 {
-    return Success;
+    int k;
+    for (k = 0; k < count; k++) {
+	freecon(items[k].octx);
+	freecon(items[k].dctx);
+    }
+    xfree(items);
 }
 
 static int
-ProcSELinuxGetWindowContext(ClientPtr client)
+SELinuxSendItemsToClient(ClientPtr client, SELinuxListItemRec *items,
+			 int size, int count)
 {
-    char *ctx;
-    WindowPtr pWin;
-    SELinuxObjectRec *obj;
-    SELinuxGetContextReply rep;
-    int rc;
-
-    REQUEST(SELinuxGetContextReq);
-    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
-
-    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
-    if (rc != Success)
-	return rc;
+    int rc, k, n, pos = 0;
+    SELinuxListItemsReply rep;
+    CARD32 *buf;
+
+    buf = xcalloc(size, sizeof(CARD32));
+    if (!buf) {
+	rc = BadAlloc;
+	goto out;
+    }
 
-    obj = dixLookupPrivate(&pWin->devPrivates, objectKey);
-    rc = avc_sid_to_context(obj->sid, &ctx);
-    if (rc != Success)
-	return BadValue;
+    /* Fill in the buffer */
+    for (k = 0; k < count; k++) {
+	buf[pos] = items[k].id;
+	if (client->swapped)
+	    swapl(buf + pos, n);
+	pos++;
+
+	buf[pos] = items[k].octx_len * 4;
+	if (client->swapped)
+	    swapl(buf + pos, n);
+	pos++;
+
+	buf[pos] = items[k].dctx_len * 4;
+	if (client->swapped)
+	    swapl(buf + pos, n);
+	pos++;
+
+	memcpy((char *)(buf + pos), items[k].octx, strlen(items[k].octx) + 1);
+	pos += items[k].octx_len;
+	memcpy((char *)(buf + pos), items[k].dctx, strlen(items[k].dctx) + 1);
+	pos += items[k].dctx_len;
+    }
 
+    /* Send reply to client */
     rep.type = X_Reply;
-    rep.length = (strlen(ctx) + 4) >> 2;
+    rep.length = size;
     rep.sequenceNumber = client->sequence;
-    rep.context_len = strlen(ctx) + 1;
+    rep.count = count;
 
     if (client->swapped) {
-	int n;
 	swapl(&rep.length, n);
 	swaps(&rep.sequenceNumber, n);
-	swaps(&rep.context_len, n);
+	swapl(&rep.count, n);
     }
 
-    WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep);
-    WriteToClient(client, rep.context_len, ctx);
-    free(ctx);
-    return client->noClientException;
-}
+    WriteToClient(client, sizeof(SELinuxListItemsReply), (char *)&rep);
+    WriteToClient(client, size * 4, (char *)buf);
 
-static int
-ProcSELinuxSetSelectionCreateContext(ClientPtr client)
-{
-    return Success;
+    /* Free stuff and return */
+    rc = client->noClientException;
+    xfree(buf);
+out:
+    SELinuxFreeItems(items, count);
+    return rc;
 }
 
 static int
-ProcSELinuxGetSelectionCreateContext(ClientPtr client)
+ProcSELinuxListProperties(ClientPtr client)
 {
-    return Success;
+    WindowPtr pWin;
+    PropertyPtr pProp;
+    SELinuxListItemRec *items;
+    int rc, count, size, i;
+    CARD32 id;
+
+    REQUEST(SELinuxGetContextReq);
+    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+
+    rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
+    if (rc != Success)
+	return rc;
+
+    /* Count the number of properties and allocate items */
+    count = 0;
+    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
+	count++;
+    items = xcalloc(count, sizeof(SELinuxListItemRec));
+    if (!items)
+	return BadAlloc;
+
+    /* Fill in the items and calculate size */
+    i = 0;
+    size = 0;
+    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
+	id = pProp->propertyName;
+	rc = SELinuxPopulateItem(items + i, &pProp->devPrivates, id, &size);
+	if (rc != Success) {
+	    SELinuxFreeItems(items, count);
+	    return rc;
+	}
+	i++;
+    }
+
+    return SELinuxSendItemsToClient(client, items, size, count);
 }
 
 static int
-ProcSELinuxGetSelectionContext(ClientPtr client)
+ProcSELinuxListSelections(ClientPtr client)
 {
-    return Success;
+    Selection *pSel;
+    SELinuxListItemRec *items;
+    int rc, count, size, i;
+    CARD32 id;
+
+    REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq);
+
+    /* Count the number of selections and allocate items */
+    count = 0;
+    for (pSel = CurrentSelections; pSel; pSel = pSel->next)
+	count++;
+    items = xcalloc(count, sizeof(SELinuxListItemRec));
+    if (!items)
+	return BadAlloc;
+
+    /* Fill in the items and calculate size */
+    i = 0;
+    size = 0;
+    for (pSel = CurrentSelections; pSel; pSel = pSel->next) {
+	id = pSel->selection;
+	rc = SELinuxPopulateItem(items + i, &pSel->devPrivates, id, &size);
+	if (rc != Success) {
+	    SELinuxFreeItems(items, count);
+	    return rc;
+	}
+	i++;
+    }
+
+    return SELinuxSendItemsToClient(client, items, size, count);
 }
 
 static int
@@ -1315,36 +1621,48 @@ ProcSELinuxDispatch(ClientPtr client)
     switch (stuff->data) {
     case X_SELinuxQueryVersion:
 	return ProcSELinuxQueryVersion(client);
-    case X_SELinuxSetSecurityManager:
-	return ProcSELinuxSetSecurityManager(client);
-    case X_SELinuxGetSecurityManager:
-	return ProcSELinuxGetSecurityManager(client);
     case X_SELinuxSetDeviceCreateContext:
-	return ProcSELinuxSetDeviceCreateContext(client);
+	return ProcSELinuxSetCreateContext(client, CTX_DEV);
     case X_SELinuxGetDeviceCreateContext:
-	return ProcSELinuxGetDeviceCreateContext(client);
+	return ProcSELinuxGetCreateContext(client, CTX_DEV);
     case X_SELinuxSetDeviceContext:
 	return ProcSELinuxSetDeviceContext(client);
     case X_SELinuxGetDeviceContext:
 	return ProcSELinuxGetDeviceContext(client);
-    case X_SELinuxSetPropertyCreateContext:
-	return ProcSELinuxSetPropertyCreateContext(client);
-    case X_SELinuxGetPropertyCreateContext:
-	return ProcSELinuxGetPropertyCreateContext(client);
-    case X_SELinuxGetPropertyContext:
-	return ProcSELinuxGetPropertyContext(client);
     case X_SELinuxSetWindowCreateContext:
-	return ProcSELinuxSetWindowCreateContext(client);
+	return ProcSELinuxSetCreateContext(client, CTX_WIN);
     case X_SELinuxGetWindowCreateContext:
-	return ProcSELinuxGetWindowCreateContext(client);
+	return ProcSELinuxGetCreateContext(client, CTX_WIN);
     case X_SELinuxGetWindowContext:
 	return ProcSELinuxGetWindowContext(client);
+    case X_SELinuxSetPropertyCreateContext:
+	return ProcSELinuxSetCreateContext(client, CTX_PRP);
+    case X_SELinuxGetPropertyCreateContext:
+	return ProcSELinuxGetCreateContext(client, CTX_PRP);
+    case X_SELinuxSetPropertyUseContext:
+	return ProcSELinuxSetCreateContext(client, USE_PRP);
+    case X_SELinuxGetPropertyUseContext:
+	return ProcSELinuxGetCreateContext(client, USE_PRP);
+    case X_SELinuxGetPropertyContext:
+	return ProcSELinuxGetPropertyContext(client, objectKey);
+    case X_SELinuxGetPropertyDataContext:
+	return ProcSELinuxGetPropertyContext(client, dataKey);
+    case X_SELinuxListProperties:
+	return ProcSELinuxListProperties(client);
     case X_SELinuxSetSelectionCreateContext:
-	return ProcSELinuxSetSelectionCreateContext(client);
+	return ProcSELinuxSetCreateContext(client, CTX_SEL);
     case X_SELinuxGetSelectionCreateContext:
-	return ProcSELinuxGetSelectionCreateContext(client);
+	return ProcSELinuxGetCreateContext(client, CTX_SEL);
+    case X_SELinuxSetSelectionUseContext:
+	return ProcSELinuxSetCreateContext(client, USE_SEL);
+    case X_SELinuxGetSelectionUseContext:
+	return ProcSELinuxGetCreateContext(client, USE_SEL);
     case X_SELinuxGetSelectionContext:
-	return ProcSELinuxGetSelectionContext(client);
+	return ProcSELinuxGetSelectionContext(client, objectKey);
+    case X_SELinuxGetSelectionDataContext:
+	return ProcSELinuxGetSelectionContext(client, dataKey);
+    case X_SELinuxListSelections:
+	return ProcSELinuxListSelections(client);
     default:
 	return BadRequest;
     }
@@ -1363,25 +1681,14 @@ SProcSELinuxQueryVersion(ClientPtr client)
 }
 
 static int
-SProcSELinuxSetSecurityManager(ClientPtr client)
-{
-    REQUEST(SELinuxSetSecurityManagerReq);
-    int n;
-
-    REQUEST_SIZE_MATCH(SELinuxSetSecurityManagerReq);
-    swapl(&stuff->window, n);
-    return ProcSELinuxSetSecurityManager(client);
-}
-
-static int
-SProcSELinuxSetDeviceCreateContext(ClientPtr client)
+SProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
 {
     REQUEST(SELinuxSetCreateContextReq);
     int n;
 
     REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq);
-    swaps(&stuff->context_len, n);
-    return ProcSELinuxSetDeviceCreateContext(client);
+    swapl(&stuff->context_len, n);
+    return ProcSELinuxSetCreateContext(client, offset);
 }
 
 static int
@@ -1392,7 +1699,7 @@ SProcSELinuxSetDeviceContext(ClientPtr client)
 
     REQUEST_AT_LEAST_SIZE(SELinuxSetContextReq);
     swapl(&stuff->id, n);
-    swaps(&stuff->context_len, n);
+    swapl(&stuff->context_len, n);
     return ProcSELinuxSetDeviceContext(client);
 }
 
@@ -1408,18 +1715,18 @@ SProcSELinuxGetDeviceContext(ClientPtr client)
 }
 
 static int
-SProcSELinuxSetPropertyCreateContext(ClientPtr client)
+SProcSELinuxGetWindowContext(ClientPtr client)
 {
-    REQUEST(SELinuxSetCreateContextReq);
+    REQUEST(SELinuxGetContextReq);
     int n;
 
-    REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq);
-    swaps(&stuff->context_len, n);
-    return ProcSELinuxSetPropertyCreateContext(client);
+    REQUEST_SIZE_MATCH(SELinuxGetContextReq);
+    swapl(&stuff->id, n);
+    return ProcSELinuxGetWindowContext(client);
 }
 
 static int
-SProcSELinuxGetPropertyContext(ClientPtr client)
+SProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey)
 {
     REQUEST(SELinuxGetPropertyContextReq);
     int n;
@@ -1427,51 +1734,29 @@ SProcSELinuxGetPropertyContext(ClientPtr client)
     REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq);
     swapl(&stuff->window, n);
     swapl(&stuff->property, n);
-    return ProcSELinuxGetPropertyContext(client);
+    return ProcSELinuxGetPropertyContext(client, privKey);
 }
 
 static int
-SProcSELinuxSetWindowCreateContext(ClientPtr client)
-{
-    REQUEST(SELinuxSetCreateContextReq);
-    int n;
-
-    REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq);
-    swaps(&stuff->context_len, n);
-    return ProcSELinuxSetWindowCreateContext(client);
-}
-
-static int
-SProcSELinuxGetWindowContext(ClientPtr client)
+SProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey)
 {
     REQUEST(SELinuxGetContextReq);
     int n;
 
     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
     swapl(&stuff->id, n);
-    return ProcSELinuxGetWindowContext(client);
-}
-
-static int
-SProcSELinuxSetSelectionCreateContext(ClientPtr client)
-{
-    REQUEST(SELinuxSetCreateContextReq);
-    int n;
-
-    REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq);
-    swaps(&stuff->context_len, n);
-    return ProcSELinuxSetSelectionCreateContext(client);
+    return ProcSELinuxGetSelectionContext(client, privKey);
 }
 
 static int
-SProcSELinuxGetSelectionContext(ClientPtr client)
+SProcSELinuxListProperties(ClientPtr client)
 {
     REQUEST(SELinuxGetContextReq);
     int n;
 
     REQUEST_SIZE_MATCH(SELinuxGetContextReq);
     swapl(&stuff->id, n);
-    return ProcSELinuxGetSelectionContext(client);
+    return ProcSELinuxListProperties(client);
 }
 
 static int
@@ -1485,36 +1770,48 @@ SProcSELinuxDispatch(ClientPtr client)
     switch (stuff->data) {
     case X_SELinuxQueryVersion:
 	return SProcSELinuxQueryVersion(client);
-    case X_SELinuxSetSecurityManager:
-	return SProcSELinuxSetSecurityManager(client);
-    case X_SELinuxGetSecurityManager:
-	return ProcSELinuxGetSecurityManager(client);
     case X_SELinuxSetDeviceCreateContext:
-	return SProcSELinuxSetDeviceCreateContext(client);
+	return SProcSELinuxSetCreateContext(client, CTX_DEV);
     case X_SELinuxGetDeviceCreateContext:
-	return ProcSELinuxGetDeviceCreateContext(client);
+	return ProcSELinuxGetCreateContext(client, CTX_DEV);
     case X_SELinuxSetDeviceContext:
 	return SProcSELinuxSetDeviceContext(client);
     case X_SELinuxGetDeviceContext:
 	return SProcSELinuxGetDeviceContext(client);
-    case X_SELinuxSetPropertyCreateContext:
-	return SProcSELinuxSetPropertyCreateContext(client);
-    case X_SELinuxGetPropertyCreateContext:
-	return ProcSELinuxGetPropertyCreateContext(client);
-    case X_SELinuxGetPropertyContext:
-	return SProcSELinuxGetPropertyContext(client);
     case X_SELinuxSetWindowCreateContext:
-	return SProcSELinuxSetWindowCreateContext(client);
+	return SProcSELinuxSetCreateContext(client, CTX_WIN);
     case X_SELinuxGetWindowCreateContext:
-	return ProcSELinuxGetWindowCreateContext(client);
+	return ProcSELinuxGetCreateContext(client, CTX_WIN);
     case X_SELinuxGetWindowContext:
 	return SProcSELinuxGetWindowContext(client);
+    case X_SELinuxSetPropertyCreateContext:
+	return SProcSELinuxSetCreateContext(client, CTX_PRP);
+    case X_SELinuxGetPropertyCreateContext:
+	return ProcSELinuxGetCreateContext(client, CTX_PRP);
+    case X_SELinuxSetPropertyUseContext:
+	return SProcSELinuxSetCreateContext(client, USE_PRP);
+    case X_SELinuxGetPropertyUseContext:
+	return ProcSELinuxGetCreateContext(client, USE_PRP);
+    case X_SELinuxGetPropertyContext:
+	return SProcSELinuxGetPropertyContext(client, objectKey);
+    case X_SELinuxGetPropertyDataContext:
+	return SProcSELinuxGetPropertyContext(client, dataKey);
+    case X_SELinuxListProperties:
+	return SProcSELinuxListProperties(client);
     case X_SELinuxSetSelectionCreateContext:
-	return SProcSELinuxSetSelectionCreateContext(client);
+	return SProcSELinuxSetCreateContext(client, CTX_SEL);
     case X_SELinuxGetSelectionCreateContext:
-	return ProcSELinuxGetSelectionCreateContext(client);
+	return ProcSELinuxGetCreateContext(client, CTX_SEL);
+    case X_SELinuxSetSelectionUseContext:
+	return SProcSELinuxSetCreateContext(client, USE_SEL);
+    case X_SELinuxGetSelectionUseContext:
+	return ProcSELinuxGetCreateContext(client, USE_SEL);
     case X_SELinuxGetSelectionContext:
-	return SProcSELinuxGetSelectionContext(client);
+	return SProcSELinuxGetSelectionContext(client, objectKey);
+    case X_SELinuxGetSelectionDataContext:
+	return SProcSELinuxGetSelectionContext(client, dataKey);
+    case X_SELinuxListSelections:
+	return ProcSELinuxListSelections(client);
     default:
 	return BadRequest;
     }
@@ -1531,7 +1828,6 @@ 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);
@@ -1556,9 +1852,9 @@ SELinuxResetProc(ExtensionEntry *extEntry)
     avc_active = 0;
 
     /* Free local state */
-    xfree(knownSelections);
-    knownSelections = NULL;
-    numKnownSelections = 0;
+    xfree(knownAtoms);
+    knownAtoms = NULL;
+    numKnownAtoms = 0;
 
     xfree(knownEvents);
     knownEvents = NULL;
@@ -1615,7 +1911,8 @@ SELinuxExtensionInit(INITARGS)
 
     /* Allocate private storage */
     if (!dixRequestPrivate(subjectKey, sizeof(SELinuxSubjectRec)) ||
-	!dixRequestPrivate(objectKey, sizeof(SELinuxObjectRec)))
+	!dixRequestPrivate(objectKey, sizeof(SELinuxObjectRec)) ||
+	!dixRequestPrivate(dataKey, sizeof(SELinuxObjectRec)))
 	FatalError("SELinux: Failed to allocate private storage.\n");
 
     /* Create atoms for doing window labeling */
@@ -1631,10 +1928,11 @@ SELinuxExtensionInit(INITARGS)
     ret &= dixRegisterPrivateDeleteFunc(subjectKey, SELinuxSubjectFree, NULL);
     ret &= dixRegisterPrivateInitFunc(objectKey, SELinuxObjectInit, NULL);
     ret &= dixRegisterPrivateDeleteFunc(objectKey, SELinuxObjectFree, NULL);
+    ret &= dixRegisterPrivateInitFunc(dataKey, SELinuxObjectInit, NULL);
+    ret &= dixRegisterPrivateDeleteFunc(dataKey, SELinuxObjectFree, NULL);
 
     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);
diff --git a/Xext/xselinux.h b/Xext/xselinux.h
index 4802761..2d0de32 100644
--- a/Xext/xselinux.h
+++ b/Xext/xselinux.h
@@ -31,21 +31,27 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 /* Extension protocol */
 #define X_SELinuxQueryVersion			0
-#define X_SELinuxSetSecurityManager		1
-#define X_SELinuxGetSecurityManager		2
-#define X_SELinuxSetDeviceCreateContext		3
-#define X_SELinuxGetDeviceCreateContext		4
-#define X_SELinuxSetDeviceContext		5
-#define X_SELinuxGetDeviceContext		6
-#define X_SELinuxSetPropertyCreateContext	7
-#define X_SELinuxGetPropertyCreateContext	8
-#define X_SELinuxGetPropertyContext		9
-#define X_SELinuxSetWindowCreateContext		10
-#define X_SELinuxGetWindowCreateContext		11
-#define X_SELinuxGetWindowContext		12
-#define X_SELinuxSetSelectionCreateContext	13
-#define X_SELinuxGetSelectionCreateContext	14
-#define X_SELinuxGetSelectionContext		15
+#define X_SELinuxSetDeviceCreateContext		1
+#define X_SELinuxGetDeviceCreateContext		2
+#define X_SELinuxSetDeviceContext		3
+#define X_SELinuxGetDeviceContext		4
+#define X_SELinuxSetWindowCreateContext		5
+#define X_SELinuxGetWindowCreateContext		6
+#define X_SELinuxGetWindowContext		7
+#define X_SELinuxSetPropertyCreateContext	8
+#define X_SELinuxGetPropertyCreateContext	9
+#define X_SELinuxSetPropertyUseContext		10
+#define X_SELinuxGetPropertyUseContext		11
+#define X_SELinuxGetPropertyContext		12
+#define X_SELinuxGetPropertyDataContext		13
+#define X_SELinuxListProperties			14
+#define X_SELinuxSetSelectionCreateContext	15
+#define X_SELinuxGetSelectionCreateContext	16
+#define X_SELinuxSetSelectionUseContext		17
+#define X_SELinuxGetSelectionUseContext		18
+#define X_SELinuxGetSelectionContext		19
+#define X_SELinuxGetSelectionDataContext	20
+#define X_SELinuxListSelections			21
 
 typedef struct {
     CARD8   reqType;
@@ -53,7 +59,6 @@ typedef struct {
     CARD16  length;
     CARD8   client_major;
     CARD8   client_minor;
-    CARD16  unused;
 } SELinuxQueryVersionReq;
 
 typedef struct {
@@ -74,35 +79,7 @@ typedef struct {
     CARD8   reqType;
     CARD8   SELinuxReqType;
     CARD16  length;
-    CARD32  window;
-} SELinuxSetSecurityManagerReq;
-
-typedef struct {
-    CARD8   reqType;
-    CARD8   SELinuxReqType;
-    CARD16  length;
-} SELinuxGetSecurityManagerReq;
-
-typedef struct {
-    CARD8   type;
-    CARD8   pad1;
-    CARD16  sequenceNumber;
-    CARD32  length;
-    CARD32  window;
-    CARD32  pad2;
-    CARD32  pad3;
-    CARD32  pad4;
-    CARD32  pad5;
-    CARD32  pad6;
-} SELinuxGetSecurityManagerReply;
-
-typedef struct {
-    CARD8   reqType;
-    CARD8   SELinuxReqType;
-    CARD16  length;
-    CARD8   permanent;
-    CARD8   unused;
-    CARD16  context_len;
+    CARD32  context_len;
 } SELinuxSetCreateContextReq;
 
 typedef struct {
@@ -112,26 +89,11 @@ typedef struct {
 } SELinuxGetCreateContextReq;
 
 typedef struct {
-    CARD8   type;
-    CARD8   permanent;
-    CARD16  sequenceNumber;
-    CARD32  length;
-    CARD16  context_len;
-    CARD16  pad1;
-    CARD32  pad2;
-    CARD32  pad3;
-    CARD32  pad4;
-    CARD32  pad5;
-    CARD32  pad6;
-} SELinuxGetCreateContextReply;
-
-typedef struct {
     CARD8   reqType;
     CARD8   SELinuxReqType;
     CARD16  length;
     CARD32  id;
-    CARD16  unused;
-    CARD16  context_len;
+    CARD32  context_len;
 } SELinuxSetContextReq;
 
 typedef struct {
@@ -154,15 +116,27 @@ typedef struct {
     CARD8   pad1;
     CARD16  sequenceNumber;
     CARD32  length;
-    CARD16  context_len;
-    CARD16  pad2;
+    CARD32  context_len;
+    CARD32  pad2;
     CARD32  pad3;
     CARD32  pad4;
     CARD32  pad5;
     CARD32  pad6;
-    CARD32  pad7;
 } SELinuxGetContextReply;
 
+typedef struct {
+    CARD8   type;
+    CARD8   pad1;
+    CARD16  sequenceNumber;
+    CARD32  length;
+    CARD32  count;
+    CARD32  pad2;
+    CARD32  pad3;
+    CARD32  pad4;
+    CARD32  pad5;
+    CARD32  pad6;
+} SELinuxListItemsReply;
+
 
 /* Private Flask definitions */
 #define SECCLASS_X_DRAWABLE		1


More information about the xorg-commit mailing list