xselinux: Split devPrivate state into subject and object records.

This commit is contained in:
Eamon Walsh 2008-02-07 16:00:52 -05:00 committed by Eamon Walsh
parent 2259b144f0
commit 6dcb7d732b

View File

@ -61,7 +61,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
/* private state record */ /* private state record */
static DevPrivateKey stateKey = &stateKey; static DevPrivateKey subjectKey = &subjectKey;
static DevPrivateKey objectKey = &objectKey;
/* This is what we store for security state */ /* This is what we store for security state */
typedef struct { typedef struct {
@ -69,7 +70,12 @@ typedef struct {
struct avc_entry_ref aeref; struct avc_entry_ref aeref;
char *command; char *command;
int privileged; int privileged;
} SELinuxStateRec; } SELinuxSubjectRec;
typedef struct {
security_id_t sid;
int poly;
} SELinuxObjectRec;
/* selection manager */ /* selection manager */
typedef struct { typedef struct {
@ -155,7 +161,7 @@ static pointer truep = (pointer)1;
* Looks up the SID corresponding to the given selection atom * Looks up the SID corresponding to the given selection atom
*/ */
static int static int
SELinuxSelectionToSID(Atom selection, SELinuxStateRec *sid_return) SELinuxSelectionToSID(Atom selection, SELinuxObjectRec *sid_return)
{ {
const char *name; const char *name;
unsigned i, size; unsigned i, size;
@ -202,7 +208,7 @@ SELinuxSelectionToSID(Atom selection, SELinuxStateRec *sid_return)
*/ */
static int static int
SELinuxEventToSID(unsigned type, security_id_t sid_of_window, SELinuxEventToSID(unsigned type, security_id_t sid_of_window,
SELinuxStateRec *sid_return) SELinuxObjectRec *sid_return)
{ {
const char *name = LookupEventName(type); const char *name = LookupEventName(type);
security_context_t con; security_context_t con;
@ -293,7 +299,7 @@ SELinuxTypeToClass(RESTYPE type)
* Performs an SELinux permission check. * Performs an SELinux permission check.
*/ */
static int static int
SELinuxDoCheck(SELinuxStateRec *subj, SELinuxStateRec *obj, SELinuxDoCheck(SELinuxSubjectRec *subj, SELinuxObjectRec *obj,
security_class_t class, Mask mode, SELinuxAuditRec *auditdata) security_class_t class, Mask mode, SELinuxAuditRec *auditdata)
{ {
/* serverClient requests OK */ /* serverClient requests OK */
@ -321,11 +327,14 @@ static void
SELinuxLabelClient(ClientPtr client) SELinuxLabelClient(ClientPtr client)
{ {
XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn; XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn;
SELinuxStateRec *state; SELinuxSubjectRec *subj;
SELinuxObjectRec *obj;
security_context_t ctx; security_context_t ctx;
state = dixLookupPrivate(&client->devPrivates, stateKey); subj = dixLookupPrivate(&client->devPrivates, subjectKey);
sidput(state->sid); sidput(subj->sid);
obj = dixLookupPrivate(&client->devPrivates, objectKey);
sidput(obj->sid);
if (_XSERVTransIsLocal(ci)) { if (_XSERVTransIsLocal(ci)) {
int fd = _XSERVTransGetConnectionNumber(ci); int fd = _XSERVTransGetConnectionNumber(ci);
@ -354,12 +363,12 @@ SELinuxLabelClient(ClientPtr client)
if (bytes <= 0) if (bytes <= 0)
goto finish; goto finish;
state->command = xalloc(bytes); subj->command = xalloc(bytes);
if (!state->command) if (!subj->command)
goto finish; goto finish;
memcpy(state->command, path, bytes); memcpy(subj->command, path, bytes);
state->command[bytes - 1] = 0; subj->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)
@ -368,10 +377,12 @@ SELinuxLabelClient(ClientPtr client)
finish: finish:
/* Get a SID from the context */ /* Get a SID from the context */
if (avc_context_to_sid(ctx, &state->sid) < 0) if (avc_context_to_sid(ctx, &subj->sid) < 0)
FatalError("Client %d: context_to_sid(%s) failed\n", FatalError("Client %d: context_to_sid(%s) failed\n",
client->index, ctx); client->index, ctx);
sidget(subj->sid);
obj->sid = subj->sid;
freecon(ctx); freecon(ctx);
} }
@ -383,23 +394,27 @@ SELinuxLabelInitial(void)
{ {
int i; int i;
XaceScreenAccessRec srec; XaceScreenAccessRec srec;
SELinuxStateRec *state; SELinuxSubjectRec *subj;
SELinuxObjectRec *obj;
security_context_t ctx; security_context_t ctx;
pointer unused; pointer unused;
/* Do the serverClient */ /* Do the serverClient */
state = dixLookupPrivate(&serverClient->devPrivates, stateKey); subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
state->privileged = 1; obj = dixLookupPrivate(&serverClient->devPrivates, objectKey);
sidput(state->sid); subj->privileged = 1;
sidput(subj->sid);
/* Use the context of the X server process for the serverClient */ /* Use the context of the X server process for the serverClient */
if (getcon(&ctx) < 0) if (getcon(&ctx) < 0)
FatalError("Couldn't get context of X server process\n"); FatalError("Couldn't get context of X server process\n");
/* Get a SID from the context */ /* Get a SID from the context */
if (avc_context_to_sid(ctx, &state->sid) < 0) if (avc_context_to_sid(ctx, &subj->sid) < 0)
FatalError("serverClient: context_to_sid(%s) failed\n", ctx); FatalError("serverClient: context_to_sid(%s) failed\n", ctx);
sidget(subj->sid);
obj->sid = subj->sid;
freecon(ctx); freecon(ctx);
srec.client = serverClient; srec.client = serverClient;
@ -487,20 +502,27 @@ static void
SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{ {
XaceDeviceAccessRec *rec = calldata; XaceDeviceAccessRec *rec = calldata;
SELinuxStateRec *subj, *obj; SELinuxSubjectRec *subj;
SELinuxObjectRec *obj;
SELinuxAuditRec auditdata = { .client = rec->client }; SELinuxAuditRec auditdata = { .client = rec->client };
int rc; int rc;
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
obj = dixLookupPrivate(&rec->dev->devPrivates, stateKey); obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey);
/* If this is a new object that needs labeling, do it now */ /* If this is a new object that needs labeling, do it now */
if (rec->access_mode & DixCreateAccess) { if (rec->access_mode & DixCreateAccess) {
SELinuxSubjectRec *dsubj;
dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey);
sidput(dsubj->sid);
sidput(obj->sid); sidput(obj->sid);
/* Label the device directly with the process SID */ /* Label the device directly with the process SID */
sidget(subj->sid); sidget(subj->sid);
obj->sid = subj->sid; obj->sid = subj->sid;
sidget(subj->sid);
dsubj->sid = subj->sid;
} }
rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DEVICE, rec->access_mode, rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DEVICE, rec->access_mode,
@ -513,17 +535,18 @@ static void
SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{ {
XaceSendAccessRec *rec = calldata; XaceSendAccessRec *rec = calldata;
SELinuxStateRec *subj, *obj, ev_sid; SELinuxSubjectRec *subj;
SELinuxObjectRec *obj, ev_sid;
SELinuxAuditRec auditdata = { .client = rec->client }; SELinuxAuditRec auditdata = { .client = rec->client };
security_class_t class; security_class_t class;
int rc, i, type; int rc, i, type;
if (rec->dev) if (rec->dev)
subj = dixLookupPrivate(&rec->dev->devPrivates, stateKey); subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey);
else else
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
obj = dixLookupPrivate(&rec->pWin->devPrivates, stateKey); obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey);
/* Check send permission on window */ /* Check send permission on window */
rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess, rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess,
@ -554,13 +577,14 @@ static void
SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{ {
XaceReceiveAccessRec *rec = calldata; XaceReceiveAccessRec *rec = calldata;
SELinuxStateRec *subj, *obj, ev_sid; SELinuxSubjectRec *subj;
SELinuxObjectRec *obj, ev_sid;
SELinuxAuditRec auditdata = { .client = NULL }; SELinuxAuditRec auditdata = { .client = NULL };
security_class_t class; security_class_t class;
int rc, i, type; int rc, i, type;
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
obj = dixLookupPrivate(&rec->pWin->devPrivates, stateKey); obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey);
/* Check receive permission on window */ /* Check receive permission on window */
rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess, rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess,
@ -591,12 +615,13 @@ 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; SELinuxSubjectRec *subj, *serv;
SELinuxObjectRec *obj;
SELinuxAuditRec auditdata = { .client = rec->client }; SELinuxAuditRec auditdata = { .client = rec->client };
int rc; int rc;
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
obj = dixLookupPrivate(&rec->ext->devPrivates, stateKey); obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey);
/* If this is a new object that needs labeling, do it now */ /* If this is a new object that needs labeling, do it now */
/* XXX there should be a separate callback for this */ /* XXX there should be a separate callback for this */
@ -605,9 +630,9 @@ SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata)
security_context_t con; security_context_t con;
security_id_t sid; security_id_t sid;
serv = dixLookupPrivate(&serverClient->devPrivates, stateKey); serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
/* Look in the mappings of property names to contexts */ /* Look in the mappings of extension names to contexts */
if (selabel_lookup(label_hnd, &con, name, SELABEL_X_EXT) < 0) { if (selabel_lookup(label_hnd, &con, name, SELABEL_X_EXT) < 0) {
ErrorF("SELinux: a property label lookup failed!\n"); ErrorF("SELinux: a property label lookup failed!\n");
rec->status = BadValue; rec->status = BadValue;
@ -645,12 +670,13 @@ static void
SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{ {
XacePropertyAccessRec *rec = calldata; XacePropertyAccessRec *rec = calldata;
SELinuxStateRec *subj, *obj; SELinuxSubjectRec *subj;
SELinuxObjectRec *obj;
SELinuxAuditRec auditdata = { .client = rec->client }; SELinuxAuditRec auditdata = { .client = rec->client };
int rc; int rc;
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
obj = dixLookupPrivate(&rec->pProp->devPrivates, stateKey); obj = dixLookupPrivate(&rec->pProp->devPrivates, objectKey);
/* If this is a new object that needs labeling, do it now */ /* If this is a new object that needs labeling, do it now */
if (rec->access_mode & DixCreateAccess) { if (rec->access_mode & DixCreateAccess) {
@ -696,13 +722,15 @@ static void
SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{ {
XaceResourceAccessRec *rec = calldata; XaceResourceAccessRec *rec = calldata;
SELinuxStateRec *subj, *obj, *pobj; SELinuxSubjectRec *subj;
SELinuxObjectRec *obj, *sobj, *pobj;
SELinuxAuditRec auditdata = { .client = rec->client }; SELinuxAuditRec auditdata = { .client = rec->client };
PrivateRec **privatePtr; PrivateRec **privatePtr;
security_class_t class; security_class_t class;
int rc, offset; int rc, offset;
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
sobj = dixLookupPrivate(&rec->client->devPrivates, objectKey);
/* Determine if the resource object has a devPrivates field */ /* Determine if the resource object has a devPrivates field */
offset = dixLookupPrivateOffset(rec->rtype); offset = dixLookupPrivateOffset(rec->rtype);
@ -710,12 +738,12 @@ SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
/* No: use the SID of the owning client */ /* No: use the SID of the owning client */
class = SECCLASS_X_RESOURCE; class = SECCLASS_X_RESOURCE;
privatePtr = &clients[CLIENT_ID(rec->id)]->devPrivates; privatePtr = &clients[CLIENT_ID(rec->id)]->devPrivates;
obj = dixLookupPrivate(privatePtr, stateKey); obj = dixLookupPrivate(privatePtr, objectKey);
} else { } else {
/* Yes: use the SID from the resource object itself */ /* Yes: use the SID from the resource object itself */
class = SELinuxTypeToClass(rec->rtype); class = SELinuxTypeToClass(rec->rtype);
privatePtr = DEVPRIV_AT(rec->res, offset); privatePtr = DEVPRIV_AT(rec->res, offset);
obj = dixLookupPrivate(privatePtr, stateKey); obj = dixLookupPrivate(privatePtr, objectKey);
} }
/* If this is a new object that needs labeling, do it now */ /* If this is a new object that needs labeling, do it now */
@ -724,10 +752,10 @@ SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
offset = dixLookupPrivateOffset(rec->ptype); offset = dixLookupPrivateOffset(rec->ptype);
if (rec->parent && offset >= 0) if (rec->parent && offset >= 0)
/* Use the SID of the parent object in the labeling operation */ /* Use the SID of the parent object in the labeling operation */
pobj = dixLookupPrivate(DEVPRIV_AT(rec->parent, offset), stateKey); pobj = dixLookupPrivate(DEVPRIV_AT(rec->parent, offset), objectKey);
else else
/* Use the SID of the subject */ /* Use the SID of the subject */
pobj = subj; pobj = sobj;
sidput(obj->sid); sidput(obj->sid);
@ -751,13 +779,14 @@ static void
SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata) SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata)
{ {
XaceScreenAccessRec *rec = calldata; XaceScreenAccessRec *rec = calldata;
SELinuxStateRec *subj, *obj; SELinuxSubjectRec *subj;
SELinuxObjectRec *obj;
SELinuxAuditRec auditdata = { .client = rec->client }; SELinuxAuditRec auditdata = { .client = rec->client };
Mask access_mode = rec->access_mode; Mask access_mode = rec->access_mode;
int rc; int rc;
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
obj = dixLookupPrivate(&rec->screen->devPrivates, stateKey); obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey);
/* If this is a new object that needs labeling, do it now */ /* If this is a new object that needs labeling, do it now */
if (access_mode & DixCreateAccess) { if (access_mode & DixCreateAccess) {
@ -784,12 +813,13 @@ static void
SELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{ {
XaceClientAccessRec *rec = calldata; XaceClientAccessRec *rec = calldata;
SELinuxStateRec *subj, *obj; SELinuxSubjectRec *subj;
SELinuxObjectRec *obj;
SELinuxAuditRec auditdata = { .client = rec->client }; SELinuxAuditRec auditdata = { .client = rec->client };
int rc; int rc;
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
obj = dixLookupPrivate(&rec->target->devPrivates, stateKey); obj = dixLookupPrivate(&rec->target->devPrivates, objectKey);
rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode, rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode,
&auditdata); &auditdata);
@ -801,12 +831,13 @@ static void
SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{ {
XaceServerAccessRec *rec = calldata; XaceServerAccessRec *rec = calldata;
SELinuxStateRec *subj, *obj; SELinuxSubjectRec *subj;
SELinuxObjectRec *obj;
SELinuxAuditRec auditdata = { .client = rec->client }; SELinuxAuditRec auditdata = { .client = rec->client };
int rc; int rc;
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
obj = dixLookupPrivate(&serverClient->devPrivates, stateKey); obj = dixLookupPrivate(&serverClient->devPrivates, objectKey);
rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode, rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode,
&auditdata); &auditdata);
@ -818,11 +849,12 @@ static void
SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{ {
XaceSelectionAccessRec *rec = (XaceSelectionAccessRec *)calldata; XaceSelectionAccessRec *rec = (XaceSelectionAccessRec *)calldata;
SELinuxStateRec *subj, sel_sid; SELinuxSubjectRec *subj;
SELinuxObjectRec sel_sid;
SELinuxAuditRec auditdata = { .client = rec->client }; SELinuxAuditRec auditdata = { .client = rec->client };
int rc; int rc;
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
rc = SELinuxSelectionToSID(rec->name, &sel_sid); rc = SELinuxSelectionToSID(rec->name, &sel_sid);
if (rc != Success) { if (rc != Success) {
@ -869,18 +901,19 @@ static void
SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{ {
ResourceStateInfoRec *rec = calldata; ResourceStateInfoRec *rec = calldata;
SELinuxStateRec *state; SELinuxSubjectRec *subj;
SELinuxObjectRec *obj;
WindowPtr pWin; WindowPtr pWin;
if (rec->type != RT_WINDOW) if (rec->type != RT_WINDOW)
return; return;
pWin = (WindowPtr)rec->value; pWin = (WindowPtr)rec->value;
state = dixLookupPrivate(&wClient(pWin)->devPrivates, stateKey); subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey);
if (state->sid) { if (subj->sid) {
security_context_t ctx; security_context_t ctx;
int rc = avc_sid_to_context(state->sid, &ctx); int rc = avc_sid_to_context(subj->sid, &ctx);
if (rc < 0) if (rc < 0)
FatalError("SELinux: Failed to get security context!\n"); FatalError("SELinux: Failed to get security context!\n");
rc = dixChangeWindowProperty(serverClient, rc = dixChangeWindowProperty(serverClient,
@ -892,11 +925,11 @@ SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
} else } else
FatalError("SELinux: Unexpected unlabeled client found\n"); FatalError("SELinux: Unexpected unlabeled client found\n");
state = dixLookupPrivate(&pWin->devPrivates, stateKey); obj = dixLookupPrivate(&pWin->devPrivates, objectKey);
if (state->sid) { if (obj->sid) {
security_context_t ctx; security_context_t ctx;
int rc = avc_sid_to_context(state->sid, &ctx); int rc = avc_sid_to_context(obj->sid, &ctx);
if (rc < 0) if (rc < 0)
FatalError("SELinux: Failed to get security context!\n"); FatalError("SELinux: Failed to get security context!\n");
rc = dixChangeWindowProperty(serverClient, rc = dixChangeWindowProperty(serverClient,
@ -913,7 +946,8 @@ static void
SELinuxSelectionState(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxSelectionState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{ {
SelectionInfoRec *rec = calldata; SelectionInfoRec *rec = calldata;
SELinuxStateRec *subj, *obj; SELinuxSubjectRec *subj;
SELinuxObjectRec *obj;
switch (rec->kind) { switch (rec->kind) {
case SelectionSetOwner: case SelectionSetOwner:
@ -922,8 +956,8 @@ SELinuxSelectionState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
rec->selection->alt_window = rec->selection->window; rec->selection->alt_window = rec->selection->window;
/* figure out the new label for the content */ /* figure out the new label for the content */
subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
obj = dixLookupPrivate(&rec->selection->devPrivates, stateKey); obj = dixLookupPrivate(&rec->selection->devPrivates, objectKey);
sidput(obj->sid); sidput(obj->sid);
if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SELECTION, if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SELECTION,
@ -959,27 +993,47 @@ SELinuxSelectionState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
*/ */
static void static void
SELinuxStateInit(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxSubjectInit(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{ {
PrivateCallbackRec *rec = calldata; PrivateCallbackRec *rec = calldata;
SELinuxStateRec *state = *rec->value; SELinuxSubjectRec *subj = *rec->value;
sidget(unlabeled_sid); sidget(unlabeled_sid);
state->sid = unlabeled_sid; subj->sid = unlabeled_sid;
avc_entry_ref_init(&state->aeref); avc_entry_ref_init(&subj->aeref);
} }
static void static void
SELinuxStateFree(CallbackListPtr *pcbl, pointer unused, pointer calldata) SELinuxSubjectFree(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{ {
PrivateCallbackRec *rec = calldata; PrivateCallbackRec *rec = calldata;
SELinuxStateRec *state = *rec->value; SELinuxSubjectRec *subj = *rec->value;
xfree(state->command); xfree(subj->command);
if (avc_active) if (avc_active)
sidput(state->sid); sidput(subj->sid);
}
static void
SELinuxObjectInit(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
PrivateCallbackRec *rec = calldata;
SELinuxObjectRec *obj = *rec->value;
sidget(unlabeled_sid);
obj->sid = unlabeled_sid;
}
static void
SELinuxObjectFree(CallbackListPtr *pcbl, pointer unused, pointer calldata)
{
PrivateCallbackRec *rec = calldata;
SELinuxObjectRec *obj = *rec->value;
if (avc_active)
sidput(obj->sid);
} }
@ -1070,7 +1124,8 @@ ProcSELinuxSetDeviceContext(ClientPtr client)
char *ctx; char *ctx;
security_id_t sid; security_id_t sid;
DeviceIntPtr dev; DeviceIntPtr dev;
SELinuxStateRec *state; SELinuxSubjectRec *subj;
SELinuxObjectRec *obj;
int rc; int rc;
REQUEST(SELinuxSetContextReq); REQUEST(SELinuxSetContextReq);
@ -1088,9 +1143,13 @@ ProcSELinuxSetDeviceContext(ClientPtr client)
if (rc != Success) if (rc != Success)
return BadValue; return BadValue;
state = dixLookupPrivate(&dev->devPrivates, stateKey); subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
sidput(state->sid); sidput(subj->sid);
state->sid = sid; subj->sid = sid;
obj = dixLookupPrivate(&dev->devPrivates, objectKey);
sidput(obj->sid);
obj->sid = sid;
return Success; return Success;
} }
@ -1099,7 +1158,7 @@ ProcSELinuxGetDeviceContext(ClientPtr client)
{ {
char *ctx; char *ctx;
DeviceIntPtr dev; DeviceIntPtr dev;
SELinuxStateRec *state; SELinuxSubjectRec *subj;
SELinuxGetContextReply rep; SELinuxGetContextReply rep;
int rc; int rc;
@ -1110,8 +1169,8 @@ ProcSELinuxGetDeviceContext(ClientPtr client)
if (rc != Success) if (rc != Success)
return rc; return rc;
state = dixLookupPrivate(&dev->devPrivates, stateKey); subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
rc = avc_sid_to_context(state->sid, &ctx); rc = avc_sid_to_context(subj->sid, &ctx);
if (rc != Success) if (rc != Success)
return BadValue; return BadValue;
@ -1151,7 +1210,7 @@ ProcSELinuxGetPropertyContext(ClientPtr client)
char *ctx; char *ctx;
WindowPtr pWin; WindowPtr pWin;
PropertyPtr pProp; PropertyPtr pProp;
SELinuxStateRec *state; SELinuxObjectRec *obj;
SELinuxGetContextReply rep; SELinuxGetContextReply rep;
int rc; int rc;
@ -1175,8 +1234,8 @@ ProcSELinuxGetPropertyContext(ClientPtr client)
if (rc != Success) if (rc != Success)
return rc; return rc;
state = dixLookupPrivate(&pProp->devPrivates, stateKey); obj = dixLookupPrivate(&pProp->devPrivates, objectKey);
rc = avc_sid_to_context(state->sid, &ctx); rc = avc_sid_to_context(obj->sid, &ctx);
if (rc != Success) if (rc != Success)
return BadValue; return BadValue;
@ -1215,7 +1274,7 @@ ProcSELinuxGetWindowContext(ClientPtr client)
{ {
char *ctx; char *ctx;
WindowPtr pWin; WindowPtr pWin;
SELinuxStateRec *state; SELinuxObjectRec *obj;
SELinuxGetContextReply rep; SELinuxGetContextReply rep;
int rc; int rc;
@ -1226,8 +1285,8 @@ ProcSELinuxGetWindowContext(ClientPtr client)
if (rc != Success) if (rc != Success)
return rc; return rc;
state = dixLookupPrivate(&pWin->devPrivates, stateKey); obj = dixLookupPrivate(&pWin->devPrivates, objectKey);
rc = avc_sid_to_context(state->sid, &ctx); rc = avc_sid_to_context(obj->sid, &ctx);
if (rc != Success) if (rc != Success)
return BadValue; return BadValue;
@ -1521,7 +1580,8 @@ SELinuxExtensionInit(INITARGS)
FatalError("SELinux: Failed to open the system audit log\n"); FatalError("SELinux: Failed to open the system audit log\n");
/* Allocate private storage */ /* Allocate private storage */
if (!dixRequestPrivate(stateKey, sizeof(SELinuxStateRec))) if (!dixRequestPrivate(subjectKey, sizeof(SELinuxSubjectRec)) ||
!dixRequestPrivate(objectKey, sizeof(SELinuxObjectRec)))
FatalError("SELinux: Failed to allocate private storage.\n"); FatalError("SELinux: Failed to allocate private storage.\n");
/* Create atoms for doing window labeling */ /* Create atoms for doing window labeling */
@ -1533,8 +1593,10 @@ SELinuxExtensionInit(INITARGS)
FatalError("SELinux: Failed to create atom\n"); FatalError("SELinux: Failed to create atom\n");
/* Register callbacks */ /* Register callbacks */
ret &= dixRegisterPrivateInitFunc(stateKey, SELinuxStateInit, NULL); ret &= dixRegisterPrivateInitFunc(subjectKey, SELinuxSubjectInit, NULL);
ret &= dixRegisterPrivateDeleteFunc(stateKey, SELinuxStateFree, NULL); ret &= dixRegisterPrivateDeleteFunc(subjectKey, SELinuxSubjectFree, NULL);
ret &= dixRegisterPrivateInitFunc(objectKey, SELinuxObjectInit, NULL);
ret &= dixRegisterPrivateDeleteFunc(objectKey, SELinuxObjectFree, NULL);
ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL); ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL);
ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL); ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL);