xselinux: Split devPrivate state into subject and object records.
This commit is contained in:
parent
2259b144f0
commit
6dcb7d732b
236
Xext/xselinux.c
236
Xext/xselinux.c
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user