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