2006-09-08 21:11:04 +02:00
|
|
|
/************************************************************
|
|
|
|
|
|
|
|
Author: Eamon Walsh <ewalsh@epoch.ncsc.mil>
|
|
|
|
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
|
|
this permission notice appear in supporting documentation. This permission
|
|
|
|
notice shall be included in all copies or substantial portions of the
|
|
|
|
Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
|
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
********************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Portions of this code copyright (c) 2005 by Trusted Computer Solutions, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2008-02-06 03:06:05 +01:00
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
|
|
#include <dix-config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
2006-09-08 21:11:04 +02:00
|
|
|
#include <selinux/selinux.h>
|
2007-06-21 21:37:18 +02:00
|
|
|
#include <selinux/label.h>
|
2006-09-08 21:11:04 +02:00
|
|
|
#include <selinux/avc.h>
|
|
|
|
|
|
|
|
#include <libaudit.h>
|
|
|
|
|
2006-10-04 22:23:35 +02:00
|
|
|
#include <X11/Xatom.h>
|
2007-10-17 19:54:56 +02:00
|
|
|
#include "resource.h"
|
|
|
|
#include "privates.h"
|
|
|
|
#include "registry.h"
|
2006-09-08 21:11:04 +02:00
|
|
|
#include "dixstruct.h"
|
2008-02-06 03:06:05 +01:00
|
|
|
#include "inputstr.h"
|
|
|
|
#include "windowstr.h"
|
|
|
|
#include "propertyst.h"
|
2006-09-08 21:11:04 +02:00
|
|
|
#include "extnsionst.h"
|
2007-10-17 19:54:56 +02:00
|
|
|
#include "scrnintstr.h"
|
2006-09-08 21:11:04 +02:00
|
|
|
#include "selection.h"
|
|
|
|
#include "xacestr.h"
|
|
|
|
#include "xselinux.h"
|
|
|
|
#define XSERV_t
|
|
|
|
#define TRANS_SERVER
|
|
|
|
#include <X11/Xtrans/Xtrans.h>
|
|
|
|
#include "../os/osdep.h"
|
|
|
|
#include "modinit.h"
|
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Globals
|
|
|
|
*/
|
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* private state record */
|
2008-02-07 22:00:52 +01:00
|
|
|
static DevPrivateKey subjectKey = &subjectKey;
|
|
|
|
static DevPrivateKey objectKey = &objectKey;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* This is what we store for security state */
|
|
|
|
typedef struct {
|
|
|
|
security_id_t sid;
|
|
|
|
struct avc_entry_ref aeref;
|
2007-10-18 18:33:39 +02:00
|
|
|
char *command;
|
2008-01-25 00:11:49 +01:00
|
|
|
int privileged;
|
2008-02-07 22:00:52 +01:00
|
|
|
} SELinuxSubjectRec;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
security_id_t sid;
|
|
|
|
int poly;
|
|
|
|
} SELinuxObjectRec;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-24 02:58:48 +02:00
|
|
|
/* selection manager */
|
|
|
|
typedef struct {
|
|
|
|
Atom selection;
|
|
|
|
security_id_t sid;
|
|
|
|
} SELinuxSelectionRec;
|
|
|
|
|
2008-01-25 01:49:13 +01:00
|
|
|
static ClientPtr securityManager;
|
|
|
|
static Window securityWindow;
|
2007-10-24 02:58:48 +02:00
|
|
|
|
2006-09-08 21:11:04 +02:00
|
|
|
/* audit file descriptor */
|
|
|
|
static int audit_fd;
|
|
|
|
|
|
|
|
/* structure passed to auditing callback */
|
|
|
|
typedef struct {
|
|
|
|
ClientPtr client; /* client */
|
2008-02-07 22:32:06 +01:00
|
|
|
DeviceIntPtr dev; /* device */
|
2007-10-18 18:33:39 +02:00
|
|
|
char *command; /* client's executable path */
|
2007-10-17 19:54:56 +02:00
|
|
|
unsigned id; /* resource id, if any */
|
|
|
|
int restype; /* resource type, if any */
|
2007-10-25 00:23:31 +02:00
|
|
|
int event; /* event type, if any */
|
2007-10-17 19:54:56 +02:00
|
|
|
Atom property; /* property name, if any */
|
2007-10-25 00:23:31 +02:00
|
|
|
Atom selection; /* selection name, if any */
|
2006-09-08 21:11:04 +02:00
|
|
|
char *extension; /* extension name, if any */
|
2007-10-17 19:54:56 +02:00
|
|
|
} SELinuxAuditRec;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-06-21 21:37:18 +02:00
|
|
|
/* labeling handle */
|
|
|
|
static struct selabel_handle *label_hnd;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* whether AVC is active */
|
|
|
|
static int avc_active;
|
|
|
|
|
|
|
|
/* atoms for window label properties */
|
|
|
|
static Atom atom_ctx;
|
|
|
|
static Atom atom_client_ctx;
|
2006-10-04 22:23:35 +02:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* The unlabeled SID */
|
|
|
|
static security_id_t unlabeled_sid;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* Array of object classes indexed by resource type */
|
|
|
|
static security_class_t *knownTypes;
|
|
|
|
static unsigned numKnownTypes;
|
|
|
|
|
2007-10-18 20:11:11 +02:00
|
|
|
/* Array of event SIDs indexed by event type */
|
|
|
|
static security_id_t *knownEvents;
|
|
|
|
static unsigned numKnownEvents;
|
|
|
|
|
2007-10-24 02:58:48 +02:00
|
|
|
/* Array of selection SID structures */
|
|
|
|
static SELinuxSelectionRec *knownSelections;
|
|
|
|
static unsigned numKnownSelections;
|
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* dynamically allocated security classes and permissions */
|
2007-06-11 20:19:37 +02:00
|
|
|
static struct security_class_mapping map[] = {
|
2007-10-17 19:54:56 +02:00
|
|
|
{ "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 }},
|
|
|
|
{ "x_screen", { "", "", "", "", "getattr", "setattr", "saver_getattr", "saver_setattr", "", "", "", "", "", "", "hide_cursor", "show_cursor", "saver_hide", "saver_show", NULL }},
|
|
|
|
{ "x_gc", { "", "", "destroy", "create", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "use", NULL }},
|
|
|
|
{ "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 }},
|
2008-02-07 20:35:02 +01:00
|
|
|
{ "x_property", { "read", "write", "destroy", "create", "getattr", "setattr", NULL }},
|
2007-10-17 19:54:56 +02:00
|
|
|
{ "x_selection", { "read", "", "", "", "getattr", "setattr", NULL }},
|
|
|
|
{ "x_cursor", { "read", "write", "destroy", "create", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "use", NULL }},
|
|
|
|
{ "x_client", { "", "", "destroy", "", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "manage", NULL }},
|
2008-02-14 01:46:29 +01:00
|
|
|
{ "x_device", { "read", "write", "", "", "getattr", "setattr", "", "", "", "getfocus", "setfocus", "", "", "", "", "", "", "grab", "freeze", "force_cursor", "", "", "", "", "use", "manage", "", "bell", NULL }},
|
2007-10-17 19:54:56 +02:00
|
|
|
{ "x_server", { "record", "", "", "", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "grab", "", "", "", "", "", "", "", "manage", "debug", NULL }},
|
|
|
|
{ "x_extension", { "", "", "", "", "query", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "use", NULL }},
|
2007-10-18 20:11:11 +02:00
|
|
|
{ "x_event", { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "send", "receive", NULL }},
|
2007-11-09 20:45:27 +01:00
|
|
|
{ "x_synthetic_event", { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "send", "receive", NULL }},
|
2007-10-17 19:54:56 +02:00
|
|
|
{ "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 }},
|
2007-06-11 20:19:37 +02:00
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
/* forward declarations */
|
|
|
|
static void SELinuxScreen(CallbackListPtr *, pointer, pointer);
|
|
|
|
|
2007-10-23 20:08:54 +02:00
|
|
|
/* "true" pointer value for use as callback data */
|
|
|
|
static pointer truep = (pointer)1;
|
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Support Routines
|
|
|
|
*/
|
|
|
|
|
2007-10-24 02:58:48 +02:00
|
|
|
/*
|
|
|
|
* Looks up the SID corresponding to the given selection atom
|
|
|
|
*/
|
|
|
|
static int
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSelectionToSID(Atom selection, SELinuxObjectRec *sid_return)
|
2007-10-24 02:58:48 +02:00
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
unsigned i, size;
|
|
|
|
|
|
|
|
for (i = 0; i < numKnownSelections; i++)
|
|
|
|
if (knownSelections[i].selection == selection) {
|
|
|
|
sid_return->sid = knownSelections[i].sid;
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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 selection names to contexts */
|
|
|
|
name = NameForAtom(selection);
|
|
|
|
if (name) {
|
|
|
|
security_context_t con;
|
|
|
|
security_id_t sid;
|
|
|
|
|
|
|
|
if (selabel_lookup(label_hnd, &con, name, SELABEL_X_SELN) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: a selection label lookup failed!\n");
|
2007-10-24 02:58:48 +02:00
|
|
|
return BadValue;
|
|
|
|
}
|
|
|
|
/* Get a SID for context */
|
|
|
|
if (avc_context_to_sid(con, &sid) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: a context_to_SID call failed!\n");
|
2007-10-24 02:58:48 +02:00
|
|
|
return BadAlloc;
|
|
|
|
}
|
|
|
|
freecon(con);
|
|
|
|
knownSelections[i].sid = sid_return->sid = sid;
|
|
|
|
} else
|
|
|
|
knownSelections[i].sid = sid_return->sid = unlabeled_sid;
|
|
|
|
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
2007-10-18 20:11:11 +02:00
|
|
|
/*
|
|
|
|
* Looks up the SID corresponding to the given event type
|
|
|
|
*/
|
|
|
|
static int
|
2007-10-25 01:59:58 +02:00
|
|
|
SELinuxEventToSID(unsigned type, security_id_t sid_of_window,
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxObjectRec *sid_return)
|
2007-10-18 20:11:11 +02:00
|
|
|
{
|
|
|
|
const char *name = LookupEventName(type);
|
|
|
|
security_context_t con;
|
2007-10-23 20:46:37 +02:00
|
|
|
type &= 127;
|
2007-10-18 20:11:11 +02:00
|
|
|
|
|
|
|
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);
|
2007-10-20 01:40:04 +02:00
|
|
|
numKnownEvents = type + 1;
|
2007-10-18 20:11:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!knownEvents[type]) {
|
2007-10-25 01:59:58 +02:00
|
|
|
/* Look in the mappings of event names to contexts */
|
2007-10-18 20:11:11 +02:00
|
|
|
if (selabel_lookup(label_hnd, &con, name, SELABEL_X_EVENT) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: an event label lookup failed!\n");
|
2007-10-18 20:11:11 +02:00
|
|
|
return BadValue;
|
|
|
|
}
|
|
|
|
/* Get a SID for context */
|
|
|
|
if (avc_context_to_sid(con, knownEvents + type) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: a context_to_SID call failed!\n");
|
2007-10-18 20:11:11 +02:00
|
|
|
return BadAlloc;
|
|
|
|
}
|
|
|
|
freecon(con);
|
|
|
|
}
|
|
|
|
|
2007-10-25 01:59:58 +02:00
|
|
|
/* Perform a transition to obtain the final SID */
|
|
|
|
if (avc_compute_create(sid_of_window, knownEvents[type], SECCLASS_X_EVENT,
|
|
|
|
&sid_return->sid) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: a compute_create call failed!\n");
|
2007-10-25 01:59:58 +02:00
|
|
|
return BadValue;
|
|
|
|
}
|
|
|
|
|
2007-10-18 20:11:11 +02:00
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
2006-12-12 19:35:22 +01:00
|
|
|
/*
|
2007-10-17 19:54:56 +02:00
|
|
|
* Returns the object class corresponding to the given resource type.
|
2006-09-08 21:11:04 +02:00
|
|
|
*/
|
2007-10-17 19:54:56 +02:00
|
|
|
static security_class_t
|
|
|
|
SELinuxTypeToClass(RESTYPE type)
|
2006-09-08 21:11:04 +02:00
|
|
|
{
|
2007-10-17 19:54:56 +02:00
|
|
|
RESTYPE fulltype = type;
|
|
|
|
type &= TypeMask;
|
|
|
|
|
|
|
|
if (type >= numKnownTypes) {
|
|
|
|
/* Need to increase size of classes array */
|
|
|
|
unsigned size = sizeof(security_class_t);
|
|
|
|
knownTypes = xrealloc(knownTypes, (type + 1) * size);
|
|
|
|
if (!knownTypes)
|
|
|
|
return 0;
|
|
|
|
memset(knownTypes + numKnownTypes, 0,
|
|
|
|
(type - numKnownTypes + 1) * size);
|
2007-10-20 01:40:04 +02:00
|
|
|
numKnownTypes = type + 1;
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
2007-10-17 19:54:56 +02:00
|
|
|
|
|
|
|
if (!knownTypes[type]) {
|
|
|
|
const char *str;
|
|
|
|
knownTypes[type] = SECCLASS_X_RESOURCE;
|
|
|
|
|
|
|
|
if (fulltype & RC_DRAWABLE)
|
|
|
|
knownTypes[type] = SECCLASS_X_DRAWABLE;
|
|
|
|
if (fulltype == RT_GC)
|
|
|
|
knownTypes[type] = SECCLASS_X_GC;
|
|
|
|
if (fulltype == RT_FONT)
|
|
|
|
knownTypes[type] = SECCLASS_X_FONT;
|
|
|
|
if (fulltype == RT_CURSOR)
|
|
|
|
knownTypes[type] = SECCLASS_X_CURSOR;
|
|
|
|
if (fulltype == RT_COLORMAP)
|
|
|
|
knownTypes[type] = SECCLASS_X_COLORMAP;
|
2008-01-25 01:02:35 +01:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* Need to do a string lookup */
|
|
|
|
str = LookupResourceName(fulltype);
|
|
|
|
if (!strcmp(str, "PICTURE"))
|
|
|
|
knownTypes[type] = SECCLASS_X_DRAWABLE;
|
|
|
|
if (!strcmp(str, "GLYPHSET"))
|
|
|
|
knownTypes[type] = SECCLASS_X_FONT;
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
return knownTypes[type];
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-10-17 19:54:56 +02:00
|
|
|
* Performs an SELinux permission check.
|
2006-09-08 21:11:04 +02:00
|
|
|
*/
|
|
|
|
static int
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxDoCheck(SELinuxSubjectRec *subj, SELinuxObjectRec *obj,
|
2007-10-18 18:33:39 +02:00
|
|
|
security_class_t class, Mask mode, SELinuxAuditRec *auditdata)
|
2006-09-08 21:11:04 +02:00
|
|
|
{
|
2007-10-17 19:54:56 +02:00
|
|
|
/* serverClient requests OK */
|
2008-01-25 00:11:49 +01:00
|
|
|
if (subj->privileged)
|
2007-04-17 22:01:56 +02:00
|
|
|
return Success;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-18 18:33:39 +02:00
|
|
|
auditdata->command = subj->command;
|
2006-09-08 21:11:04 +02:00
|
|
|
errno = 0;
|
2007-10-17 19:54:56 +02:00
|
|
|
|
2007-10-18 18:33:39 +02:00
|
|
|
if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref,
|
2007-10-17 19:54:56 +02:00
|
|
|
auditdata) < 0) {
|
2007-04-17 22:01:56 +02:00
|
|
|
if (errno == EACCES)
|
|
|
|
return BadAccess;
|
2007-10-17 19:54:56 +02:00
|
|
|
ErrorF("ServerPerm: unexpected error %d\n", errno);
|
2007-04-17 22:01:56 +02:00
|
|
|
return BadValue;
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
|
|
|
|
2007-04-17 22:01:56 +02:00
|
|
|
return Success;
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
|
|
|
|
2007-10-24 02:58:48 +02:00
|
|
|
/*
|
|
|
|
* Labels a newly connected client.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
SELinuxLabelClient(ClientPtr client)
|
|
|
|
{
|
|
|
|
XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec *obj;
|
2007-10-24 02:58:48 +02:00
|
|
|
security_context_t ctx;
|
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&client->devPrivates, subjectKey);
|
|
|
|
sidput(subj->sid);
|
|
|
|
obj = dixLookupPrivate(&client->devPrivates, objectKey);
|
|
|
|
sidput(obj->sid);
|
2007-10-24 02:58:48 +02:00
|
|
|
|
|
|
|
if (_XSERVTransIsLocal(ci)) {
|
|
|
|
int fd = _XSERVTransGetConnectionNumber(ci);
|
|
|
|
struct ucred creds;
|
|
|
|
socklen_t len = sizeof(creds);
|
|
|
|
char path[PATH_MAX + 1];
|
|
|
|
size_t bytes;
|
|
|
|
|
|
|
|
/* For local clients, can get context from the socket */
|
|
|
|
if (getpeercon(fd, &ctx) < 0)
|
|
|
|
FatalError("Client %d: couldn't get context from socket\n",
|
|
|
|
client->index);
|
|
|
|
|
|
|
|
/* Try and determine the client's executable name */
|
|
|
|
memset(&creds, 0, sizeof(creds));
|
|
|
|
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) < 0)
|
|
|
|
goto finish;
|
|
|
|
|
|
|
|
snprintf(path, PATH_MAX + 1, "/proc/%d/cmdline", creds.pid);
|
|
|
|
fd = open(path, O_RDONLY);
|
|
|
|
if (fd < 0)
|
|
|
|
goto finish;
|
|
|
|
|
|
|
|
bytes = read(fd, path, PATH_MAX + 1);
|
|
|
|
close(fd);
|
|
|
|
if (bytes <= 0)
|
|
|
|
goto finish;
|
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
subj->command = xalloc(bytes);
|
|
|
|
if (!subj->command)
|
2007-10-24 02:58:48 +02:00
|
|
|
goto finish;
|
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
memcpy(subj->command, path, bytes);
|
|
|
|
subj->command[bytes - 1] = 0;
|
2007-10-24 02:58:48 +02:00
|
|
|
} else
|
|
|
|
/* For remote clients, need to use a default context */
|
|
|
|
if (selabel_lookup(label_hnd, &ctx, NULL, SELABEL_X_CLIENT) < 0)
|
|
|
|
FatalError("Client %d: couldn't get default remote context\n",
|
|
|
|
client->index);
|
|
|
|
|
|
|
|
finish:
|
|
|
|
/* Get a SID from the context */
|
2008-02-07 22:00:52 +01:00
|
|
|
if (avc_context_to_sid(ctx, &subj->sid) < 0)
|
2007-10-24 02:58:48 +02:00
|
|
|
FatalError("Client %d: context_to_sid(%s) failed\n",
|
|
|
|
client->index, ctx);
|
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
sidget(subj->sid);
|
|
|
|
obj->sid = subj->sid;
|
2007-10-24 02:58:48 +02:00
|
|
|
freecon(ctx);
|
|
|
|
}
|
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
/*
|
|
|
|
* Labels initial server objects.
|
|
|
|
*/
|
|
|
|
static void
|
2007-10-24 02:58:48 +02:00
|
|
|
SELinuxLabelInitial(void)
|
2007-10-18 01:14:15 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
XaceScreenAccessRec srec;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec *obj;
|
2007-10-18 01:14:15 +02:00
|
|
|
security_context_t ctx;
|
|
|
|
pointer unused;
|
|
|
|
|
|
|
|
/* Do the serverClient */
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
|
|
|
|
obj = dixLookupPrivate(&serverClient->devPrivates, objectKey);
|
|
|
|
subj->privileged = 1;
|
|
|
|
sidput(subj->sid);
|
2007-10-18 01:14:15 +02:00
|
|
|
|
|
|
|
/* Use the context of the X server process for the serverClient */
|
|
|
|
if (getcon(&ctx) < 0)
|
|
|
|
FatalError("Couldn't get context of X server process\n");
|
|
|
|
|
|
|
|
/* Get a SID from the context */
|
2008-02-07 22:00:52 +01:00
|
|
|
if (avc_context_to_sid(ctx, &subj->sid) < 0)
|
2007-10-18 01:14:15 +02:00
|
|
|
FatalError("serverClient: context_to_sid(%s) failed\n", ctx);
|
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
sidget(subj->sid);
|
|
|
|
obj->sid = subj->sid;
|
2007-10-18 01:14:15 +02:00
|
|
|
freecon(ctx);
|
|
|
|
|
|
|
|
srec.client = serverClient;
|
|
|
|
srec.access_mode = DixCreateAccess;
|
|
|
|
srec.status = Success;
|
|
|
|
|
|
|
|
for (i = 0; i < screenInfo.numScreens; i++) {
|
|
|
|
/* Do the screen object */
|
|
|
|
srec.screen = screenInfo.screens[i];
|
|
|
|
SELinuxScreen(NULL, NULL, &srec);
|
|
|
|
|
|
|
|
/* Do the default colormap */
|
|
|
|
dixLookupResource(&unused, screenInfo.screens[i]->defColormap,
|
|
|
|
RT_COLORMAP, serverClient, DixCreateAccess);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Libselinux Callbacks
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int
|
|
|
|
SELinuxAudit(void *auditdata,
|
|
|
|
security_class_t class,
|
|
|
|
char *msgbuf,
|
|
|
|
size_t msgbufsize)
|
|
|
|
{
|
|
|
|
SELinuxAuditRec *audit = auditdata;
|
|
|
|
ClientPtr client = audit->client;
|
2007-10-25 00:23:31 +02:00
|
|
|
char idNum[16], *propertyName, *selectionName;
|
2007-10-18 18:33:39 +02:00
|
|
|
int major = -1, minor = -1;
|
2007-10-18 01:14:15 +02:00
|
|
|
|
2007-10-18 18:33:39 +02:00
|
|
|
if (client) {
|
|
|
|
REQUEST(xReq);
|
|
|
|
if (stuff) {
|
|
|
|
major = stuff->reqType;
|
|
|
|
minor = MinorOpcodeOfRequest(client);
|
|
|
|
}
|
|
|
|
}
|
2007-10-18 01:14:15 +02:00
|
|
|
if (audit->id)
|
|
|
|
snprintf(idNum, 16, "%x", audit->id);
|
|
|
|
|
|
|
|
propertyName = audit->property ? NameForAtom(audit->property) : NULL;
|
2007-10-25 00:23:31 +02:00
|
|
|
selectionName = audit->selection ? NameForAtom(audit->selection) : NULL;
|
2007-10-18 01:14:15 +02:00
|
|
|
|
2008-02-07 22:32:06 +01:00
|
|
|
return snprintf(msgbuf, msgbufsize,
|
|
|
|
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
2007-10-18 18:33:39 +02:00
|
|
|
(major >= 0) ? "request=" : "",
|
|
|
|
(major >= 0) ? LookupRequestName(major, minor) : "",
|
|
|
|
audit->command ? " comm=" : "",
|
|
|
|
audit->command ? audit->command : "",
|
2008-02-07 22:32:06 +01:00
|
|
|
audit->dev ? " xdevice=\"" : "",
|
|
|
|
audit->dev ? audit->dev->name : "",
|
|
|
|
audit->dev ? "\"" : "",
|
2007-10-18 01:14:15 +02:00
|
|
|
audit->id ? " resid=" : "",
|
|
|
|
audit->id ? idNum : "",
|
|
|
|
audit->restype ? " restype=" : "",
|
|
|
|
audit->restype ? LookupResourceName(audit->restype) : "",
|
2007-10-25 00:23:31 +02:00
|
|
|
audit->event ? " event=" : "",
|
|
|
|
audit->event ? LookupEventName(audit->event & 127) : "",
|
2007-10-18 01:14:15 +02:00
|
|
|
audit->property ? " property=" : "",
|
|
|
|
audit->property ? propertyName : "",
|
2007-10-25 00:23:31 +02:00
|
|
|
audit->selection ? " selection=" : "",
|
|
|
|
audit->selection ? selectionName : "",
|
2007-10-18 01:14:15 +02:00
|
|
|
audit->extension ? " extension=" : "",
|
|
|
|
audit->extension ? audit->extension : "");
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
SELinuxLog(int type, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
2007-12-20 22:23:35 +01:00
|
|
|
char buf[MAX_AUDIT_MESSAGE_LENGTH];
|
|
|
|
int rc, aut = AUDIT_USER_AVC;
|
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
va_start(ap, fmt);
|
2007-12-20 22:23:35 +01:00
|
|
|
vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap);
|
|
|
|
rc = audit_log_user_avc_message(audit_fd, aut, buf, NULL, NULL, NULL, 0);
|
2007-10-18 01:14:15 +02:00
|
|
|
va_end(ap);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XACE Callbacks
|
|
|
|
*/
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-18 01:27:16 +02:00
|
|
|
static void
|
|
|
|
SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
|
|
|
{
|
|
|
|
XaceDeviceAccessRec *rec = calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec *obj;
|
2008-02-07 22:32:06 +01:00
|
|
|
SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev };
|
2007-10-18 01:27:16 +02:00
|
|
|
int rc;
|
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
|
|
|
|
obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey);
|
2007-10-18 01:27:16 +02:00
|
|
|
|
|
|
|
/* If this is a new object that needs labeling, do it now */
|
|
|
|
if (rec->access_mode & DixCreateAccess) {
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *dsubj;
|
|
|
|
dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey);
|
|
|
|
|
|
|
|
sidput(dsubj->sid);
|
2007-10-18 01:27:16 +02:00
|
|
|
sidput(obj->sid);
|
|
|
|
|
2007-10-25 18:35:01 +02:00
|
|
|
/* Label the device directly with the process SID */
|
|
|
|
sidget(subj->sid);
|
|
|
|
obj->sid = subj->sid;
|
2008-02-07 22:00:52 +01:00
|
|
|
sidget(subj->sid);
|
|
|
|
dsubj->sid = subj->sid;
|
2007-10-18 01:27:16 +02:00
|
|
|
}
|
|
|
|
|
2008-01-25 00:11:49 +01:00
|
|
|
rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DEVICE, rec->access_mode,
|
|
|
|
&auditdata);
|
2007-10-18 01:27:16 +02:00
|
|
|
if (rc != Success)
|
|
|
|
rec->status = rc;
|
|
|
|
}
|
|
|
|
|
2007-10-18 18:33:39 +02:00
|
|
|
static void
|
|
|
|
SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
|
|
|
{
|
|
|
|
XaceSendAccessRec *rec = calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec *obj, ev_sid;
|
2008-02-07 22:32:06 +01:00
|
|
|
SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev };
|
2007-11-09 20:45:27 +01:00
|
|
|
security_class_t class;
|
2008-01-25 00:11:49 +01:00
|
|
|
int rc, i, type;
|
2007-10-18 18:33:39 +02:00
|
|
|
|
2008-01-25 00:11:49 +01:00
|
|
|
if (rec->dev)
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey);
|
2008-01-25 00:11:49 +01:00
|
|
|
else
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
|
2007-10-18 18:33:39 +02:00
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey);
|
2007-10-18 18:33:39 +02:00
|
|
|
|
2007-10-18 20:11:11 +02:00
|
|
|
/* Check send permission on window */
|
2008-01-25 00:11:49 +01:00
|
|
|
rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess,
|
|
|
|
&auditdata);
|
2007-10-18 18:33:39 +02:00
|
|
|
if (rc != Success)
|
2007-10-18 20:11:11 +02:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* Check send permission on specific event types */
|
|
|
|
for (i = 0; i < rec->count; i++) {
|
2007-11-09 20:45:27 +01:00
|
|
|
type = rec->events[i].u.u.type;
|
|
|
|
class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT;
|
2007-10-18 20:11:11 +02:00
|
|
|
|
2007-11-09 20:45:27 +01:00
|
|
|
rc = SELinuxEventToSID(type, obj->sid, &ev_sid);
|
2007-10-18 20:11:11 +02:00
|
|
|
if (rc != Success)
|
|
|
|
goto err;
|
|
|
|
|
2007-11-14 18:23:29 +01:00
|
|
|
auditdata.event = type;
|
2008-01-25 00:11:49 +01:00
|
|
|
rc = SELinuxDoCheck(subj, &ev_sid, class, DixSendAccess, &auditdata);
|
2007-10-18 20:11:11 +02:00
|
|
|
if (rc != Success)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
err:
|
|
|
|
rec->status = rc;
|
2007-10-18 18:33:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
|
|
|
{
|
|
|
|
XaceReceiveAccessRec *rec = calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec *obj, ev_sid;
|
2007-10-26 01:00:50 +02:00
|
|
|
SELinuxAuditRec auditdata = { .client = NULL };
|
2007-11-14 18:23:29 +01:00
|
|
|
security_class_t class;
|
|
|
|
int rc, i, type;
|
2007-10-18 18:33:39 +02:00
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
|
|
|
|
obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey);
|
2007-10-18 18:33:39 +02:00
|
|
|
|
2007-10-18 20:11:11 +02:00
|
|
|
/* Check receive permission on window */
|
2008-01-25 00:11:49 +01:00
|
|
|
rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess,
|
|
|
|
&auditdata);
|
2007-10-18 18:33:39 +02:00
|
|
|
if (rc != Success)
|
2007-10-18 20:11:11 +02:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* Check receive permission on specific event types */
|
|
|
|
for (i = 0; i < rec->count; i++) {
|
2007-11-14 18:23:29 +01:00
|
|
|
type = rec->events[i].u.u.type;
|
|
|
|
class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT;
|
2007-10-18 20:11:11 +02:00
|
|
|
|
2007-11-14 18:23:29 +01:00
|
|
|
rc = SELinuxEventToSID(type, obj->sid, &ev_sid);
|
2007-10-18 20:11:11 +02:00
|
|
|
if (rc != Success)
|
|
|
|
goto err;
|
|
|
|
|
2007-11-14 18:23:29 +01:00
|
|
|
auditdata.event = type;
|
2008-01-25 00:11:49 +01:00
|
|
|
rc = SELinuxDoCheck(subj, &ev_sid, class, DixReceiveAccess, &auditdata);
|
2007-10-18 20:11:11 +02:00
|
|
|
if (rc != Success)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
err:
|
|
|
|
rec->status = rc;
|
2007-10-18 18:33:39 +02:00
|
|
|
}
|
|
|
|
|
2006-12-12 21:59:08 +01:00
|
|
|
static void
|
2007-10-17 19:54:56 +02:00
|
|
|
SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
2006-12-12 21:59:08 +01:00
|
|
|
{
|
2007-10-17 19:54:56 +02:00
|
|
|
XaceExtAccessRec *rec = calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj, *serv;
|
|
|
|
SELinuxObjectRec *obj;
|
2007-10-25 00:23:31 +02:00
|
|
|
SELinuxAuditRec auditdata = { .client = rec->client };
|
2007-10-17 19:54:56 +02:00
|
|
|
int rc;
|
2006-12-12 21:59:08 +01:00
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
|
|
|
|
obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey);
|
2006-12-12 21:59:08 +01:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* If this is a new object that needs labeling, do it now */
|
|
|
|
/* XXX there should be a separate callback for this */
|
|
|
|
if (obj->sid == unlabeled_sid) {
|
|
|
|
const char *name = rec->ext->name;
|
|
|
|
security_context_t con;
|
|
|
|
security_id_t sid;
|
2006-12-12 21:59:08 +01:00
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
|
2006-12-12 21:59:08 +01:00
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
/* Look in the mappings of extension names to contexts */
|
2007-10-17 19:54:56 +02:00
|
|
|
if (selabel_lookup(label_hnd, &con, name, SELABEL_X_EXT) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: a property label lookup failed!\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
rec->status = BadValue;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* Get a SID for context */
|
|
|
|
if (avc_context_to_sid(con, &sid) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: a context_to_SID call failed!\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
rec->status = BadAlloc;
|
|
|
|
return;
|
|
|
|
}
|
2006-12-12 21:59:08 +01:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
sidput(obj->sid);
|
2006-12-12 21:59:08 +01:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* Perform a transition to obtain the final SID */
|
|
|
|
if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION,
|
|
|
|
&obj->sid) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: a SID transition call failed!\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
freecon(con);
|
|
|
|
rec->status = BadValue;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
freecon(con);
|
2006-12-12 21:59:08 +01:00
|
|
|
}
|
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* Perform the security check */
|
|
|
|
auditdata.extension = rec->ext->name;
|
2008-01-25 00:11:49 +01:00
|
|
|
rc = SELinuxDoCheck(subj, obj, SECCLASS_X_EXTENSION, rec->access_mode,
|
|
|
|
&auditdata);
|
2007-10-17 19:54:56 +02:00
|
|
|
if (rc != Success)
|
|
|
|
rec->status = rc;
|
2006-12-12 21:59:08 +01:00
|
|
|
}
|
|
|
|
|
2006-09-08 21:11:04 +02:00
|
|
|
static void
|
2007-10-17 19:54:56 +02:00
|
|
|
SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
2006-09-08 21:11:04 +02:00
|
|
|
{
|
2007-10-17 19:54:56 +02:00
|
|
|
XacePropertyAccessRec *rec = calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec *obj;
|
2007-10-25 00:23:31 +02:00
|
|
|
SELinuxAuditRec auditdata = { .client = rec->client };
|
2007-10-17 19:54:56 +02:00
|
|
|
int rc;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
|
|
|
|
obj = dixLookupPrivate(&rec->pProp->devPrivates, objectKey);
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* If this is a new object that needs labeling, do it now */
|
|
|
|
if (rec->access_mode & DixCreateAccess) {
|
|
|
|
const char *name = NameForAtom(rec->pProp->propertyName);
|
|
|
|
security_context_t con;
|
|
|
|
security_id_t sid;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* Look in the mappings of property names to contexts */
|
|
|
|
if (selabel_lookup(label_hnd, &con, name, SELABEL_X_PROP) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: a property label lookup failed!\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
rec->status = BadValue;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* Get a SID for context */
|
|
|
|
if (avc_context_to_sid(con, &sid) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: a context_to_SID call failed!\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
rec->status = BadAlloc;
|
|
|
|
return;
|
|
|
|
}
|
2006-12-12 21:59:08 +01:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
sidput(obj->sid);
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* Perform a transition to obtain the final SID */
|
|
|
|
if (avc_compute_create(subj->sid, sid, SECCLASS_X_PROPERTY,
|
|
|
|
&obj->sid) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: a SID transition call failed!\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
freecon(con);
|
|
|
|
rec->status = BadValue;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
freecon(con);
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* Perform the security check */
|
|
|
|
auditdata.property = rec->pProp->propertyName;
|
2008-01-25 00:11:49 +01:00
|
|
|
rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode,
|
|
|
|
&auditdata);
|
2007-10-17 19:54:56 +02:00
|
|
|
if (rc != Success)
|
|
|
|
rec->status = rc;
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-10-17 19:54:56 +02:00
|
|
|
SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
2006-09-08 21:11:04 +02:00
|
|
|
{
|
2007-10-17 19:54:56 +02:00
|
|
|
XaceResourceAccessRec *rec = calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec *obj, *sobj, *pobj;
|
2007-10-25 00:23:31 +02:00
|
|
|
SELinuxAuditRec auditdata = { .client = rec->client };
|
2007-10-17 19:54:56 +02:00
|
|
|
PrivateRec **privatePtr;
|
|
|
|
security_class_t class;
|
|
|
|
int rc, offset;
|
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
|
|
|
|
sobj = dixLookupPrivate(&rec->client->devPrivates, objectKey);
|
2007-10-17 19:54:56 +02:00
|
|
|
|
|
|
|
/* Determine if the resource object has a devPrivates field */
|
|
|
|
offset = dixLookupPrivateOffset(rec->rtype);
|
|
|
|
if (offset < 0) {
|
|
|
|
/* No: use the SID of the owning client */
|
|
|
|
class = SECCLASS_X_RESOURCE;
|
|
|
|
privatePtr = &clients[CLIENT_ID(rec->id)]->devPrivates;
|
2008-02-07 22:00:52 +01:00
|
|
|
obj = dixLookupPrivate(privatePtr, objectKey);
|
2007-10-17 19:54:56 +02:00
|
|
|
} else {
|
|
|
|
/* Yes: use the SID from the resource object itself */
|
|
|
|
class = SELinuxTypeToClass(rec->rtype);
|
|
|
|
privatePtr = DEVPRIV_AT(rec->res, offset);
|
2008-02-07 22:00:52 +01:00
|
|
|
obj = dixLookupPrivate(privatePtr, objectKey);
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* 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 */
|
2008-02-07 22:00:52 +01:00
|
|
|
pobj = dixLookupPrivate(DEVPRIV_AT(rec->parent, offset), objectKey);
|
2007-10-17 19:54:56 +02:00
|
|
|
else
|
|
|
|
/* Use the SID of the subject */
|
2008-02-07 22:00:52 +01:00
|
|
|
pobj = sobj;
|
2007-10-17 19:54:56 +02:00
|
|
|
|
|
|
|
sidput(obj->sid);
|
|
|
|
|
|
|
|
/* Perform a transition to obtain the final SID */
|
|
|
|
if (avc_compute_create(subj->sid, pobj->sid, class, &obj->sid) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: a compute_create call failed!\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
rec->status = BadValue;
|
|
|
|
return;
|
|
|
|
}
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
2007-10-17 19:54:56 +02:00
|
|
|
|
|
|
|
/* Perform the security check */
|
|
|
|
auditdata.restype = rec->rtype;
|
|
|
|
auditdata.id = rec->id;
|
2008-01-25 00:11:49 +01:00
|
|
|
rc = SELinuxDoCheck(subj, obj, class, rec->access_mode, &auditdata);
|
2007-10-17 19:54:56 +02:00
|
|
|
if (rc != Success)
|
|
|
|
rec->status = rc;
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
2006-12-12 19:35:22 +01:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
static void
|
|
|
|
SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata)
|
2006-09-08 21:11:04 +02:00
|
|
|
{
|
2007-10-17 19:54:56 +02:00
|
|
|
XaceScreenAccessRec *rec = calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec *obj;
|
2007-10-25 00:23:31 +02:00
|
|
|
SELinuxAuditRec auditdata = { .client = rec->client };
|
2007-10-17 19:54:56 +02:00
|
|
|
Mask access_mode = rec->access_mode;
|
|
|
|
int rc;
|
2006-12-12 19:35:22 +01:00
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
|
|
|
|
obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey);
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* If this is a new object that needs labeling, do it now */
|
|
|
|
if (access_mode & DixCreateAccess) {
|
|
|
|
sidput(obj->sid);
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* Perform a transition to obtain the final SID */
|
|
|
|
if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN,
|
|
|
|
&obj->sid) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: a compute_create call failed!\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
rec->status = BadValue;
|
|
|
|
return;
|
2007-04-17 22:01:56 +02:00
|
|
|
}
|
|
|
|
}
|
2007-10-17 19:54:56 +02:00
|
|
|
|
|
|
|
if (is_saver)
|
|
|
|
access_mode <<= 2;
|
|
|
|
|
2008-01-25 00:11:49 +01:00
|
|
|
rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SCREEN, access_mode, &auditdata);
|
2007-10-17 19:54:56 +02:00
|
|
|
if (rc != Success)
|
|
|
|
rec->status = rc;
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
static void
|
|
|
|
SELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
2006-09-08 21:11:04 +02:00
|
|
|
{
|
2007-10-17 19:54:56 +02:00
|
|
|
XaceClientAccessRec *rec = calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec *obj;
|
2007-10-25 00:23:31 +02:00
|
|
|
SELinuxAuditRec auditdata = { .client = rec->client };
|
2007-10-17 19:54:56 +02:00
|
|
|
int rc;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
|
|
|
|
obj = dixLookupPrivate(&rec->target->devPrivates, objectKey);
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2008-01-25 00:11:49 +01:00
|
|
|
rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode,
|
|
|
|
&auditdata);
|
2007-10-17 19:54:56 +02:00
|
|
|
if (rc != Success)
|
|
|
|
rec->status = rc;
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
2006-12-12 19:35:22 +01:00
|
|
|
|
2007-03-19 21:51:29 +01:00
|
|
|
static void
|
2007-10-17 19:54:56 +02:00
|
|
|
SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
2006-09-08 21:11:04 +02:00
|
|
|
{
|
2007-10-17 19:54:56 +02:00
|
|
|
XaceServerAccessRec *rec = calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec *obj;
|
2007-10-25 00:23:31 +02:00
|
|
|
SELinuxAuditRec auditdata = { .client = rec->client };
|
2007-10-17 19:54:56 +02:00
|
|
|
int rc;
|
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
|
|
|
|
obj = dixLookupPrivate(&serverClient->devPrivates, objectKey);
|
2007-10-17 19:54:56 +02:00
|
|
|
|
2008-01-25 00:11:49 +01:00
|
|
|
rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode,
|
|
|
|
&auditdata);
|
2007-10-17 19:54:56 +02:00
|
|
|
if (rc != Success)
|
|
|
|
rec->status = rc;
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
|
|
|
|
2007-10-24 02:58:48 +02:00
|
|
|
static void
|
|
|
|
SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
|
|
|
{
|
|
|
|
XaceSelectionAccessRec *rec = (XaceSelectionAccessRec *)calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec sel_sid;
|
2007-10-25 00:23:31 +02:00
|
|
|
SELinuxAuditRec auditdata = { .client = rec->client };
|
2007-10-24 02:58:48 +02:00
|
|
|
int rc;
|
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
|
2007-10-24 02:58:48 +02:00
|
|
|
|
|
|
|
rc = SELinuxSelectionToSID(rec->name, &sel_sid);
|
|
|
|
if (rc != Success) {
|
|
|
|
rec->status = rc;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-10-25 00:23:31 +02:00
|
|
|
auditdata.selection = rec->name;
|
2008-01-25 00:11:49 +01:00
|
|
|
rc = SELinuxDoCheck(subj, &sel_sid, SECCLASS_X_SELECTION, rec->access_mode,
|
|
|
|
&auditdata);
|
2007-10-24 02:58:48 +02:00
|
|
|
if (rc != Success)
|
|
|
|
rec->status = rc;
|
|
|
|
}
|
|
|
|
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
/*
|
|
|
|
* DIX Callbacks
|
|
|
|
*/
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-03-19 21:51:29 +01:00
|
|
|
static void
|
2007-10-17 19:54:56 +02:00
|
|
|
SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
2006-09-08 21:11:04 +02:00
|
|
|
{
|
2007-10-17 19:54:56 +02:00
|
|
|
NewClientInfoRec *pci = calldata;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-24 02:58:48 +02:00
|
|
|
switch (pci->client->clientState) {
|
|
|
|
case ClientStateInitial:
|
|
|
|
SELinuxLabelClient(pci->client);
|
|
|
|
break;
|
2007-10-17 19:54:56 +02:00
|
|
|
|
2007-10-24 02:58:48 +02:00
|
|
|
case ClientStateRetained:
|
|
|
|
case ClientStateGone:
|
2008-01-25 01:49:13 +01:00
|
|
|
if (pci->client == securityManager) {
|
|
|
|
securityManager = NULL;
|
|
|
|
securityWindow = 0;
|
2007-10-24 02:58:48 +02:00
|
|
|
}
|
|
|
|
break;
|
2007-10-17 19:54:56 +02:00
|
|
|
|
2007-10-24 02:58:48 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2007-10-17 19:54:56 +02:00
|
|
|
}
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-03-19 21:51:29 +01:00
|
|
|
static void
|
2007-10-17 19:54:56 +02:00
|
|
|
SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
2006-10-04 22:23:35 +02:00
|
|
|
{
|
2007-10-17 19:54:56 +02:00
|
|
|
ResourceStateInfoRec *rec = calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec *obj;
|
2007-03-19 22:04:51 +01:00
|
|
|
WindowPtr pWin;
|
2006-10-04 22:23:35 +02:00
|
|
|
|
2007-03-19 22:04:51 +01:00
|
|
|
if (rec->type != RT_WINDOW)
|
|
|
|
return;
|
|
|
|
|
|
|
|
pWin = (WindowPtr)rec->value;
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey);
|
2007-03-19 22:04:51 +01:00
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
if (subj->sid) {
|
2007-10-17 19:54:56 +02:00
|
|
|
security_context_t ctx;
|
2008-02-07 22:00:52 +01:00
|
|
|
int rc = avc_sid_to_context(subj->sid, &ctx);
|
2006-10-04 22:23:35 +02:00
|
|
|
if (rc < 0)
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Failed to get security context!\n");
|
2007-03-23 15:33:53 +01:00
|
|
|
rc = dixChangeWindowProperty(serverClient,
|
|
|
|
pWin, atom_client_ctx, XA_STRING, 8,
|
|
|
|
PropModeReplace, strlen(ctx), ctx, FALSE);
|
2007-10-17 19:54:56 +02:00
|
|
|
if (rc != Success)
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Failed to set label property on window!\n");
|
2006-10-04 22:23:35 +02:00
|
|
|
freecon(ctx);
|
2008-01-25 01:02:35 +01:00
|
|
|
} else
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Unexpected unlabeled client found\n");
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
obj = dixLookupPrivate(&pWin->devPrivates, objectKey);
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
if (obj->sid) {
|
2007-10-17 19:54:56 +02:00
|
|
|
security_context_t ctx;
|
2008-02-07 22:00:52 +01:00
|
|
|
int rc = avc_sid_to_context(obj->sid, &ctx);
|
2007-10-17 19:54:56 +02:00
|
|
|
if (rc < 0)
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Failed to get security context!\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
rc = dixChangeWindowProperty(serverClient,
|
|
|
|
pWin, atom_ctx, XA_STRING, 8,
|
|
|
|
PropModeReplace, strlen(ctx), ctx, FALSE);
|
|
|
|
if (rc != Success)
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Failed to set label property on window!\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
freecon(ctx);
|
2008-01-25 01:02:35 +01:00
|
|
|
} else
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Unexpected unlabeled window found\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
}
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-24 02:58:48 +02:00
|
|
|
static void
|
|
|
|
SELinuxSelectionState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
|
|
|
{
|
|
|
|
SelectionInfoRec *rec = calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec *obj;
|
2007-10-24 02:58:48 +02:00
|
|
|
|
|
|
|
switch (rec->kind) {
|
|
|
|
case SelectionSetOwner:
|
|
|
|
/* save off the "real" owner of the selection */
|
|
|
|
rec->selection->alt_client = rec->selection->client;
|
|
|
|
rec->selection->alt_window = rec->selection->window;
|
|
|
|
|
|
|
|
/* figure out the new label for the content */
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
|
|
|
|
obj = dixLookupPrivate(&rec->selection->devPrivates, objectKey);
|
2007-10-24 02:58:48 +02:00
|
|
|
sidput(obj->sid);
|
|
|
|
|
|
|
|
if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SELECTION,
|
|
|
|
&obj->sid) < 0) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: a compute_create call failed!\n");
|
2007-10-24 02:58:48 +02:00
|
|
|
obj->sid = unlabeled_sid;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SelectionGetOwner:
|
|
|
|
/* restore the real owner */
|
|
|
|
rec->selection->window = rec->selection->alt_window;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SelectionConvertSelection:
|
|
|
|
/* redirect the convert request if necessary */
|
2008-01-25 01:49:13 +01:00
|
|
|
if (securityManager && securityManager != rec->client) {
|
|
|
|
rec->selection->client = securityManager;
|
|
|
|
rec->selection->window = securityWindow;
|
2007-10-24 02:58:48 +02:00
|
|
|
} else {
|
|
|
|
rec->selection->client = rec->selection->alt_client;
|
|
|
|
rec->selection->window = rec->selection->alt_window;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* DevPrivates Callbacks
|
|
|
|
*/
|
2006-09-08 21:11:04 +02:00
|
|
|
|
|
|
|
static void
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectInit(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
2006-09-08 21:11:04 +02:00
|
|
|
{
|
2007-10-18 01:14:15 +02:00
|
|
|
PrivateCallbackRec *rec = calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj = *rec->value;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
sidget(unlabeled_sid);
|
2008-02-07 22:00:52 +01:00
|
|
|
subj->sid = unlabeled_sid;
|
|
|
|
|
|
|
|
avc_entry_ref_init(&subj->aeref);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
SELinuxSubjectFree(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
|
|
|
{
|
|
|
|
PrivateCallbackRec *rec = calldata;
|
|
|
|
SELinuxSubjectRec *subj = *rec->value;
|
|
|
|
|
|
|
|
xfree(subj->command);
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
if (avc_active)
|
|
|
|
sidput(subj->sid);
|
2007-10-17 19:54:56 +02:00
|
|
|
}
|
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
static void
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxObjectInit(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
2006-09-08 21:11:04 +02:00
|
|
|
{
|
2007-10-18 01:14:15 +02:00
|
|
|
PrivateCallbackRec *rec = calldata;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxObjectRec *obj = *rec->value;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
sidget(unlabeled_sid);
|
|
|
|
obj->sid = unlabeled_sid;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
SELinuxObjectFree(CallbackListPtr *pcbl, pointer unused, pointer calldata)
|
|
|
|
{
|
|
|
|
PrivateCallbackRec *rec = calldata;
|
|
|
|
SELinuxObjectRec *obj = *rec->value;
|
2007-10-17 19:54:56 +02:00
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
if (avc_active)
|
2008-02-07 22:00:52 +01:00
|
|
|
sidput(obj->sid);
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Extension Dispatch
|
|
|
|
*/
|
|
|
|
|
2007-10-24 02:58:48 +02:00
|
|
|
static int
|
|
|
|
ProcSELinuxQueryVersion(ClientPtr client)
|
|
|
|
{
|
|
|
|
SELinuxQueryVersionReply rep;
|
|
|
|
|
|
|
|
rep.type = X_Reply;
|
|
|
|
rep.length = 0;
|
|
|
|
rep.sequenceNumber = client->sequence;
|
2007-12-28 19:26:26 +01:00
|
|
|
rep.server_major = SELINUX_MAJOR_VERSION;
|
|
|
|
rep.server_minor = SELINUX_MINOR_VERSION;
|
2007-10-24 02:58:48 +02:00
|
|
|
if (client->swapped) {
|
|
|
|
int n;
|
|
|
|
swaps(&rep.sequenceNumber, n);
|
|
|
|
swapl(&rep.length, n);
|
|
|
|
swaps(&rep.server_major, n);
|
|
|
|
swaps(&rep.server_minor, n);
|
|
|
|
}
|
|
|
|
WriteToClient(client, sizeof(rep), (char *)&rep);
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2008-01-25 01:49:13 +01:00
|
|
|
ProcSELinuxSetSecurityManager(ClientPtr client)
|
2007-10-24 02:58:48 +02:00
|
|
|
{
|
|
|
|
WindowPtr pWin;
|
|
|
|
int rc;
|
|
|
|
|
2008-01-25 01:49:13 +01:00
|
|
|
REQUEST(SELinuxSetSecurityManagerReq);
|
|
|
|
REQUEST_SIZE_MATCH(SELinuxSetSecurityManagerReq);
|
2007-10-24 02:58:48 +02:00
|
|
|
|
|
|
|
if (stuff->window == None) {
|
2008-01-25 01:49:13 +01:00
|
|
|
securityManager = NULL;
|
|
|
|
securityWindow = None;
|
2007-10-24 02:58:48 +02:00
|
|
|
} else {
|
|
|
|
rc = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW,
|
|
|
|
client, DixGetAttrAccess);
|
|
|
|
if (rc != Success)
|
|
|
|
return rc;
|
|
|
|
|
2008-01-25 01:49:13 +01:00
|
|
|
securityManager = client;
|
|
|
|
securityWindow = stuff->window;
|
2007-10-24 02:58:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
2007-10-27 02:32:10 +02:00
|
|
|
static int
|
2008-01-25 01:49:13 +01:00
|
|
|
ProcSELinuxGetSecurityManager(ClientPtr client)
|
2007-10-27 02:32:10 +02:00
|
|
|
{
|
2008-01-25 01:49:13 +01:00
|
|
|
SELinuxGetSecurityManagerReply rep;
|
2007-10-27 02:32:10 +02:00
|
|
|
|
|
|
|
rep.type = X_Reply;
|
|
|
|
rep.length = 0;
|
|
|
|
rep.sequenceNumber = client->sequence;
|
2008-01-25 01:49:13 +01:00
|
|
|
rep.window = securityWindow;
|
2007-10-27 02:32:10 +02:00
|
|
|
if (client->swapped) {
|
|
|
|
int n;
|
|
|
|
swaps(&rep.sequenceNumber, n);
|
|
|
|
swapl(&rep.length, n);
|
|
|
|
swapl(&rep.window, n);
|
|
|
|
}
|
|
|
|
WriteToClient(client, sizeof(rep), (char *)&rep);
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
|
2007-12-13 02:44:59 +01:00
|
|
|
static int
|
|
|
|
ProcSELinuxSetDeviceCreateContext(ClientPtr client)
|
|
|
|
{
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ProcSELinuxGetDeviceCreateContext(ClientPtr client)
|
|
|
|
{
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
2007-10-27 02:32:10 +02:00
|
|
|
static int
|
|
|
|
ProcSELinuxSetDeviceContext(ClientPtr client)
|
|
|
|
{
|
|
|
|
char *ctx;
|
|
|
|
security_id_t sid;
|
|
|
|
DeviceIntPtr dev;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
|
|
|
SELinuxObjectRec *obj;
|
2007-10-27 02:32:10 +02:00
|
|
|
int rc;
|
|
|
|
|
|
|
|
REQUEST(SELinuxSetContextReq);
|
|
|
|
REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len);
|
|
|
|
|
|
|
|
ctx = (char *)(stuff + 1);
|
|
|
|
if (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)
|
|
|
|
return BadValue;
|
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
|
|
|
|
sidput(subj->sid);
|
|
|
|
subj->sid = sid;
|
|
|
|
obj = dixLookupPrivate(&dev->devPrivates, objectKey);
|
|
|
|
sidput(obj->sid);
|
|
|
|
obj->sid = sid;
|
|
|
|
|
2007-10-27 02:32:10 +02:00
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ProcSELinuxGetDeviceContext(ClientPtr client)
|
|
|
|
{
|
2008-01-25 01:09:58 +01:00
|
|
|
char *ctx;
|
|
|
|
DeviceIntPtr dev;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxSubjectRec *subj;
|
2008-01-25 01:09:58 +01:00
|
|
|
SELinuxGetContextReply rep;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
REQUEST(SELinuxGetContextReq);
|
|
|
|
REQUEST_SIZE_MATCH(SELinuxGetContextReq);
|
|
|
|
|
|
|
|
rc = dixLookupDevice(&dev, stuff->id, client, DixGetAttrAccess);
|
|
|
|
if (rc != Success)
|
|
|
|
return rc;
|
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
subj = dixLookupPrivate(&dev->devPrivates, subjectKey);
|
|
|
|
rc = avc_sid_to_context(subj->sid, &ctx);
|
2008-01-25 01:09:58 +01:00
|
|
|
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;
|
2007-10-27 02:32:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ProcSELinuxSetPropertyCreateContext(ClientPtr client)
|
|
|
|
{
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ProcSELinuxGetPropertyCreateContext(ClientPtr client)
|
|
|
|
{
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ProcSELinuxGetPropertyContext(ClientPtr client)
|
|
|
|
{
|
2008-01-25 01:09:58 +01:00
|
|
|
char *ctx;
|
|
|
|
WindowPtr pWin;
|
|
|
|
PropertyPtr pProp;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxObjectRec *obj;
|
2008-01-25 01:09:58 +01:00
|
|
|
SELinuxGetContextReply rep;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
REQUEST(SELinuxGetPropertyContextReq);
|
|
|
|
REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq);
|
|
|
|
|
|
|
|
rc = dixLookupWindow(&pWin, stuff->window, client, DixGetPropAccess);
|
|
|
|
if (rc != Success)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
pProp = wUserProps(pWin);
|
|
|
|
while (pProp) {
|
|
|
|
if (pProp->propertyName == stuff->property)
|
|
|
|
break;
|
|
|
|
pProp = pProp->next;
|
|
|
|
}
|
|
|
|
if (!pProp)
|
|
|
|
return BadValue;
|
|
|
|
|
2008-02-06 02:07:08 +01:00
|
|
|
rc = XaceHookPropertyAccess(client, pWin, pProp, DixGetAttrAccess);
|
2008-01-25 01:09:58 +01:00
|
|
|
if (rc != Success)
|
|
|
|
return rc;
|
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
obj = dixLookupPrivate(&pProp->devPrivates, objectKey);
|
|
|
|
rc = avc_sid_to_context(obj->sid, &ctx);
|
2008-01-25 01:09:58 +01:00
|
|
|
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;
|
2007-10-27 02:32:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ProcSELinuxSetWindowCreateContext(ClientPtr client)
|
|
|
|
{
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ProcSELinuxGetWindowCreateContext(ClientPtr client)
|
|
|
|
{
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ProcSELinuxGetWindowContext(ClientPtr client)
|
|
|
|
{
|
2008-01-25 01:09:58 +01:00
|
|
|
char *ctx;
|
|
|
|
WindowPtr pWin;
|
2008-02-07 22:00:52 +01:00
|
|
|
SELinuxObjectRec *obj;
|
2008-01-25 01:09:58 +01:00
|
|
|
SELinuxGetContextReply rep;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
REQUEST(SELinuxGetContextReq);
|
|
|
|
REQUEST_SIZE_MATCH(SELinuxGetContextReq);
|
|
|
|
|
|
|
|
rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
|
|
|
|
if (rc != Success)
|
|
|
|
return rc;
|
|
|
|
|
2008-02-07 22:00:52 +01:00
|
|
|
obj = dixLookupPrivate(&pWin->devPrivates, objectKey);
|
|
|
|
rc = avc_sid_to_context(obj->sid, &ctx);
|
2008-01-25 01:09:58 +01:00
|
|
|
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;
|
2007-10-27 02:32:10 +02:00
|
|
|
}
|
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
static int
|
2007-10-18 01:14:15 +02:00
|
|
|
ProcSELinuxDispatch(ClientPtr client)
|
2006-09-08 21:11:04 +02:00
|
|
|
{
|
2007-10-24 02:58:48 +02:00
|
|
|
REQUEST(xReq);
|
|
|
|
switch (stuff->data) {
|
|
|
|
case X_SELinuxQueryVersion:
|
2007-12-28 19:29:45 +01:00
|
|
|
return ProcSELinuxQueryVersion(client);
|
2008-01-25 01:49:13 +01:00
|
|
|
case X_SELinuxSetSecurityManager:
|
|
|
|
return ProcSELinuxSetSecurityManager(client);
|
|
|
|
case X_SELinuxGetSecurityManager:
|
|
|
|
return ProcSELinuxGetSecurityManager(client);
|
2007-12-13 02:44:59 +01:00
|
|
|
case X_SELinuxSetDeviceCreateContext:
|
2007-12-28 19:29:45 +01:00
|
|
|
return ProcSELinuxSetDeviceCreateContext(client);
|
2007-12-13 02:44:59 +01:00
|
|
|
case X_SELinuxGetDeviceCreateContext:
|
2007-12-28 19:29:45 +01:00
|
|
|
return ProcSELinuxGetDeviceCreateContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxSetDeviceContext:
|
2007-12-28 19:29:45 +01:00
|
|
|
return ProcSELinuxSetDeviceContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxGetDeviceContext:
|
2007-12-28 19:29:45 +01:00
|
|
|
return ProcSELinuxGetDeviceContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxSetPropertyCreateContext:
|
2007-12-28 19:29:45 +01:00
|
|
|
return ProcSELinuxSetPropertyCreateContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxGetPropertyCreateContext:
|
2007-12-28 19:29:45 +01:00
|
|
|
return ProcSELinuxGetPropertyCreateContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxGetPropertyContext:
|
2007-12-28 19:29:45 +01:00
|
|
|
return ProcSELinuxGetPropertyContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxSetWindowCreateContext:
|
2007-12-28 19:29:45 +01:00
|
|
|
return ProcSELinuxSetWindowCreateContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxGetWindowCreateContext:
|
2007-12-28 19:29:45 +01:00
|
|
|
return ProcSELinuxGetWindowCreateContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxGetWindowContext:
|
2007-12-28 19:29:45 +01:00
|
|
|
return ProcSELinuxGetWindowContext(client);
|
2007-10-24 02:58:48 +02:00
|
|
|
default:
|
|
|
|
return BadRequest;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
SProcSELinuxQueryVersion(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(SELinuxQueryVersionReq);
|
|
|
|
int n;
|
|
|
|
|
2008-01-25 01:02:35 +01:00
|
|
|
REQUEST_SIZE_MATCH(SELinuxQueryVersionReq);
|
|
|
|
swaps(&stuff->client_major, n);
|
|
|
|
swaps(&stuff->client_minor, n);
|
2007-10-24 02:58:48 +02:00
|
|
|
return ProcSELinuxQueryVersion(client);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2008-01-25 01:49:13 +01:00
|
|
|
SProcSELinuxSetSecurityManager(ClientPtr client)
|
2007-10-24 02:58:48 +02:00
|
|
|
{
|
2008-01-25 01:49:13 +01:00
|
|
|
REQUEST(SELinuxSetSecurityManagerReq);
|
2007-10-24 02:58:48 +02:00
|
|
|
int n;
|
|
|
|
|
2008-01-25 01:49:13 +01:00
|
|
|
REQUEST_SIZE_MATCH(SELinuxSetSecurityManagerReq);
|
2008-01-25 01:02:35 +01:00
|
|
|
swapl(&stuff->window, n);
|
2008-01-25 01:49:13 +01:00
|
|
|
return ProcSELinuxSetSecurityManager(client);
|
2007-10-24 02:58:48 +02:00
|
|
|
}
|
|
|
|
|
2007-12-13 02:44:59 +01:00
|
|
|
static int
|
|
|
|
SProcSELinuxSetDeviceCreateContext(ClientPtr client)
|
|
|
|
{
|
2007-12-21 02:32:07 +01:00
|
|
|
REQUEST(SELinuxSetCreateContextReq);
|
|
|
|
int n;
|
2007-12-13 02:44:59 +01:00
|
|
|
|
2007-12-21 02:32:07 +01:00
|
|
|
REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq);
|
2008-01-25 01:02:35 +01:00
|
|
|
swaps(&stuff->context_len, n);
|
2007-12-21 02:32:07 +01:00
|
|
|
return ProcSELinuxSetDeviceCreateContext(client);
|
2007-12-13 02:44:59 +01:00
|
|
|
}
|
|
|
|
|
2007-10-27 02:32:10 +02:00
|
|
|
static int
|
|
|
|
SProcSELinuxSetDeviceContext(ClientPtr client)
|
|
|
|
{
|
2007-12-21 02:32:07 +01:00
|
|
|
REQUEST(SELinuxSetContextReq);
|
|
|
|
int n;
|
|
|
|
|
|
|
|
REQUEST_AT_LEAST_SIZE(SELinuxSetContextReq);
|
2008-01-25 01:02:35 +01:00
|
|
|
swapl(&stuff->id, n);
|
|
|
|
swaps(&stuff->context_len, n);
|
2007-10-27 02:32:10 +02:00
|
|
|
return ProcSELinuxSetDeviceContext(client);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
SProcSELinuxGetDeviceContext(ClientPtr client)
|
|
|
|
{
|
2007-12-21 02:32:07 +01:00
|
|
|
REQUEST(SELinuxGetContextReq);
|
|
|
|
int n;
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(SELinuxGetContextReq);
|
2008-01-25 01:02:35 +01:00
|
|
|
swapl(&stuff->id, n);
|
2007-10-27 02:32:10 +02:00
|
|
|
return ProcSELinuxGetDeviceContext(client);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
SProcSELinuxSetPropertyCreateContext(ClientPtr client)
|
|
|
|
{
|
2007-12-21 02:32:07 +01:00
|
|
|
REQUEST(SELinuxSetCreateContextReq);
|
|
|
|
int n;
|
2007-10-27 02:32:10 +02:00
|
|
|
|
2007-12-21 02:32:07 +01:00
|
|
|
REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq);
|
2008-01-25 01:02:35 +01:00
|
|
|
swaps(&stuff->context_len, n);
|
2007-12-21 02:32:07 +01:00
|
|
|
return ProcSELinuxSetPropertyCreateContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
SProcSELinuxGetPropertyContext(ClientPtr client)
|
|
|
|
{
|
2007-12-21 02:32:07 +01:00
|
|
|
REQUEST(SELinuxGetPropertyContextReq);
|
|
|
|
int n;
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq);
|
2008-01-25 01:02:35 +01:00
|
|
|
swapl(&stuff->window, n);
|
|
|
|
swapl(&stuff->property, n);
|
2007-10-27 02:32:10 +02:00
|
|
|
return ProcSELinuxGetPropertyContext(client);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
SProcSELinuxSetWindowCreateContext(ClientPtr client)
|
|
|
|
{
|
2007-12-21 02:32:07 +01:00
|
|
|
REQUEST(SELinuxSetCreateContextReq);
|
|
|
|
int n;
|
2007-10-27 02:32:10 +02:00
|
|
|
|
2007-12-21 02:32:07 +01:00
|
|
|
REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq);
|
2008-01-25 01:02:35 +01:00
|
|
|
swaps(&stuff->context_len, n);
|
2007-12-21 02:32:07 +01:00
|
|
|
return ProcSELinuxSetWindowCreateContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
SProcSELinuxGetWindowContext(ClientPtr client)
|
|
|
|
{
|
2007-12-21 02:32:07 +01:00
|
|
|
REQUEST(SELinuxGetContextReq);
|
|
|
|
int n;
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(SELinuxGetContextReq);
|
2008-01-25 01:02:35 +01:00
|
|
|
swapl(&stuff->id, n);
|
2007-10-27 02:32:10 +02:00
|
|
|
return ProcSELinuxGetWindowContext(client);
|
|
|
|
}
|
|
|
|
|
2007-10-24 02:58:48 +02:00
|
|
|
static int
|
|
|
|
SProcSELinuxDispatch(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xReq);
|
|
|
|
int n;
|
|
|
|
|
|
|
|
swaps(&stuff->length, n);
|
|
|
|
|
|
|
|
switch (stuff->data) {
|
|
|
|
case X_SELinuxQueryVersion:
|
2008-01-25 01:02:35 +01:00
|
|
|
return SProcSELinuxQueryVersion(client);
|
2008-01-25 01:49:13 +01:00
|
|
|
case X_SELinuxSetSecurityManager:
|
|
|
|
return SProcSELinuxSetSecurityManager(client);
|
|
|
|
case X_SELinuxGetSecurityManager:
|
|
|
|
return ProcSELinuxGetSecurityManager(client);
|
2007-12-13 02:44:59 +01:00
|
|
|
case X_SELinuxSetDeviceCreateContext:
|
2008-01-25 01:02:35 +01:00
|
|
|
return SProcSELinuxSetDeviceCreateContext(client);
|
2007-12-13 02:44:59 +01:00
|
|
|
case X_SELinuxGetDeviceCreateContext:
|
2008-01-25 01:02:35 +01:00
|
|
|
return ProcSELinuxGetDeviceCreateContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxSetDeviceContext:
|
2008-01-25 01:02:35 +01:00
|
|
|
return SProcSELinuxSetDeviceContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxGetDeviceContext:
|
2008-01-25 01:02:35 +01:00
|
|
|
return SProcSELinuxGetDeviceContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxSetPropertyCreateContext:
|
2008-01-25 01:02:35 +01:00
|
|
|
return SProcSELinuxSetPropertyCreateContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxGetPropertyCreateContext:
|
2008-01-25 01:02:35 +01:00
|
|
|
return ProcSELinuxGetPropertyCreateContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxGetPropertyContext:
|
2008-01-25 01:02:35 +01:00
|
|
|
return SProcSELinuxGetPropertyContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxSetWindowCreateContext:
|
2008-01-25 01:02:35 +01:00
|
|
|
return SProcSELinuxSetWindowCreateContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxGetWindowCreateContext:
|
2008-01-25 01:02:35 +01:00
|
|
|
return ProcSELinuxGetWindowCreateContext(client);
|
2007-10-27 02:32:10 +02:00
|
|
|
case X_SELinuxGetWindowContext:
|
2008-01-25 01:02:35 +01:00
|
|
|
return SProcSELinuxGetWindowContext(client);
|
2007-10-24 02:58:48 +02:00
|
|
|
default:
|
|
|
|
return BadRequest;
|
|
|
|
}
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
/*
|
|
|
|
* Extension Setup / Teardown
|
|
|
|
*/
|
2007-10-17 19:54:56 +02:00
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
static void
|
|
|
|
SELinuxResetProc(ExtensionEntry *extEntry)
|
|
|
|
{
|
2007-10-23 20:08:54 +02:00
|
|
|
/* Unregister callbacks */
|
|
|
|
DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL);
|
|
|
|
DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL);
|
2007-10-24 02:58:48 +02:00
|
|
|
DeleteCallback(&SelectionCallback, SELinuxSelectionState, NULL);
|
2007-10-23 20:08:54 +02:00
|
|
|
|
|
|
|
XaceDeleteCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL);
|
|
|
|
XaceDeleteCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL);
|
|
|
|
XaceDeleteCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL);
|
|
|
|
XaceDeleteCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL);
|
|
|
|
XaceDeleteCallback(XACE_SEND_ACCESS, SELinuxSend, NULL);
|
|
|
|
XaceDeleteCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL);
|
|
|
|
XaceDeleteCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL);
|
|
|
|
XaceDeleteCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL);
|
|
|
|
XaceDeleteCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL);
|
2007-10-24 02:58:48 +02:00
|
|
|
XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
|
2007-10-23 20:08:54 +02:00
|
|
|
XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL);
|
|
|
|
XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep);
|
|
|
|
|
|
|
|
/* Tear down SELinux stuff */
|
2007-10-18 01:14:15 +02:00
|
|
|
selabel_close(label_hnd);
|
|
|
|
label_hnd = NULL;
|
2007-10-17 19:54:56 +02:00
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
audit_close(audit_fd);
|
2007-10-17 19:54:56 +02:00
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
avc_destroy();
|
|
|
|
avc_active = 0;
|
2007-10-17 19:54:56 +02:00
|
|
|
|
2007-10-23 20:08:54 +02:00
|
|
|
/* Free local state */
|
2007-10-24 02:58:48 +02:00
|
|
|
xfree(knownSelections);
|
|
|
|
knownSelections = NULL;
|
|
|
|
numKnownSelections = 0;
|
|
|
|
|
2007-10-18 20:11:11 +02:00
|
|
|
xfree(knownEvents);
|
|
|
|
knownEvents = NULL;
|
|
|
|
numKnownEvents = 0;
|
|
|
|
|
2007-10-18 01:14:15 +02:00
|
|
|
xfree(knownTypes);
|
|
|
|
knownTypes = NULL;
|
|
|
|
numKnownTypes = 0;
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-12-28 19:26:26 +01:00
|
|
|
SELinuxExtensionInit(INITARGS)
|
2006-09-08 21:11:04 +02:00
|
|
|
{
|
2007-10-17 19:54:56 +02:00
|
|
|
ExtensionEntry *extEntry;
|
|
|
|
struct selinux_opt options[] = { { SELABEL_OPT_VALIDATE, (char *)1 } };
|
|
|
|
security_context_t con;
|
|
|
|
int ret = TRUE;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* Setup SELinux stuff */
|
|
|
|
if (!is_selinux_enabled()) {
|
2008-01-25 01:02:35 +01:00
|
|
|
ErrorF("SELinux: SELinux not enabled, disabling SELinux support.\n");
|
|
|
|
return;
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)SELinuxLog);
|
|
|
|
selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)SELinuxAudit);
|
|
|
|
|
2007-12-28 17:56:54 +01:00
|
|
|
if (selinux_set_mapping(map) < 0) {
|
|
|
|
if (errno == EINVAL) {
|
2007-12-28 19:26:26 +01:00
|
|
|
ErrorF("SELinux: Invalid object class mapping, disabling SELinux support.\n");
|
2007-12-28 17:56:54 +01:00
|
|
|
return;
|
|
|
|
}
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Failed to set up security class mapping\n");
|
2007-12-28 17:56:54 +01:00
|
|
|
}
|
2007-06-11 20:19:37 +02:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
if (avc_open(NULL, 0) < 0)
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
avc_active = 1;
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
label_hnd = selabel_open(SELABEL_CTX_X, options, 1);
|
|
|
|
if (!label_hnd)
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Failed to open x_contexts mapping in policy\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
|
|
|
|
if (security_get_initial_context("unlabeled", &con) < 0)
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Failed to look up unlabeled context\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
if (avc_context_to_sid(con, &unlabeled_sid) < 0)
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: a context_to_SID call failed!\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
freecon(con);
|
|
|
|
|
|
|
|
/* Prepare for auditing */
|
|
|
|
audit_fd = audit_open();
|
|
|
|
if (audit_fd < 0)
|
2008-01-25 01:02:35 +01:00
|
|
|
FatalError("SELinux: Failed to open the system audit log\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
|
|
|
|
/* Allocate private storage */
|
2008-02-07 22:00:52 +01:00
|
|
|
if (!dixRequestPrivate(subjectKey, sizeof(SELinuxSubjectRec)) ||
|
|
|
|
!dixRequestPrivate(objectKey, sizeof(SELinuxObjectRec)))
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Failed to allocate private storage.\n");
|
2006-09-08 21:11:04 +02:00
|
|
|
|
2006-10-04 22:23:35 +02:00
|
|
|
/* Create atoms for doing window labeling */
|
2007-10-17 19:54:56 +02:00
|
|
|
atom_ctx = MakeAtom("_SELINUX_CONTEXT", 16, TRUE);
|
2006-10-04 22:23:35 +02:00
|
|
|
if (atom_ctx == BAD_RESOURCE)
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Failed to create atom\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
atom_client_ctx = MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE);
|
2006-10-04 22:23:35 +02:00
|
|
|
if (atom_client_ctx == BAD_RESOURCE)
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Failed to create atom\n");
|
2006-10-04 22:23:35 +02:00
|
|
|
|
2007-10-17 19:54:56 +02:00
|
|
|
/* Register callbacks */
|
2008-02-07 22:00:52 +01:00
|
|
|
ret &= dixRegisterPrivateInitFunc(subjectKey, SELinuxSubjectInit, NULL);
|
|
|
|
ret &= dixRegisterPrivateDeleteFunc(subjectKey, SELinuxSubjectFree, NULL);
|
|
|
|
ret &= dixRegisterPrivateInitFunc(objectKey, SELinuxObjectInit, NULL);
|
|
|
|
ret &= dixRegisterPrivateDeleteFunc(objectKey, SELinuxObjectFree, NULL);
|
2007-10-17 19:54:56 +02:00
|
|
|
|
2007-10-23 20:08:54 +02:00
|
|
|
ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL);
|
|
|
|
ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL);
|
2007-10-24 02:58:48 +02:00
|
|
|
ret &= AddCallback(&SelectionCallback, SELinuxSelectionState, NULL);
|
2007-10-23 20:08:54 +02:00
|
|
|
|
|
|
|
ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL);
|
|
|
|
ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL);
|
|
|
|
ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL);
|
|
|
|
ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL);
|
|
|
|
ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, NULL);
|
|
|
|
ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL);
|
|
|
|
ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL);
|
|
|
|
ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL);
|
|
|
|
ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL);
|
2007-10-24 02:58:48 +02:00
|
|
|
ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
|
2007-10-23 20:08:54 +02:00
|
|
|
ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL);
|
|
|
|
ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep);
|
2007-10-17 19:54:56 +02:00
|
|
|
if (!ret)
|
2007-12-28 19:26:26 +01:00
|
|
|
FatalError("SELinux: Failed to register one or more callbacks\n");
|
2007-10-17 19:54:56 +02:00
|
|
|
|
|
|
|
/* Add extension to server */
|
2007-12-28 19:26:26 +01:00
|
|
|
extEntry = AddExtension(SELINUX_EXTENSION_NAME,
|
|
|
|
SELinuxNumberEvents, SELinuxNumberErrors,
|
2007-10-24 02:58:48 +02:00
|
|
|
ProcSELinuxDispatch, SProcSELinuxDispatch,
|
2007-10-17 19:54:56 +02:00
|
|
|
SELinuxResetProc, StandardMinorOpcode);
|
|
|
|
|
|
|
|
/* Label objects that were created before we could register ourself */
|
2007-10-24 02:58:48 +02:00
|
|
|
SELinuxLabelInitial();
|
2006-09-08 21:11:04 +02:00
|
|
|
}
|