xselinux: add hooks for send and receive access.

This commit is contained in:
Eamon Walsh 2007-10-18 12:33:39 -04:00 committed by Eamon Walsh
parent 06eb830169
commit e974bc1233

View File

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