From 1f876171067c04fc21fccd5a3051f982fd85c0f0 Mon Sep 17 00:00:00 2001 From: marha Date: Wed, 21 Oct 2009 19:07:36 +0000 Subject: Updated to xorg-server-1.7.99.1 --- xorg-server/Xext/Makefile.am | 3 +- xorg-server/Xext/Makefile.in | 32 +- xorg-server/Xext/shm.c | 79 +- xorg-server/Xext/xselinux.c | 2070 ------------------------------------- xorg-server/Xext/xselinux.h | 412 -------- xorg-server/Xext/xselinux_ext.c | 729 +++++++++++++ xorg-server/Xext/xselinux_hooks.c | 1030 ++++++++++++++++++ xorg-server/Xext/xselinux_label.c | 381 +++++++ xorg-server/Xext/xselinuxint.h | 556 ++++++++++ xorg-server/Xext/xtest.c | 6 +- xorg-server/Xext/xvdisp.c | 2 +- 11 files changed, 2778 insertions(+), 2522 deletions(-) delete mode 100644 xorg-server/Xext/xselinux.c create mode 100644 xorg-server/Xext/xselinux_ext.c create mode 100644 xorg-server/Xext/xselinux_hooks.c create mode 100644 xorg-server/Xext/xselinux_label.c create mode 100644 xorg-server/Xext/xselinuxint.h (limited to 'xorg-server/Xext') diff --git a/xorg-server/Xext/Makefile.am b/xorg-server/Xext/Makefile.am index ac45f955a..7287c4a62 100644 --- a/xorg-server/Xext/Makefile.am +++ b/xorg-server/Xext/Makefile.am @@ -80,7 +80,7 @@ endif # SELinux extension: provides SELinux policy support for X objects # requires X-ACE extension -XSELINUX_SRCS = xselinux.c xselinux.h +XSELINUX_SRCS = xselinux_ext.c xselinux_hooks.c xselinux_label.c xselinux.h xselinuxint.h if XSELINUX MODULE_SRCS += $(XSELINUX_SRCS) endif @@ -133,6 +133,7 @@ EXTRA_DIST = \ $(SCREENSAVER_SRCS) \ $(XACE_SRCS) \ $(XCSECURITY_SRCS) \ + $(XSELINUX_SRCS) \ $(XCALIBRATE_SRCS) \ $(XINERAMA_SRCS) \ $(MULTIBUFFER_SRCS) \ diff --git a/xorg-server/Xext/Makefile.in b/xorg-server/Xext/Makefile.in index e3909ff88..2fb733684 100644 --- a/xorg-server/Xext/Makefile.in +++ b/xorg-server/Xext/Makefile.in @@ -57,7 +57,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_define_dir.m4 \ $(top_srcdir)/m4/dolt.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/m4/shave.m4 $(top_srcdir)/configure.ac + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -79,7 +79,8 @@ am__libXext_la_SOURCES_DIST = bigreq.c geext.c shape.c sleepuntil.c \ panoramiXprocs.c panoramiXSwap.c xace.c xace.h xacestr.h \ security.c securitysrv.h xcalibrate.c xf86bigfont.c xvmain.c \ xvdisp.c xvmc.c xvdix.h xvmcext.h xvdisp.h xres.c saver.c \ - xselinux.c xselinux.h mbuf.c dpms.c dpmsproc.h + xselinux_ext.c xselinux_hooks.c xselinux_label.c xselinux.h \ + xselinuxint.h mbuf.c dpms.c dpmsproc.h am__objects_1 = shm.lo @MITSHM_TRUE@am__objects_2 = $(am__objects_1) am__objects_3 = panoramiX.lo panoramiXprocs.lo panoramiXSwap.lo @@ -102,7 +103,7 @@ am__objects_16 = xres.lo @RES_TRUE@am__objects_17 = $(am__objects_16) am__objects_18 = saver.lo @SCREENSAVER_TRUE@am__objects_19 = $(am__objects_18) -am__objects_20 = xselinux.lo +am__objects_20 = xselinux_ext.lo xselinux_hooks.lo xselinux_label.lo @XSELINUX_TRUE@am__objects_21 = $(am__objects_20) am__objects_22 = mbuf.lo @MULTIBUFFER_TRUE@am__objects_23 = $(am__objects_22) @@ -128,8 +129,9 @@ libXextbuiltin_la_OBJECTS = $(am_libXextbuiltin_la_OBJECTS) @XORG_TRUE@am_libXextbuiltin_la_rpath = libXextmodule_la_LIBADD = am__libXextmodule_la_SOURCES_DIST = xvmain.c xvdisp.c xvmc.c xvdix.h \ - xvmcext.h xvdisp.h xres.c saver.c xselinux.c xselinux.h mbuf.c \ - dpms.c dpmsproc.h + xvmcext.h xvdisp.h xres.c saver.c xselinux_ext.c \ + xselinux_hooks.c xselinux_label.c xselinux.h xselinuxint.h \ + mbuf.c dpms.c dpmsproc.h @XORG_TRUE@am_libXextmodule_la_OBJECTS = $(am__objects_26) libXextmodule_la_OBJECTS = $(am_libXextmodule_la_OBJECTS) @XORG_TRUE@am_libXextmodule_la_rpath = @@ -194,7 +196,6 @@ ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AM_MAKEFLAGS = @AM_MAKEFLAGS@ APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@ APPLE_APPLICATION_NAME = @APPLE_APPLICATION_NAME@ APP_MAN_DIR = @APP_MAN_DIR@ @@ -219,7 +220,6 @@ COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CWARNFLAGS = @CWARNFLAGS@ -CXX = @CXX@ CYGPATH_W = @CYGPATH_W@ DARWIN_LIBS = @DARWIN_LIBS@ DBUS_CFLAGS = @DBUS_CFLAGS@ @@ -243,6 +243,7 @@ DMXXIEXAMPLES_DEP_LIBS = @DMXXIEXAMPLES_DEP_LIBS@ DMXXMUEXAMPLES_DEP_CFLAGS = @DMXXMUEXAMPLES_DEP_CFLAGS@ DMXXMUEXAMPLES_DEP_LIBS = @DMXXMUEXAMPLES_DEP_LIBS@ DOLT_BASH = @DOLT_BASH@ +DOXYGEN = @DOXYGEN@ DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ DRI2PROTO_LIBS = @DRI2PROTO_LIBS@ DRIPROTO_CFLAGS = @DRIPROTO_CFLAGS@ @@ -260,8 +261,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -F77 = @F77@ -FC = @FC@ FGREP = @FGREP@ FILE_MAN_DIR = @FILE_MAN_DIR@ FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ @@ -307,7 +306,6 @@ LTCXXCOMPILE = @LTCXXCOMPILE@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAIN_LIB = @MAIN_LIB@ -MAKEFLAGS = @MAKEFLAGS@ MAKEINFO = @MAKEINFO@ MAKE_HTML = @MAKE_HTML@ MAKE_PDF = @MAKE_PDF@ @@ -333,6 +331,7 @@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@ @@ -342,7 +341,6 @@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PROJECTROOT = @PROJECTROOT@ PS2PDF = @PS2PDF@ -Q = @Q@ RANLIB = @RANLIB@ RAWCPP = @RAWCPP@ RAWCPPFLAGS = @RAWCPPFLAGS@ @@ -356,7 +354,6 @@ STRIP = @STRIP@ TSLIB_CFLAGS = @TSLIB_CFLAGS@ TSLIB_LIBS = @TSLIB_LIBS@ UTILS_SYS_LIBS = @UTILS_SYS_LIBS@ -V = @V@ VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@ VERSION = @VERSION@ WINDRES = @WINDRES@ @@ -398,8 +395,6 @@ XPBPROXY_LIBS = @XPBPROXY_LIBS@ XQUARTZ_SPARKLE = @XQUARTZ_SPARKLE@ XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@ XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@ -XSDL_INCS = @XSDL_INCS@ -XSDL_LIBS = @XSDL_LIBS@ XSERVERCFLAGS_CFLAGS = @XSERVERCFLAGS_CFLAGS@ XSERVERCFLAGS_LIBS = @XSERVERCFLAGS_LIBS@ XSERVERLIBS_CFLAGS = @XSERVERLIBS_CFLAGS@ @@ -442,6 +437,7 @@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ +distcleancheck_listfiles = @distcleancheck_listfiles@ docdir = @docdir@ driverdir = @driverdir@ dvidir = @dvidir@ @@ -473,7 +469,6 @@ psdir = @psdir@ sbindir = @sbindir@ sdkdir = @sdkdir@ sharedstatedir = @sharedstatedir@ -shavedir = @shavedir@ srcdir = @srcdir@ symbol_visibility = @symbol_visibility@ sysconfdir = @sysconfdir@ @@ -528,7 +523,7 @@ XACE_SRCS = xace.c xace.h xacestr.h # SELinux extension: provides SELinux policy support for X objects # requires X-ACE extension -XSELINUX_SRCS = xselinux.c xselinux.h +XSELINUX_SRCS = xselinux_ext.c xselinux_hooks.c xselinux_label.c xselinux.h xselinuxint.h # Security extension: multi-level security to protect clients from each other XCSECURITY_SRCS = security.c securitysrv.h @@ -556,6 +551,7 @@ EXTRA_DIST = \ $(SCREENSAVER_SRCS) \ $(XACE_SRCS) \ $(XCSECURITY_SRCS) \ + $(XSELINUX_SRCS) \ $(XCALIBRATE_SRCS) \ $(XINERAMA_SRCS) \ $(MULTIBUFFER_SRCS) \ @@ -639,7 +635,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xcmisc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xf86bigfont.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xres.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xselinux.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xselinux_ext.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xselinux_hooks.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xselinux_label.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xtest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xvdisp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xvmain.Plo@am__quote@ diff --git a/xorg-server/Xext/shm.c b/xorg-server/Xext/shm.c index a6f804cd5..8106c40b6 100644 --- a/xorg-server/Xext/shm.c +++ b/xorg-server/Xext/shm.c @@ -99,6 +99,12 @@ typedef struct _ShmDesc { unsigned long size; } ShmDescRec, *ShmDescPtr; +typedef struct _ShmScrPrivateRec { + CloseScreenProcPtr CloseScreen; + ShmFuncsPtr shmFuncs; + DestroyPixmapProcPtr destroyPixmap; +} ShmScrPrivateRec; + static PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); static int ShmDetachSegment( pointer /* value */, @@ -135,13 +141,16 @@ int BadShmSegCode; RESTYPE ShmSegType; static ShmDescPtr Shmsegs; static Bool sharedPixmaps; -static ShmFuncsPtr shmFuncs[MAXSCREENS]; -static DestroyPixmapProcPtr destroyPixmap[MAXSCREENS]; +static DrawablePtr *drawables; +static int shmScrPrivateKeyIndex; +static DevPrivateKey shmScrPrivateKey = &shmScrPrivateKeyIndex; static int shmPixmapPrivateIndex; static DevPrivateKey shmPixmapPrivate = &shmPixmapPrivateIndex; static ShmFuncs miFuncs = {NULL, NULL}; static ShmFuncs fbFuncs = {fbShmCreatePixmap, NULL}; +#define ShmGetScreenPriv(s) ((ShmScrPrivateRec *)dixLookupPrivate(&(s)->devPrivates, shmScrPrivateKey)) + #define VERIFY_SHMSEG(shmseg,shmdesc,client) \ { \ int rc; \ @@ -212,6 +221,30 @@ static Bool CheckForShmSyscall(void) #endif +static Bool +ShmCloseScreen(int i, ScreenPtr pScreen) +{ + ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); + pScreen->CloseScreen = screen_priv->CloseScreen; + dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, NULL); + xfree (screen_priv); + return (*pScreen->CloseScreen) (i, pScreen); +} + +static ShmScrPrivateRec * +ShmInitScreenPriv(ScreenPtr pScreen) +{ + ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); + if (!screen_priv) + { + screen_priv = xcalloc (1, sizeof (ShmScrPrivateRec)); + screen_priv->CloseScreen = pScreen->CloseScreen; + dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, screen_priv); + pScreen->CloseScreen = ShmCloseScreen; + } + return screen_priv; +} + void ShmExtensionInit(INITARGS) { @@ -226,20 +259,29 @@ ShmExtensionInit(INITARGS) } #endif + drawables = xcalloc(screenInfo.numScreens, sizeof(DrawablePtr)); + if (!drawables) + { + ErrorF("MIT-SHM extension disabled: no memory for per-screen drawables\n"); + return; + } + sharedPixmaps = xFalse; { sharedPixmaps = xTrue; for (i = 0; i < screenInfo.numScreens; i++) { - if (!shmFuncs[i]) - shmFuncs[i] = &miFuncs; - if (!shmFuncs[i]->CreatePixmap) + ShmScrPrivateRec *screen_priv = ShmInitScreenPriv(screenInfo.screens[i]); + if (!screen_priv->shmFuncs) + screen_priv->shmFuncs = &miFuncs; + if (!screen_priv->shmFuncs->CreatePixmap) sharedPixmaps = xFalse; } if (sharedPixmaps) for (i = 0; i < screenInfo.numScreens; i++) { - destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap; + ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(screenInfo.screens[i]); + screen_priv->destroyPixmap = screenInfo.screens[i]->DestroyPixmap; screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; } } @@ -261,23 +303,21 @@ static void ShmResetProc(ExtensionEntry *extEntry) { int i; - - for (i = 0; i < MAXSCREENS; i++) - { - shmFuncs[i] = NULL; - } + for (i = 0; i < screenInfo.numScreens; i++) + ShmRegisterFuncs(screenInfo.screens[i], NULL); } void ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs) { - shmFuncs[pScreen->myNum] = funcs; + ShmInitScreenPriv(pScreen)->shmFuncs = funcs; } static Bool ShmDestroyPixmap (PixmapPtr pPixmap) { ScreenPtr pScreen = pPixmap->drawable.pScreen; + ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); Bool ret; if (pPixmap->refcnt == 1) { @@ -288,9 +328,9 @@ ShmDestroyPixmap (PixmapPtr pPixmap) ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id); } - pScreen->DestroyPixmap = destroyPixmap[pScreen->myNum]; + pScreen->DestroyPixmap = screen_priv->destroyPixmap; ret = (*pScreen->DestroyPixmap) (pPixmap); - destroyPixmap[pScreen->myNum] = pScreen->DestroyPixmap; + screen_priv->destroyPixmap = pScreen->DestroyPixmap; pScreen->DestroyPixmap = ShmDestroyPixmap; return ret; } @@ -298,7 +338,7 @@ ShmDestroyPixmap (PixmapPtr pPixmap) void ShmRegisterFbFuncs(ScreenPtr pScreen) { - shmFuncs[pScreen->myNum] = &fbFuncs; + ShmRegisterFuncs(pScreen, &fbFuncs); } static int @@ -578,7 +618,6 @@ static int ProcPanoramiXShmGetImage(ClientPtr client) { PanoramiXRes *draw; - DrawablePtr drawables[MAXSCREENS]; DrawablePtr pDraw; xShmGetImageReply xgi; ShmDescPtr shmdesc; @@ -767,9 +806,11 @@ CreatePmap: result = (client->noClientException); FOR_NSCREENS(j) { + ShmScrPrivateRec *screen_priv; pScreen = screenInfo.screens[j]; - pMap = (*shmFuncs[j]->CreatePixmap)(pScreen, + screen_priv = ShmGetScreenPriv(pScreen); + pMap = (*screen_priv->shmFuncs->CreatePixmap)(pScreen, stuff->width, stuff->height, stuff->depth, shmdesc->addr + stuff->offset); @@ -1052,6 +1093,7 @@ ProcShmCreatePixmap(ClientPtr client) DepthPtr pDepth; int i, rc; ShmDescPtr shmdesc; + ShmScrPrivateRec *screen_priv; REQUEST(xShmCreatePixmapReq); unsigned int width, height, depth; unsigned long size; @@ -1100,7 +1142,8 @@ CreatePmap: return BadAlloc; VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); - pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)( + screen_priv = ShmGetScreenPriv(pDraw->pScreen); + pMap = (*screen_priv->shmFuncs->CreatePixmap)( pDraw->pScreen, stuff->width, stuff->height, stuff->depth, shmdesc->addr + stuff->offset); diff --git a/xorg-server/Xext/xselinux.c b/xorg-server/Xext/xselinux.c deleted file mode 100644 index b9b16b6ce..000000000 --- a/xorg-server/Xext/xselinux.c +++ /dev/null @@ -1,2070 +0,0 @@ -/************************************************************ - -Author: Eamon Walsh - -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. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include "globals.h" -#include "resource.h" -#include "privates.h" -#include "registry.h" -#include "dixstruct.h" -#include "inputstr.h" -#include "windowstr.h" -#include "propertyst.h" -#include "extnsionst.h" -#include "scrnintstr.h" -#include "selection.h" -#include "xacestr.h" -#define _XSELINUX_NEED_FLASK -#include "xselinux.h" -#include "../os/osdep.h" -#include "modinit.h" - - -/* - * Globals - */ - -/* private state keys */ -static int subjectKeyIndex; -static DevPrivateKey subjectKey = &subjectKeyIndex; -static int objectKeyIndex; -static DevPrivateKey objectKey = &objectKeyIndex; -static int dataKeyIndex; -static DevPrivateKey dataKey = &dataKeyIndex; - -/* subject state (clients and devices only) */ -typedef struct { - security_id_t sid; - security_id_t dev_create_sid; - security_id_t win_create_sid; - security_id_t sel_create_sid; - security_id_t prp_create_sid; - security_id_t sel_use_sid; - security_id_t prp_use_sid; - struct avc_entry_ref aeref; - char *command; - int privileged; -} SELinuxSubjectRec; - -/* object state */ -typedef struct { - security_id_t sid; - int poly; -} SELinuxObjectRec; - -/* selection and property atom cache */ -typedef struct { - SELinuxObjectRec prp; - SELinuxObjectRec sel; -} SELinuxAtomRec; - -/* audit file descriptor */ -static int audit_fd; - -/* structure passed to auditing callback */ -typedef struct { - ClientPtr client; /* client */ - DeviceIntPtr dev; /* device */ - char *command; /* client's executable path */ - unsigned id; /* resource id, if any */ - int restype; /* resource type, if any */ - int event; /* event type, if any */ - Atom property; /* property name, if any */ - Atom selection; /* selection name, if any */ - char *extension; /* extension name, if any */ -} SELinuxAuditRec; - -/* labeling handle */ -static struct selabel_handle *label_hnd; - -/* whether AVC is active */ -static int avc_active; - -/* atoms for window label properties */ -static Atom atom_ctx; -static Atom atom_client_ctx; - -/* The unlabeled SID */ -static security_id_t unlabeled_sid; - -/* Array of object classes indexed by resource type */ -static security_class_t *knownTypes; -static unsigned numKnownTypes; - -/* Array of event SIDs indexed by event type */ -static security_id_t *knownEvents; -static unsigned numKnownEvents; - -/* Array of property and selection SID structures */ -static SELinuxAtomRec *knownAtoms; -static unsigned numKnownAtoms; - -/* forward declarations */ -static void SELinuxScreen(CallbackListPtr *, pointer, pointer); - -/* "true" pointer value for use as callback data */ -static pointer truep = (pointer)1; - - -/* - * Support Routines - */ - -/* - * Looks up a name in the selection or property mappings - */ -static int -SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec *obj, int map, int polymap) -{ - const char *name = NameForAtom(atom); - security_context_t ctx; - int rc = Success; - - obj->poly = 1; - - /* Look in the mappings of names to contexts */ - if (selabel_lookup_raw(label_hnd, &ctx, name, map) == 0) { - obj->poly = 0; - } else if (errno != ENOENT) { - ErrorF("SELinux: a property label lookup failed!\n"); - return BadValue; - } else if (selabel_lookup_raw(label_hnd, &ctx, name, polymap) < 0) { - ErrorF("SELinux: a property label lookup failed!\n"); - return BadValue; - } - - /* Get a SID for context */ - if (avc_context_to_sid_raw(ctx, &obj->sid) < 0) { - ErrorF("SELinux: a context_to_SID_raw call failed!\n"); - rc = BadAlloc; - } - - freecon(ctx); - return rc; -} - -/* - * Looks up the SID corresponding to the given property or selection atom - */ -static int -SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn) -{ - SELinuxObjectRec *obj; - int rc, map, polymap; - - if (atom >= numKnownAtoms) { - /* Need to increase size of atoms array */ - unsigned size = sizeof(SELinuxAtomRec); - knownAtoms = xrealloc(knownAtoms, (atom + 1) * size); - if (!knownAtoms) - return BadAlloc; - memset(knownAtoms + numKnownAtoms, 0, - (atom - numKnownAtoms + 1) * size); - numKnownAtoms = atom + 1; - } - - if (prop) { - obj = &knownAtoms[atom].prp; - map = SELABEL_X_PROP; - polymap = SELABEL_X_POLYPROP; - } else { - obj = &knownAtoms[atom].sel; - map = SELABEL_X_SELN; - polymap = SELABEL_X_POLYSELN; - } - - if (!obj->sid) { - rc = SELinuxAtomToSIDLookup(atom, obj, map, polymap); - if (rc != Success) - goto out; - } - - *obj_rtn = obj; - rc = Success; -out: - return rc; -} - -/* - * Looks up a SID for a selection/subject pair - */ -static int -SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec *subj, - security_id_t *sid_rtn, int *poly_rtn) -{ - int rc; - SELinuxObjectRec *obj; - security_id_t tsid; - - /* Get the default context and polyinstantiation bit */ - rc = SELinuxAtomToSID(selection, 0, &obj); - if (rc != Success) - return rc; - - /* Check for an override context next */ - if (subj->sel_use_sid) { - sidget(tsid = subj->sel_use_sid); - goto out; - } - - sidget(tsid = obj->sid); - - /* Polyinstantiate if necessary to obtain the final SID */ - if (obj->poly) { - sidput(tsid); - if (avc_compute_member(subj->sid, obj->sid, - SECCLASS_X_SELECTION, &tsid) < 0) { - ErrorF("SELinux: a compute_member call failed!\n"); - return BadValue; - } - } -out: - *sid_rtn = tsid; - if (poly_rtn) - *poly_rtn = obj->poly; - return Success; -} - -/* - * Looks up a SID for a property/subject pair - */ -static int -SELinuxPropertyToSID(Atom property, SELinuxSubjectRec *subj, - security_id_t *sid_rtn, int *poly_rtn) -{ - int rc; - SELinuxObjectRec *obj; - security_id_t tsid, tsid2; - - /* Get the default context and polyinstantiation bit */ - rc = SELinuxAtomToSID(property, 1, &obj); - if (rc != Success) - return rc; - - /* Check for an override context next */ - if (subj->prp_use_sid) { - sidget(tsid = subj->prp_use_sid); - goto out; - } - - /* Perform a transition */ - if (avc_compute_create(subj->sid, obj->sid, - SECCLASS_X_PROPERTY, &tsid) < 0) { - ErrorF("SELinux: a compute_create call failed!\n"); - return BadValue; - } - - /* Polyinstantiate if necessary to obtain the final SID */ - if (obj->poly) { - tsid2 = tsid; - if (avc_compute_member(subj->sid, tsid2, - SECCLASS_X_PROPERTY, &tsid) < 0) { - ErrorF("SELinux: a compute_member call failed!\n"); - sidput(tsid2); - return BadValue; - } - sidput(tsid2); - } -out: - *sid_rtn = tsid; - if (poly_rtn) - *poly_rtn = obj->poly; - return Success; -} - -/* - * Looks up the SID corresponding to the given event type - */ -static int -SELinuxEventToSID(unsigned type, security_id_t sid_of_window, - SELinuxObjectRec *sid_return) -{ - const char *name = LookupEventName(type); - security_context_t ctx; - type &= 127; - - 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); - numKnownEvents = type + 1; - } - - if (!knownEvents[type]) { - /* Look in the mappings of event names to contexts */ - if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EVENT) < 0) { - ErrorF("SELinux: an event label lookup failed!\n"); - return BadValue; - } - /* Get a SID for context */ - if (avc_context_to_sid_raw(ctx, knownEvents + type) < 0) { - ErrorF("SELinux: a context_to_SID_raw call failed!\n"); - return BadAlloc; - } - freecon(ctx); - } - - /* Perform a transition to obtain the final SID */ - if (avc_compute_create(sid_of_window, knownEvents[type], SECCLASS_X_EVENT, - &sid_return->sid) < 0) { - ErrorF("SELinux: a compute_create call failed!\n"); - return BadValue; - } - - return Success; -} - -/* - * Returns the object class corresponding to the given resource type. - */ -static security_class_t -SELinuxTypeToClass(RESTYPE type) -{ - 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); - numKnownTypes = type + 1; - } - - 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; - - /* 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; - } - - return knownTypes[type]; -} - -/* - * Performs an SELinux permission check. - */ -static int -SELinuxDoCheck(SELinuxSubjectRec *subj, SELinuxObjectRec *obj, - security_class_t class, Mask mode, SELinuxAuditRec *auditdata) -{ - /* serverClient requests OK */ - if (subj->privileged) - return Success; - - auditdata->command = subj->command; - errno = 0; - - if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref, - auditdata) < 0) { - if (mode == DixUnknownAccess) - return Success; /* DixUnknownAccess requests OK ... for now */ - if (errno == EACCES) - return BadAccess; - ErrorF("SELinux: avc_has_perm: unexpected error %d\n", errno); - return BadValue; - } - - return Success; -} - -/* - * Labels a newly connected client. - */ -static void -SELinuxLabelClient(ClientPtr client) -{ - int fd = XaceGetConnectionNumber(client); - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - security_context_t ctx; - - subj = dixLookupPrivate(&client->devPrivates, subjectKey); - sidput(subj->sid); - obj = dixLookupPrivate(&client->devPrivates, objectKey); - sidput(obj->sid); - - /* Try to get a context from the socket */ - if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) { - /* Otherwise, fall back to a default context */ - if (selabel_lookup_raw(label_hnd, &ctx, "remote", SELABEL_X_CLIENT) < 0) - FatalError("SELinux: failed to look up remote-client context\n"); - } - - /* For local clients, try and determine the executable name */ - if (XaceIsLocal(client)) { - struct ucred creds; - socklen_t len = sizeof(creds); - char path[PATH_MAX + 1]; - size_t bytes; - - 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; - - subj->command = xalloc(bytes); - if (!subj->command) - goto finish; - - memcpy(subj->command, path, bytes); - subj->command[bytes - 1] = 0; - } - -finish: - /* Get a SID from the context */ - if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) - FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n", - client->index, ctx); - - sidget(obj->sid = subj->sid); - freecon(ctx); -} - -/* - * Labels initial server objects. - */ -static void -SELinuxLabelInitial(void) -{ - int i; - XaceScreenAccessRec srec; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - security_context_t ctx; - pointer unused; - - /* Do the serverClient */ - subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey); - obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); - subj->privileged = 1; - sidput(subj->sid); - - /* Use the context of the X server process for the serverClient */ - if (getcon_raw(&ctx) < 0) - FatalError("SELinux: couldn't get context of X server process\n"); - - /* Get a SID from the context */ - if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) - FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx); - - sidget(obj->sid = subj->sid); - 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 */ - dixLookupResourceByType(&unused, screenInfo.screens[i]->defColormap, - RT_COLORMAP, serverClient, DixCreateAccess); - } -} - -/* - * Labels new resource objects. - */ -static int -SELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj, - SELinuxObjectRec *obj, security_class_t class) -{ - int offset; - security_id_t tsid; - - /* Check for a create context */ - if (rec->rtype == RT_WINDOW && subj->win_create_sid) { - sidget(obj->sid = subj->win_create_sid); - return Success; - } - - if (rec->parent) - offset = dixLookupPrivateOffset(rec->ptype); - - if (rec->parent && offset >= 0) { - /* Use the SID of the parent object in the labeling operation */ - PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset); - SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey); - tsid = pobj->sid; - } else { - /* Use the SID of the subject */ - tsid = subj->sid; - } - - /* Perform a transition to obtain the final SID */ - if (avc_compute_create(subj->sid, tsid, class, &obj->sid) < 0) { - ErrorF("SELinux: a compute_create call failed!\n"); - return BadValue; - } - - return Success; -} - - -/* - * Libselinux Callbacks - */ - -static int -SELinuxAudit(void *auditdata, - security_class_t class, - char *msgbuf, - size_t msgbufsize) -{ - SELinuxAuditRec *audit = auditdata; - ClientPtr client = audit->client; - char idNum[16]; - const char *propertyName, *selectionName; - int major = -1, minor = -1; - - if (client) { - REQUEST(xReq); - if (stuff) { - major = stuff->reqType; - minor = MinorOpcodeOfRequest(client); - } - } - if (audit->id) - snprintf(idNum, 16, "%x", audit->id); - - propertyName = audit->property ? NameForAtom(audit->property) : NULL; - selectionName = audit->selection ? NameForAtom(audit->selection) : NULL; - - return snprintf(msgbuf, msgbufsize, - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", - (major >= 0) ? "request=" : "", - (major >= 0) ? LookupRequestName(major, minor) : "", - audit->command ? " comm=" : "", - audit->command ? audit->command : "", - audit->dev ? " xdevice=\"" : "", - audit->dev ? audit->dev->name : "", - audit->dev ? "\"" : "", - audit->id ? " resid=" : "", - audit->id ? idNum : "", - audit->restype ? " restype=" : "", - audit->restype ? LookupResourceName(audit->restype) : "", - audit->event ? " event=" : "", - audit->event ? LookupEventName(audit->event & 127) : "", - audit->property ? " property=" : "", - audit->property ? propertyName : "", - audit->selection ? " selection=" : "", - audit->selection ? selectionName : "", - audit->extension ? " extension=" : "", - audit->extension ? audit->extension : ""); -} - -static int -SELinuxLog(int type, const char *fmt, ...) -{ - va_list ap; - char buf[MAX_AUDIT_MESSAGE_LENGTH]; - int rc, aut; - - switch (type) { - case SELINUX_INFO: - aut = AUDIT_USER_MAC_POLICY_LOAD; - break; - case SELINUX_AVC: - aut = AUDIT_USER_AVC; - break; - default: - aut = AUDIT_USER_SELINUX_ERR; - break; - } - - va_start(ap, fmt); - vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap); - rc = audit_log_user_avc_message(audit_fd, aut, buf, NULL, NULL, NULL, 0); - va_end(ap); - LogMessageVerb(X_WARNING, 0, "%s", buf); - return 0; -} - -/* - * XACE Callbacks - */ - -static void -SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceDeviceAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - if (rec->access_mode & DixCreateAccess) { - SELinuxSubjectRec *dsubj; - dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); - - sidput(dsubj->sid); - sidput(obj->sid); - - if (subj->dev_create_sid) { - /* Label the device with the create context */ - sidget(obj->sid = subj->dev_create_sid); - sidget(dsubj->sid = subj->dev_create_sid); - } else { - /* Label the device directly with the process SID */ - sidget(obj->sid = subj->sid); - sidget(dsubj->sid = subj->sid); - } - } - - /* XXX only check read permission on XQueryKeymap */ - /* This is to allow the numerous apps that call XQueryPointer to work */ - if (rec->access_mode & DixReadAccess) { - ClientPtr client = rec->client; - REQUEST(xReq); - if (stuff && stuff->reqType != X_QueryKeymap) { - rec->access_mode &= ~DixReadAccess; - rec->access_mode |= DixGetAttrAccess; - } - } - - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DEVICE, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; -} - -static void -SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceSendAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj, ev_sid; - SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; - security_class_t class; - int rc, i, type; - - if (rec->dev) - subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); - else - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - - obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); - - /* Check send permission on window */ - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess, - &auditdata); - if (rc != Success) - goto err; - - /* Check send permission on specific event types */ - for (i = 0; i < rec->count; i++) { - type = rec->events[i].u.u.type; - class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; - - rc = SELinuxEventToSID(type, obj->sid, &ev_sid); - if (rc != Success) - goto err; - - auditdata.event = type; - rc = SELinuxDoCheck(subj, &ev_sid, class, DixSendAccess, &auditdata); - if (rc != Success) - goto err; - } - return; -err: - rec->status = rc; -} - -static void -SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceReceiveAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj, ev_sid; - SELinuxAuditRec auditdata = { .client = NULL }; - security_class_t class; - int rc, i, type; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); - - /* Check receive permission on window */ - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess, - &auditdata); - if (rc != Success) - goto err; - - /* Check receive permission on specific event types */ - for (i = 0; i < rec->count; i++) { - type = rec->events[i].u.u.type; - class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; - - rc = SELinuxEventToSID(type, obj->sid, &ev_sid); - if (rc != Success) - goto err; - - auditdata.event = type; - rc = SELinuxDoCheck(subj, &ev_sid, class, DixReceiveAccess, &auditdata); - if (rc != Success) - goto err; - } - return; -err: - rec->status = rc; -} - -static void -SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceExtAccessRec *rec = calldata; - SELinuxSubjectRec *subj, *serv; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey); - - /* 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 ctx; - security_id_t sid; - - serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey); - - /* Look in the mappings of extension names to contexts */ - if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EXT) < 0) { - ErrorF("SELinux: a property label lookup failed!\n"); - rec->status = BadValue; - return; - } - /* Get a SID for context */ - if (avc_context_to_sid_raw(ctx, &sid) < 0) { - ErrorF("SELinux: a context_to_SID_raw call failed!\n"); - rec->status = BadAlloc; - return; - } - - sidput(obj->sid); - - /* Perform a transition to obtain the final SID */ - if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION, - &obj->sid) < 0) { - ErrorF("SELinux: a SID transition call failed!\n"); - freecon(ctx); - rec->status = BadValue; - return; - } - freecon(ctx); - } - - /* Perform the security check */ - auditdata.extension = rec->ext->name; - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_EXTENSION, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; -} - -static void -SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceSelectionAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj, *data; - Selection *pSel = *rec->ppSel; - Atom name = pSel->selection; - Mask access_mode = rec->access_mode; - SELinuxAuditRec auditdata = { .client = rec->client, .selection = name }; - security_id_t tsid; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&pSel->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - if (access_mode & DixCreateAccess) { - sidput(obj->sid); - rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly); - if (rc != Success) - obj->sid = unlabeled_sid; - access_mode = DixSetAttrAccess; - } - /* If this is a polyinstantiated object, find the right instance */ - else if (obj->poly) { - rc = SELinuxSelectionToSID(name, subj, &tsid, NULL); - if (rc != Success) { - rec->status = rc; - return; - } - while (pSel->selection != name || obj->sid != tsid) { - if ((pSel = pSel->next) == NULL) - break; - obj = dixLookupPrivate(&pSel->devPrivates, objectKey); - } - sidput(tsid); - - if (pSel) - *rec->ppSel = pSel; - else { - rec->status = BadMatch; - return; - } - } - - /* Perform the security check */ - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; - - /* Label the content (advisory only) */ - if (access_mode & DixSetAttrAccess) { - data = dixLookupPrivate(&pSel->devPrivates, dataKey); - sidput(data->sid); - if (subj->sel_create_sid) - sidget(data->sid = subj->sel_create_sid); - else - sidget(data->sid = obj->sid); - } -} - -static void -SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XacePropertyAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj, *data; - PropertyPtr pProp = *rec->ppProp; - Atom name = pProp->propertyName; - SELinuxAuditRec auditdata = { .client = rec->client, .property = name }; - security_id_t tsid; - int rc; - - /* Don't care about the new content check */ - if (rec->access_mode & DixPostAccess) - return; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&pProp->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - if (rec->access_mode & DixCreateAccess) { - sidput(obj->sid); - rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly); - if (rc != Success) { - rec->status = rc; - return; - } - } - /* If this is a polyinstantiated object, find the right instance */ - else if (obj->poly) { - rc = SELinuxPropertyToSID(name, subj, &tsid, NULL); - if (rc != Success) { - rec->status = rc; - return; - } - while (pProp->propertyName != name || obj->sid != tsid) { - if ((pProp = pProp->next) == NULL) - break; - obj = dixLookupPrivate(&pProp->devPrivates, objectKey); - } - sidput(tsid); - - if (pProp) - *rec->ppProp = pProp; - else { - rec->status = BadMatch; - return; - } - } - - /* Perform the security check */ - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; - - /* Label the content (advisory only) */ - if (rec->access_mode & DixWriteAccess) { - data = dixLookupPrivate(&pProp->devPrivates, dataKey); - sidput(data->sid); - if (subj->prp_create_sid) - sidget(data->sid = subj->prp_create_sid); - else - sidget(data->sid = obj->sid); - } -} - -static void -SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceResourceAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - Mask access_mode = rec->access_mode; - PrivateRec **privatePtr; - security_class_t class; - int rc, offset; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - - /* 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; - obj = dixLookupPrivate(privatePtr, objectKey); - } else { - /* Yes: use the SID from the resource object itself */ - class = SELinuxTypeToClass(rec->rtype); - privatePtr = DEVPRIV_AT(rec->res, offset); - obj = dixLookupPrivate(privatePtr, objectKey); - } - - /* If this is a new object that needs labeling, do it now */ - if (access_mode & DixCreateAccess && offset >= 0) { - rc = SELinuxLabelResource(rec, subj, obj, class); - if (rc != Success) { - rec->status = rc; - return; - } - } - - /* Collapse generic resource permissions down to read/write */ - if (class == SECCLASS_X_RESOURCE) { - access_mode = !!(rec->access_mode & SELinuxReadMask); /* rd */ - access_mode |= !!(rec->access_mode & ~SELinuxReadMask) << 1; /* wr */ - } - - /* Perform the security check */ - auditdata.restype = rec->rtype; - auditdata.id = rec->id; - rc = SELinuxDoCheck(subj, obj, class, access_mode, &auditdata); - if (rc != Success) - rec->status = rc; - - /* Perform the background none check on windows */ - if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW) { - rc = SELinuxDoCheck(subj, obj, class, DixBlendAccess, &auditdata); - if (rc != Success) - ((WindowPtr)rec->res)->forcedBG = TRUE; - } -} - -static void -SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata) -{ - XaceScreenAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - Mask access_mode = rec->access_mode; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - if (access_mode & DixCreateAccess) { - sidput(obj->sid); - - /* Perform a transition to obtain the final SID */ - if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN, - &obj->sid) < 0) { - ErrorF("SELinux: a compute_create call failed!\n"); - rec->status = BadValue; - return; - } - } - - if (is_saver) - access_mode <<= 2; - - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SCREEN, access_mode, &auditdata); - if (rc != Success) - rec->status = rc; -} - -static void -SELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceClientAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->target->devPrivates, objectKey); - - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; -} - -static void -SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceServerAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); - - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; -} - - -/* - * DIX Callbacks - */ - -static void -SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - NewClientInfoRec *pci = calldata; - - switch (pci->client->clientState) { - case ClientStateInitial: - SELinuxLabelClient(pci->client); - break; - - default: - break; - } -} - -static void -SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - ResourceStateInfoRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - WindowPtr pWin; - - if (rec->type != RT_WINDOW) - return; - if (rec->state != ResourceStateAdding) - return; - - pWin = (WindowPtr)rec->value; - subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey); - - if (subj->sid) { - security_context_t ctx; - int rc = avc_sid_to_context_raw(subj->sid, &ctx); - if (rc < 0) - FatalError("SELinux: Failed to get security context!\n"); - rc = dixChangeWindowProperty(serverClient, - pWin, atom_client_ctx, XA_STRING, 8, - PropModeReplace, strlen(ctx), ctx, FALSE); - if (rc != Success) - FatalError("SELinux: Failed to set label property on window!\n"); - freecon(ctx); - } else - FatalError("SELinux: Unexpected unlabeled client found\n"); - - obj = dixLookupPrivate(&pWin->devPrivates, objectKey); - - if (obj->sid) { - security_context_t ctx; - int rc = avc_sid_to_context_raw(obj->sid, &ctx); - if (rc < 0) - FatalError("SELinux: Failed to get security context!\n"); - rc = dixChangeWindowProperty(serverClient, - pWin, atom_ctx, XA_STRING, 8, - PropModeReplace, strlen(ctx), ctx, FALSE); - if (rc != Success) - FatalError("SELinux: Failed to set label property on window!\n"); - freecon(ctx); - } else - FatalError("SELinux: Unexpected unlabeled window found\n"); -} - - -/* - * DevPrivates Callbacks - */ - -static void -SELinuxSubjectInit(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - PrivateCallbackRec *rec = calldata; - SELinuxSubjectRec *subj = *rec->value; - - sidget(unlabeled_sid); - 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); - - if (avc_active) { - sidput(subj->sid); - sidput(subj->dev_create_sid); - sidput(subj->win_create_sid); - sidput(subj->sel_create_sid); - sidput(subj->prp_create_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); -} - - -/* - * Extension Dispatch - */ - -#define CTX_DEV offsetof(SELinuxSubjectRec, dev_create_sid) -#define CTX_WIN offsetof(SELinuxSubjectRec, win_create_sid) -#define CTX_PRP offsetof(SELinuxSubjectRec, prp_create_sid) -#define CTX_SEL offsetof(SELinuxSubjectRec, sel_create_sid) -#define USE_PRP offsetof(SELinuxSubjectRec, prp_use_sid) -#define USE_SEL offsetof(SELinuxSubjectRec, sel_use_sid) - -typedef struct { - security_context_t octx; - security_context_t dctx; - CARD32 octx_len; - CARD32 dctx_len; - CARD32 id; -} SELinuxListItemRec; - -static security_context_t -SELinuxCopyContext(char *ptr, unsigned len) -{ - security_context_t copy = xalloc(len + 1); - if (!copy) - return NULL; - strncpy(copy, ptr, len); - copy[len] = '\0'; - return copy; -} - -static int -ProcSELinuxQueryVersion(ClientPtr client) -{ - SELinuxQueryVersionReply rep; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.server_major = SELINUX_MAJOR_VERSION; - rep.server_minor = SELINUX_MINOR_VERSION; - 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 -SELinuxSendContextReply(ClientPtr client, security_id_t sid) -{ - SELinuxGetContextReply rep; - security_context_t ctx = NULL; - int len = 0; - - if (sid) { - if (avc_sid_to_context_raw(sid, &ctx) < 0) - return BadValue; - len = strlen(ctx) + 1; - } - - rep.type = X_Reply; - rep.length = bytes_to_int32(len); - rep.sequenceNumber = client->sequence; - rep.context_len = len; - - if (client->swapped) { - int n; - swapl(&rep.length, n); - swaps(&rep.sequenceNumber, n); - swapl(&rep.context_len, n); - } - - WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep); - WriteToClient(client, len, ctx); - freecon(ctx); - return client->noClientException; -} - -static int -ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset) -{ - PrivateRec **privPtr = &client->devPrivates; - security_id_t *pSid; - security_context_t ctx = NULL; - char *ptr; - int rc; - - REQUEST(SELinuxSetCreateContextReq); - REQUEST_FIXED_SIZE(SELinuxSetCreateContextReq, stuff->context_len); - - if (stuff->context_len > 0) { - ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len); - if (!ctx) - return BadAlloc; - } - - ptr = dixLookupPrivate(privPtr, subjectKey); - pSid = (security_id_t *)(ptr + offset); - sidput(*pSid); - *pSid = NULL; - - rc = Success; - if (stuff->context_len > 0) { - if (security_check_context_raw(ctx) < 0 || - avc_context_to_sid_raw(ctx, pSid) < 0) - rc = BadValue; - } - - xfree(ctx); - return rc; -} - -static int -ProcSELinuxGetCreateContext(ClientPtr client, unsigned offset) -{ - security_id_t *pSid; - char *ptr; - - REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq); - - if (offset == CTX_DEV) - ptr = dixLookupPrivate(&serverClient->devPrivates, subjectKey); - else - ptr = dixLookupPrivate(&client->devPrivates, subjectKey); - - pSid = (security_id_t *)(ptr + offset); - return SELinuxSendContextReply(client, *pSid); -} - -static int -ProcSELinuxSetDeviceContext(ClientPtr client) -{ - security_context_t ctx; - security_id_t sid; - DeviceIntPtr dev; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - int rc; - - REQUEST(SELinuxSetContextReq); - REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len); - - if (stuff->context_len < 1) - return BadLength; - ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len); - if (!ctx) - return BadAlloc; - - rc = dixLookupDevice(&dev, stuff->id, client, DixManageAccess); - if (rc != Success) - goto out; - - if (security_check_context_raw(ctx) < 0 || - avc_context_to_sid_raw(ctx, &sid) < 0) { - rc = BadValue; - goto out; - } - - subj = dixLookupPrivate(&dev->devPrivates, subjectKey); - sidput(subj->sid); - subj->sid = sid; - obj = dixLookupPrivate(&dev->devPrivates, objectKey); - sidput(obj->sid); - sidget(obj->sid = sid); - - rc = Success; -out: - xfree(ctx); - return rc; -} - -static int -ProcSELinuxGetDeviceContext(ClientPtr client) -{ - DeviceIntPtr dev; - SELinuxSubjectRec *subj; - int rc; - - REQUEST(SELinuxGetContextReq); - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - - rc = dixLookupDevice(&dev, stuff->id, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - subj = dixLookupPrivate(&dev->devPrivates, subjectKey); - return SELinuxSendContextReply(client, subj->sid); -} - -static int -ProcSELinuxGetWindowContext(ClientPtr client) -{ - WindowPtr pWin; - SELinuxObjectRec *obj; - int rc; - - REQUEST(SELinuxGetContextReq); - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - - rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - obj = dixLookupPrivate(&pWin->devPrivates, objectKey); - return SELinuxSendContextReply(client, obj->sid); -} - -static int -ProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey) -{ - WindowPtr pWin; - PropertyPtr pProp; - SELinuxObjectRec *obj; - int rc; - - REQUEST(SELinuxGetPropertyContextReq); - REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq); - - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetPropAccess); - if (rc != Success) - return rc; - - rc = dixLookupProperty(&pProp, pWin, stuff->property, client, - DixGetAttrAccess); - if (rc != Success) - return rc; - - obj = dixLookupPrivate(&pProp->devPrivates, privKey); - return SELinuxSendContextReply(client, obj->sid); -} - -static int -ProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey) -{ - Selection *pSel; - SELinuxObjectRec *obj; - int rc; - - REQUEST(SELinuxGetContextReq); - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - - rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - obj = dixLookupPrivate(&pSel->devPrivates, privKey); - return SELinuxSendContextReply(client, obj->sid); -} - -static int -ProcSELinuxGetClientContext(ClientPtr client) -{ - ClientPtr target; - SELinuxSubjectRec *subj; - int rc; - - REQUEST(SELinuxGetContextReq); - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - - rc = dixLookupClient(&target, stuff->id, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - subj = dixLookupPrivate(&target->devPrivates, subjectKey); - return SELinuxSendContextReply(client, subj->sid); -} - -static int -SELinuxPopulateItem(SELinuxListItemRec *i, PrivateRec **privPtr, CARD32 id, - int *size) -{ - SELinuxObjectRec *obj = dixLookupPrivate(privPtr, objectKey); - SELinuxObjectRec *data = dixLookupPrivate(privPtr, dataKey); - - if (avc_sid_to_context_raw(obj->sid, &i->octx) < 0) - return BadValue; - if (avc_sid_to_context_raw(data->sid, &i->dctx) < 0) - return BadValue; - - i->id = id; - i->octx_len = bytes_to_int32(strlen(i->octx) + 1); - i->dctx_len = bytes_to_int32(strlen(i->dctx) + 1); - - *size += i->octx_len + i->dctx_len + 3; - return Success; -} - -static void -SELinuxFreeItems(SELinuxListItemRec *items, int count) -{ - int k; - for (k = 0; k < count; k++) { - freecon(items[k].octx); - freecon(items[k].dctx); - } - xfree(items); -} - -static int -SELinuxSendItemsToClient(ClientPtr client, SELinuxListItemRec *items, - int size, int count) -{ - int rc, k, n, pos = 0; - SELinuxListItemsReply rep; - CARD32 *buf; - - buf = xcalloc(size, sizeof(CARD32)); - if (size && !buf) { - rc = BadAlloc; - goto out; - } - - /* Fill in the buffer */ - for (k = 0; k < count; k++) { - buf[pos] = items[k].id; - if (client->swapped) - swapl(buf + pos, n); - pos++; - - buf[pos] = items[k].octx_len * 4; - if (client->swapped) - swapl(buf + pos, n); - pos++; - - buf[pos] = items[k].dctx_len * 4; - if (client->swapped) - swapl(buf + pos, n); - pos++; - - memcpy((char *)(buf + pos), items[k].octx, strlen(items[k].octx) + 1); - pos += items[k].octx_len; - memcpy((char *)(buf + pos), items[k].dctx, strlen(items[k].dctx) + 1); - pos += items[k].dctx_len; - } - - /* Send reply to client */ - rep.type = X_Reply; - rep.length = size; - rep.sequenceNumber = client->sequence; - rep.count = count; - - if (client->swapped) { - swapl(&rep.length, n); - swaps(&rep.sequenceNumber, n); - swapl(&rep.count, n); - } - - WriteToClient(client, sizeof(SELinuxListItemsReply), (char *)&rep); - WriteToClient(client, size * 4, (char *)buf); - - /* Free stuff and return */ - rc = client->noClientException; - xfree(buf); -out: - SELinuxFreeItems(items, count); - return rc; -} - -static int -ProcSELinuxListProperties(ClientPtr client) -{ - WindowPtr pWin; - PropertyPtr pProp; - SELinuxListItemRec *items; - int rc, count, size, i; - CARD32 id; - - REQUEST(SELinuxGetContextReq); - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - - rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess); - if (rc != Success) - return rc; - - /* Count the number of properties and allocate items */ - count = 0; - for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) - count++; - items = xcalloc(count, sizeof(SELinuxListItemRec)); - if (count && !items) - return BadAlloc; - - /* Fill in the items and calculate size */ - i = 0; - size = 0; - for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) { - id = pProp->propertyName; - rc = SELinuxPopulateItem(items + i, &pProp->devPrivates, id, &size); - if (rc != Success) { - SELinuxFreeItems(items, count); - return rc; - } - i++; - } - - return SELinuxSendItemsToClient(client, items, size, count); -} - -static int -ProcSELinuxListSelections(ClientPtr client) -{ - Selection *pSel; - SELinuxListItemRec *items; - int rc, count, size, i; - CARD32 id; - - REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq); - - /* Count the number of selections and allocate items */ - count = 0; - for (pSel = CurrentSelections; pSel; pSel = pSel->next) - count++; - items = xcalloc(count, sizeof(SELinuxListItemRec)); - if (count && !items) - return BadAlloc; - - /* Fill in the items and calculate size */ - i = 0; - size = 0; - for (pSel = CurrentSelections; pSel; pSel = pSel->next) { - id = pSel->selection; - rc = SELinuxPopulateItem(items + i, &pSel->devPrivates, id, &size); - if (rc != Success) { - SELinuxFreeItems(items, count); - return rc; - } - i++; - } - - return SELinuxSendItemsToClient(client, items, size, count); -} - -static int -ProcSELinuxDispatch(ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) { - case X_SELinuxQueryVersion: - return ProcSELinuxQueryVersion(client); - case X_SELinuxSetDeviceCreateContext: - return ProcSELinuxSetCreateContext(client, CTX_DEV); - case X_SELinuxGetDeviceCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_DEV); - case X_SELinuxSetDeviceContext: - return ProcSELinuxSetDeviceContext(client); - case X_SELinuxGetDeviceContext: - return ProcSELinuxGetDeviceContext(client); - case X_SELinuxSetWindowCreateContext: - return ProcSELinuxSetCreateContext(client, CTX_WIN); - case X_SELinuxGetWindowCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_WIN); - case X_SELinuxGetWindowContext: - return ProcSELinuxGetWindowContext(client); - case X_SELinuxSetPropertyCreateContext: - return ProcSELinuxSetCreateContext(client, CTX_PRP); - case X_SELinuxGetPropertyCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_PRP); - case X_SELinuxSetPropertyUseContext: - return ProcSELinuxSetCreateContext(client, USE_PRP); - case X_SELinuxGetPropertyUseContext: - return ProcSELinuxGetCreateContext(client, USE_PRP); - case X_SELinuxGetPropertyContext: - return ProcSELinuxGetPropertyContext(client, objectKey); - case X_SELinuxGetPropertyDataContext: - return ProcSELinuxGetPropertyContext(client, dataKey); - case X_SELinuxListProperties: - return ProcSELinuxListProperties(client); - case X_SELinuxSetSelectionCreateContext: - return ProcSELinuxSetCreateContext(client, CTX_SEL); - case X_SELinuxGetSelectionCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_SEL); - case X_SELinuxSetSelectionUseContext: - return ProcSELinuxSetCreateContext(client, USE_SEL); - case X_SELinuxGetSelectionUseContext: - return ProcSELinuxGetCreateContext(client, USE_SEL); - case X_SELinuxGetSelectionContext: - return ProcSELinuxGetSelectionContext(client, objectKey); - case X_SELinuxGetSelectionDataContext: - return ProcSELinuxGetSelectionContext(client, dataKey); - case X_SELinuxListSelections: - return ProcSELinuxListSelections(client); - case X_SELinuxGetClientContext: - return ProcSELinuxGetClientContext(client); - default: - return BadRequest; - } -} - -static int -SProcSELinuxQueryVersion(ClientPtr client) -{ - REQUEST(SELinuxQueryVersionReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxQueryVersionReq); - swaps(&stuff->client_major, n); - swaps(&stuff->client_minor, n); - return ProcSELinuxQueryVersion(client); -} - -static int -SProcSELinuxSetCreateContext(ClientPtr client, unsigned offset) -{ - REQUEST(SELinuxSetCreateContextReq); - int n; - - REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq); - swapl(&stuff->context_len, n); - return ProcSELinuxSetCreateContext(client, offset); -} - -static int -SProcSELinuxSetDeviceContext(ClientPtr client) -{ - REQUEST(SELinuxSetContextReq); - int n; - - REQUEST_AT_LEAST_SIZE(SELinuxSetContextReq); - swapl(&stuff->id, n); - swapl(&stuff->context_len, n); - return ProcSELinuxSetDeviceContext(client); -} - -static int -SProcSELinuxGetDeviceContext(ClientPtr client) -{ - REQUEST(SELinuxGetContextReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - swapl(&stuff->id, n); - return ProcSELinuxGetDeviceContext(client); -} - -static int -SProcSELinuxGetWindowContext(ClientPtr client) -{ - REQUEST(SELinuxGetContextReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - swapl(&stuff->id, n); - return ProcSELinuxGetWindowContext(client); -} - -static int -SProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey) -{ - REQUEST(SELinuxGetPropertyContextReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq); - swapl(&stuff->window, n); - swapl(&stuff->property, n); - return ProcSELinuxGetPropertyContext(client, privKey); -} - -static int -SProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey) -{ - REQUEST(SELinuxGetContextReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - swapl(&stuff->id, n); - return ProcSELinuxGetSelectionContext(client, privKey); -} - -static int -SProcSELinuxListProperties(ClientPtr client) -{ - REQUEST(SELinuxGetContextReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - swapl(&stuff->id, n); - return ProcSELinuxListProperties(client); -} - -static int -SProcSELinuxGetClientContext(ClientPtr client) -{ - REQUEST(SELinuxGetContextReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - swapl(&stuff->id, n); - return ProcSELinuxGetClientContext(client); -} - -static int -SProcSELinuxDispatch(ClientPtr client) -{ - REQUEST(xReq); - int n; - - swaps(&stuff->length, n); - - switch (stuff->data) { - case X_SELinuxQueryVersion: - return SProcSELinuxQueryVersion(client); - case X_SELinuxSetDeviceCreateContext: - return SProcSELinuxSetCreateContext(client, CTX_DEV); - case X_SELinuxGetDeviceCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_DEV); - case X_SELinuxSetDeviceContext: - return SProcSELinuxSetDeviceContext(client); - case X_SELinuxGetDeviceContext: - return SProcSELinuxGetDeviceContext(client); - case X_SELinuxSetWindowCreateContext: - return SProcSELinuxSetCreateContext(client, CTX_WIN); - case X_SELinuxGetWindowCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_WIN); - case X_SELinuxGetWindowContext: - return SProcSELinuxGetWindowContext(client); - case X_SELinuxSetPropertyCreateContext: - return SProcSELinuxSetCreateContext(client, CTX_PRP); - case X_SELinuxGetPropertyCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_PRP); - case X_SELinuxSetPropertyUseContext: - return SProcSELinuxSetCreateContext(client, USE_PRP); - case X_SELinuxGetPropertyUseContext: - return ProcSELinuxGetCreateContext(client, USE_PRP); - case X_SELinuxGetPropertyContext: - return SProcSELinuxGetPropertyContext(client, objectKey); - case X_SELinuxGetPropertyDataContext: - return SProcSELinuxGetPropertyContext(client, dataKey); - case X_SELinuxListProperties: - return SProcSELinuxListProperties(client); - case X_SELinuxSetSelectionCreateContext: - return SProcSELinuxSetCreateContext(client, CTX_SEL); - case X_SELinuxGetSelectionCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_SEL); - case X_SELinuxSetSelectionUseContext: - return SProcSELinuxSetCreateContext(client, USE_SEL); - case X_SELinuxGetSelectionUseContext: - return ProcSELinuxGetCreateContext(client, USE_SEL); - case X_SELinuxGetSelectionContext: - return SProcSELinuxGetSelectionContext(client, objectKey); - case X_SELinuxGetSelectionDataContext: - return SProcSELinuxGetSelectionContext(client, dataKey); - case X_SELinuxListSelections: - return ProcSELinuxListSelections(client); - case X_SELinuxGetClientContext: - return SProcSELinuxGetClientContext(client); - default: - return BadRequest; - } -} - -#ifdef HAVE_AVC_NETLINK_ACQUIRE_FD -static int netlink_fd; - -static void -SELinuxBlockHandler(void *data, struct timeval **tv, void *read_mask) -{ -} - -static void -SELinuxWakeupHandler(void *data, int err, void *read_mask) -{ - if (FD_ISSET(netlink_fd, (fd_set *)read_mask)) - avc_netlink_check_nb(); -} -#endif - - -/* - * Extension Setup / Teardown - */ - -static void -SELinuxResetProc(ExtensionEntry *extEntry) -{ - /* Unregister callbacks */ - DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL); - DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL); - - 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); - XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); - XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); - XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); - - /* Tear down SELinux stuff */ - selabel_close(label_hnd); - label_hnd = NULL; - - audit_close(audit_fd); -#ifdef HAVE_AVC_NETLINK_ACQUIRE_FD - avc_netlink_release_fd(); - RemoveBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, - NULL); - RemoveGeneralSocket(netlink_fd); -#endif - - avc_destroy(); - avc_active = 0; - - /* Free local state */ - xfree(knownAtoms); - knownAtoms = NULL; - numKnownAtoms = 0; - - xfree(knownEvents); - knownEvents = NULL; - numKnownEvents = 0; - - xfree(knownTypes); - knownTypes = NULL; - numKnownTypes = 0; -} - -void -SELinuxExtensionInit(INITARGS) -{ - ExtensionEntry *extEntry; - struct selinux_opt selabel_option = { SELABEL_OPT_VALIDATE, (char *)1 }; - struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 }; - security_context_t ctx; - int ret = TRUE; - - /* Check SELinux mode on system */ - if (!is_selinux_enabled()) { - ErrorF("SELinux: Disabled on system, not enabling in X server\n"); - return; - } - - /* Don't init unless there's something to do */ - if (!security_get_boolean_active("xserver_object_manager")) - return; - - /* Check SELinux mode in configuration file */ - switch(selinuxEnforcingState) { - case SELINUX_MODE_DISABLED: - LogMessage(X_INFO, "SELinux: Disabled in configuration file\n"); - return; - case SELINUX_MODE_ENFORCING: - LogMessage(X_INFO, "SELinux: Configured in enforcing mode\n"); - avc_option.value = (char *)1; - break; - case SELINUX_MODE_PERMISSIVE: - LogMessage(X_INFO, "SELinux: Configured in permissive mode\n"); - avc_option.value = (char *)0; - break; - default: - avc_option.type = AVC_OPT_UNUSED; - break; - } - - /* Set up SELinux stuff */ - selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)SELinuxLog); - selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)SELinuxAudit); - - if (selinux_set_mapping(map) < 0) { - if (errno == EINVAL) { - ErrorF("SELinux: Invalid object class mapping, disabling SELinux support.\n"); - return; - } - FatalError("SELinux: Failed to set up security class mapping\n"); - } - - if (avc_open(&avc_option, 1) < 0) - FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n"); - avc_active = 1; - - label_hnd = selabel_open(SELABEL_CTX_X, &selabel_option, 1); - if (!label_hnd) - FatalError("SELinux: Failed to open x_contexts mapping in policy\n"); - - if (security_get_initial_context_raw("unlabeled", &ctx) < 0) - FatalError("SELinux: Failed to look up unlabeled context\n"); - if (avc_context_to_sid_raw(ctx, &unlabeled_sid) < 0) - FatalError("SELinux: a context_to_SID call failed!\n"); - freecon(ctx); - - /* Prepare for auditing */ - audit_fd = audit_open(); - if (audit_fd < 0) - FatalError("SELinux: Failed to open the system audit log\n"); - - /* Allocate private storage */ - if (!dixRequestPrivate(subjectKey, sizeof(SELinuxSubjectRec)) || - !dixRequestPrivate(objectKey, sizeof(SELinuxObjectRec)) || - !dixRequestPrivate(dataKey, sizeof(SELinuxObjectRec))) - FatalError("SELinux: Failed to allocate private storage.\n"); - - /* Create atoms for doing window labeling */ - atom_ctx = MakeAtom("_SELINUX_CONTEXT", 16, TRUE); - if (atom_ctx == BAD_RESOURCE) - FatalError("SELinux: Failed to create atom\n"); - atom_client_ctx = MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE); - if (atom_client_ctx == BAD_RESOURCE) - FatalError("SELinux: Failed to create atom\n"); - -#ifdef HAVE_AVC_NETLINK_ACQUIRE_FD - netlink_fd = avc_netlink_acquire_fd(); - AddGeneralSocket(netlink_fd); - RegisterBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, - NULL); -#endif - - /* Register callbacks */ - ret &= dixRegisterPrivateInitFunc(subjectKey, SELinuxSubjectInit, NULL); - ret &= dixRegisterPrivateDeleteFunc(subjectKey, SELinuxSubjectFree, NULL); - ret &= dixRegisterPrivateInitFunc(objectKey, SELinuxObjectInit, NULL); - ret &= dixRegisterPrivateDeleteFunc(objectKey, SELinuxObjectFree, NULL); - ret &= dixRegisterPrivateInitFunc(dataKey, SELinuxObjectInit, NULL); - ret &= dixRegisterPrivateDeleteFunc(dataKey, SELinuxObjectFree, NULL); - - ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL); - ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL); - - 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); - ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); - ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); - ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); - if (!ret) - FatalError("SELinux: Failed to register one or more callbacks\n"); - - /* Add extension to server */ - extEntry = AddExtension(SELINUX_EXTENSION_NAME, - SELinuxNumberEvents, SELinuxNumberErrors, - ProcSELinuxDispatch, SProcSELinuxDispatch, - SELinuxResetProc, StandardMinorOpcode); - - AddExtensionAlias("Flask", extEntry); - - /* Label objects that were created before we could register ourself */ - SELinuxLabelInitial(); -} diff --git a/xorg-server/Xext/xselinux.h b/xorg-server/Xext/xselinux.h index e99f05b09..dcd250e76 100644 --- a/xorg-server/Xext/xselinux.h +++ b/xorg-server/Xext/xselinux.h @@ -20,8 +20,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef _XSELINUX_H #define _XSELINUX_H -#include "dixaccess.h" - /* Extension info */ #define SELINUX_EXTENSION_NAME "SELinux" #define SELINUX_MAJOR_VERSION 1 @@ -138,414 +136,4 @@ typedef struct { CARD32 pad6; } SELinuxListItemsReply; - -#ifdef _XSELINUX_NEED_FLASK -/* Private Flask definitions */ -#define SECCLASS_X_DRAWABLE 1 -#define SECCLASS_X_SCREEN 2 -#define SECCLASS_X_GC 3 -#define SECCLASS_X_FONT 4 -#define SECCLASS_X_COLORMAP 5 -#define SECCLASS_X_PROPERTY 6 -#define SECCLASS_X_SELECTION 7 -#define SECCLASS_X_CURSOR 8 -#define SECCLASS_X_CLIENT 9 -#define SECCLASS_X_DEVICE 10 -#define SECCLASS_X_SERVER 11 -#define SECCLASS_X_EXTENSION 12 -#define SECCLASS_X_EVENT 13 -#define SECCLASS_X_FAKEEVENT 14 -#define SECCLASS_X_RESOURCE 15 - -/* Mapping from DixAccess bits to Flask permissions */ -static struct security_class_mapping map[] = { - { "x_drawable", - { "read", /* DixReadAccess */ - "write", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "list_property", /* DixListPropAccess */ - "get_property", /* DixGetPropAccess */ - "set_property", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "list_child", /* DixListAccess */ - "add_child", /* DixAddAccess */ - "remove_child", /* DixRemoveAccess */ - "hide", /* DixHideAccess */ - "show", /* DixShowAccess */ - "blend", /* DixBlendAccess */ - "override", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "send", /* DixSendAccess */ - "receive", /* DixReceiveAccess */ - "", /* DixUseAccess */ - "manage", /* DixManageAccess */ - NULL }}, - { "x_screen", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "", /* DixDestroyAccess */ - "", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "saver_getattr", /* DixListPropAccess */ - "saver_setattr", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "hide_cursor", /* DixHideAccess */ - "show_cursor", /* DixShowAccess */ - "saver_hide", /* DixBlendAccess */ - "saver_show", /* DixGrabAccess */ - NULL }}, - { "x_gc", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "use", /* DixUseAccess */ - NULL }}, - { "x_font", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "add_glyph", /* DixAddAccess */ - "remove_glyph", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "use", /* DixUseAccess */ - NULL }}, - { "x_colormap", - { "read", /* DixReadAccess */ - "write", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "add_color", /* DixAddAccess */ - "remove_color", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "install", /* DixInstallAccess */ - "uninstall", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "use", /* DixUseAccess */ - NULL }}, - { "x_property", - { "read", /* DixReadAccess */ - "write", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "write", /* DixBlendAccess */ - NULL }}, - { "x_selection", - { "read", /* DixReadAccess */ - "", /* DixWriteAccess */ - "", /* DixDestroyAccess */ - "setattr", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - NULL }}, - { "x_cursor", - { "read", /* DixReadAccess */ - "write", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "use", /* DixUseAccess */ - NULL }}, - { "x_client", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "", /* DixUseAccess */ - "manage", /* DixManageAccess */ - NULL }}, - { "x_device", - { "read", /* DixReadAccess */ - "write", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "list_property", /* DixListPropAccess */ - "get_property", /* DixGetPropAccess */ - "set_property", /* DixSetPropAccess */ - "getfocus", /* DixGetFocusAccess */ - "setfocus", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "add", /* DixAddAccess */ - "remove", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "grab", /* DixGrabAccess */ - "freeze", /* DixFreezeAccess */ - "force_cursor", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "use", /* DixUseAccess */ - "manage", /* DixManageAccess */ - "", /* DixDebugAccess */ - "bell", /* DixBellAccess */ - NULL }}, - { "x_server", - { "record", /* DixReadAccess */ - "", /* DixWriteAccess */ - "", /* DixDestroyAccess */ - "", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "grab", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "", /* DixUseAccess */ - "manage", /* DixManageAccess */ - "debug", /* DixDebugAccess */ - NULL }}, - { "x_extension", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "", /* DixDestroyAccess */ - "", /* DixCreateAccess */ - "query", /* DixGetAttrAccess */ - "", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "use", /* DixUseAccess */ - NULL }}, - { "x_event", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "", /* DixDestroyAccess */ - "", /* DixCreateAccess */ - "", /* DixGetAttrAccess */ - "", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "send", /* DixSendAccess */ - "receive", /* DixReceiveAccess */ - NULL }}, - { "x_synthetic_event", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "", /* DixDestroyAccess */ - "", /* DixCreateAccess */ - "", /* DixGetAttrAccess */ - "", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "send", /* DixSendAccess */ - "receive", /* DixReceiveAccess */ - NULL }}, - { "x_resource", - { "read", /* DixReadAccess */ - "write", /* DixWriteAccess */ - "write", /* DixDestroyAccess */ - "write", /* DixCreateAccess */ - "read", /* DixGetAttrAccess */ - "write", /* DixSetAttrAccess */ - "read", /* DixListPropAccess */ - "read", /* DixGetPropAccess */ - "write", /* DixSetPropAccess */ - "read", /* DixGetFocusAccess */ - "write", /* DixSetFocusAccess */ - "read", /* DixListAccess */ - "write", /* DixAddAccess */ - "write", /* DixRemoveAccess */ - "write", /* DixHideAccess */ - "read", /* DixShowAccess */ - "read", /* DixBlendAccess */ - "write", /* DixGrabAccess */ - "write", /* DixFreezeAccess */ - "write", /* DixForceAccess */ - "write", /* DixInstallAccess */ - "write", /* DixUninstallAccess */ - "write", /* DixSendAccess */ - "read", /* DixReceiveAccess */ - "read", /* DixUseAccess */ - "write", /* DixManageAccess */ - "read", /* DixDebugAccess */ - "write", /* DixBellAccess */ - NULL }}, - { NULL } -}; - -/* x_resource "read" bits from the list above */ -#define SELinuxReadMask (DixReadAccess|DixGetAttrAccess|DixListPropAccess| \ - DixGetPropAccess|DixGetFocusAccess|DixListAccess| \ - DixShowAccess|DixBlendAccess|DixReceiveAccess| \ - DixUseAccess|DixDebugAccess) - -#endif /* _XSELINUX_NEED_FLASK */ #endif /* _XSELINUX_H */ diff --git a/xorg-server/Xext/xselinux_ext.c b/xorg-server/Xext/xselinux_ext.c new file mode 100644 index 000000000..b36fb13eb --- /dev/null +++ b/xorg-server/Xext/xselinux_ext.c @@ -0,0 +1,729 @@ +/************************************************************ + +Author: Eamon Walsh + +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. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "selection.h" +#include "inputstr.h" +#include "windowstr.h" +#include "propertyst.h" +#include "extnsionst.h" +#include "modinit.h" +#include "xselinuxint.h" + +#define CTX_DEV offsetof(SELinuxSubjectRec, dev_create_sid) +#define CTX_WIN offsetof(SELinuxSubjectRec, win_create_sid) +#define CTX_PRP offsetof(SELinuxSubjectRec, prp_create_sid) +#define CTX_SEL offsetof(SELinuxSubjectRec, sel_create_sid) +#define USE_PRP offsetof(SELinuxSubjectRec, prp_use_sid) +#define USE_SEL offsetof(SELinuxSubjectRec, sel_use_sid) + +typedef struct { + security_context_t octx; + security_context_t dctx; + CARD32 octx_len; + CARD32 dctx_len; + CARD32 id; +} SELinuxListItemRec; + + +/* + * Extension Dispatch + */ + +static security_context_t +SELinuxCopyContext(char *ptr, unsigned len) +{ + security_context_t copy = xalloc(len + 1); + if (!copy) + return NULL; + strncpy(copy, ptr, len); + copy[len] = '\0'; + return copy; +} + +static int +ProcSELinuxQueryVersion(ClientPtr client) +{ + SELinuxQueryVersionReply rep; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.server_major = SELINUX_MAJOR_VERSION; + rep.server_minor = SELINUX_MINOR_VERSION; + 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 +SELinuxSendContextReply(ClientPtr client, security_id_t sid) +{ + SELinuxGetContextReply rep; + security_context_t ctx = NULL; + int len = 0; + + if (sid) { + if (avc_sid_to_context_raw(sid, &ctx) < 0) + return BadValue; + len = strlen(ctx) + 1; + } + + rep.type = X_Reply; + rep.length = bytes_to_int32(len); + rep.sequenceNumber = client->sequence; + rep.context_len = len; + + if (client->swapped) { + int n; + swapl(&rep.length, n); + swaps(&rep.sequenceNumber, n); + swapl(&rep.context_len, n); + } + + WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep); + WriteToClient(client, len, ctx); + freecon(ctx); + return client->noClientException; +} + +static int +ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset) +{ + PrivateRec **privPtr = &client->devPrivates; + security_id_t *pSid; + security_context_t ctx = NULL; + char *ptr; + int rc; + + REQUEST(SELinuxSetCreateContextReq); + REQUEST_FIXED_SIZE(SELinuxSetCreateContextReq, stuff->context_len); + + if (stuff->context_len > 0) { + ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len); + if (!ctx) + return BadAlloc; + } + + ptr = dixLookupPrivate(privPtr, subjectKey); + pSid = (security_id_t *)(ptr + offset); + sidput(*pSid); + *pSid = NULL; + + rc = Success; + if (stuff->context_len > 0) { + if (security_check_context_raw(ctx) < 0 || + avc_context_to_sid_raw(ctx, pSid) < 0) + rc = BadValue; + } + + xfree(ctx); + return rc; +} + +static int +ProcSELinuxGetCreateContext(ClientPtr client, unsigned offset) +{ + security_id_t *pSid; + char *ptr; + + REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq); + + if (offset == CTX_DEV) + ptr = dixLookupPrivate(&serverClient->devPrivates, subjectKey); + else + ptr = dixLookupPrivate(&client->devPrivates, subjectKey); + + pSid = (security_id_t *)(ptr + offset); + return SELinuxSendContextReply(client, *pSid); +} + +static int +ProcSELinuxSetDeviceContext(ClientPtr client) +{ + security_context_t ctx; + security_id_t sid; + DeviceIntPtr dev; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + int rc; + + REQUEST(SELinuxSetContextReq); + REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len); + + if (stuff->context_len < 1) + return BadLength; + ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len); + if (!ctx) + return BadAlloc; + + rc = dixLookupDevice(&dev, stuff->id, client, DixManageAccess); + if (rc != Success) + goto out; + + if (security_check_context_raw(ctx) < 0 || + avc_context_to_sid_raw(ctx, &sid) < 0) { + rc = BadValue; + goto out; + } + + subj = dixLookupPrivate(&dev->devPrivates, subjectKey); + sidput(subj->sid); + subj->sid = sid; + obj = dixLookupPrivate(&dev->devPrivates, objectKey); + sidput(obj->sid); + sidget(obj->sid = sid); + + rc = Success; +out: + xfree(ctx); + return rc; +} + +static int +ProcSELinuxGetDeviceContext(ClientPtr client) +{ + DeviceIntPtr dev; + SELinuxSubjectRec *subj; + int rc; + + REQUEST(SELinuxGetContextReq); + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + + rc = dixLookupDevice(&dev, stuff->id, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + subj = dixLookupPrivate(&dev->devPrivates, subjectKey); + return SELinuxSendContextReply(client, subj->sid); +} + +static int +ProcSELinuxGetWindowContext(ClientPtr client) +{ + WindowPtr pWin; + SELinuxObjectRec *obj; + int rc; + + REQUEST(SELinuxGetContextReq); + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + + rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + obj = dixLookupPrivate(&pWin->devPrivates, objectKey); + return SELinuxSendContextReply(client, obj->sid); +} + +static int +ProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey) +{ + WindowPtr pWin; + PropertyPtr pProp; + SELinuxObjectRec *obj; + int rc; + + REQUEST(SELinuxGetPropertyContextReq); + REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq); + + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetPropAccess); + if (rc != Success) + return rc; + + rc = dixLookupProperty(&pProp, pWin, stuff->property, client, + DixGetAttrAccess); + if (rc != Success) + return rc; + + obj = dixLookupPrivate(&pProp->devPrivates, privKey); + return SELinuxSendContextReply(client, obj->sid); +} + +static int +ProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey) +{ + Selection *pSel; + SELinuxObjectRec *obj; + int rc; + + REQUEST(SELinuxGetContextReq); + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + + rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + obj = dixLookupPrivate(&pSel->devPrivates, privKey); + return SELinuxSendContextReply(client, obj->sid); +} + +static int +ProcSELinuxGetClientContext(ClientPtr client) +{ + ClientPtr target; + SELinuxSubjectRec *subj; + int rc; + + REQUEST(SELinuxGetContextReq); + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + + rc = dixLookupClient(&target, stuff->id, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + subj = dixLookupPrivate(&target->devPrivates, subjectKey); + return SELinuxSendContextReply(client, subj->sid); +} + +static int +SELinuxPopulateItem(SELinuxListItemRec *i, PrivateRec **privPtr, CARD32 id, + int *size) +{ + SELinuxObjectRec *obj = dixLookupPrivate(privPtr, objectKey); + SELinuxObjectRec *data = dixLookupPrivate(privPtr, dataKey); + + if (avc_sid_to_context_raw(obj->sid, &i->octx) < 0) + return BadValue; + if (avc_sid_to_context_raw(data->sid, &i->dctx) < 0) + return BadValue; + + i->id = id; + i->octx_len = bytes_to_int32(strlen(i->octx) + 1); + i->dctx_len = bytes_to_int32(strlen(i->dctx) + 1); + + *size += i->octx_len + i->dctx_len + 3; + return Success; +} + +static void +SELinuxFreeItems(SELinuxListItemRec *items, int count) +{ + int k; + for (k = 0; k < count; k++) { + freecon(items[k].octx); + freecon(items[k].dctx); + } + xfree(items); +} + +static int +SELinuxSendItemsToClient(ClientPtr client, SELinuxListItemRec *items, + int size, int count) +{ + int rc, k, n, pos = 0; + SELinuxListItemsReply rep; + CARD32 *buf; + + buf = xcalloc(size, sizeof(CARD32)); + if (size && !buf) { + rc = BadAlloc; + goto out; + } + + /* Fill in the buffer */ + for (k = 0; k < count; k++) { + buf[pos] = items[k].id; + if (client->swapped) + swapl(buf + pos, n); + pos++; + + buf[pos] = items[k].octx_len * 4; + if (client->swapped) + swapl(buf + pos, n); + pos++; + + buf[pos] = items[k].dctx_len * 4; + if (client->swapped) + swapl(buf + pos, n); + pos++; + + memcpy((char *)(buf + pos), items[k].octx, strlen(items[k].octx) + 1); + pos += items[k].octx_len; + memcpy((char *)(buf + pos), items[k].dctx, strlen(items[k].dctx) + 1); + pos += items[k].dctx_len; + } + + /* Send reply to client */ + rep.type = X_Reply; + rep.length = size; + rep.sequenceNumber = client->sequence; + rep.count = count; + + if (client->swapped) { + swapl(&rep.length, n); + swaps(&rep.sequenceNumber, n); + swapl(&rep.count, n); + } + + WriteToClient(client, sizeof(SELinuxListItemsReply), (char *)&rep); + WriteToClient(client, size * 4, (char *)buf); + + /* Free stuff and return */ + rc = client->noClientException; + xfree(buf); +out: + SELinuxFreeItems(items, count); + return rc; +} + +static int +ProcSELinuxListProperties(ClientPtr client) +{ + WindowPtr pWin; + PropertyPtr pProp; + SELinuxListItemRec *items; + int rc, count, size, i; + CARD32 id; + + REQUEST(SELinuxGetContextReq); + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + + rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess); + if (rc != Success) + return rc; + + /* Count the number of properties and allocate items */ + count = 0; + for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) + count++; + items = xcalloc(count, sizeof(SELinuxListItemRec)); + if (count && !items) + return BadAlloc; + + /* Fill in the items and calculate size */ + i = 0; + size = 0; + for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) { + id = pProp->propertyName; + rc = SELinuxPopulateItem(items + i, &pProp->devPrivates, id, &size); + if (rc != Success) { + SELinuxFreeItems(items, count); + return rc; + } + i++; + } + + return SELinuxSendItemsToClient(client, items, size, count); +} + +static int +ProcSELinuxListSelections(ClientPtr client) +{ + Selection *pSel; + SELinuxListItemRec *items; + int rc, count, size, i; + CARD32 id; + + REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq); + + /* Count the number of selections and allocate items */ + count = 0; + for (pSel = CurrentSelections; pSel; pSel = pSel->next) + count++; + items = xcalloc(count, sizeof(SELinuxListItemRec)); + if (count && !items) + return BadAlloc; + + /* Fill in the items and calculate size */ + i = 0; + size = 0; + for (pSel = CurrentSelections; pSel; pSel = pSel->next) { + id = pSel->selection; + rc = SELinuxPopulateItem(items + i, &pSel->devPrivates, id, &size); + if (rc != Success) { + SELinuxFreeItems(items, count); + return rc; + } + i++; + } + + return SELinuxSendItemsToClient(client, items, size, count); +} + +static int +ProcSELinuxDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_SELinuxQueryVersion: + return ProcSELinuxQueryVersion(client); + case X_SELinuxSetDeviceCreateContext: + return ProcSELinuxSetCreateContext(client, CTX_DEV); + case X_SELinuxGetDeviceCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_DEV); + case X_SELinuxSetDeviceContext: + return ProcSELinuxSetDeviceContext(client); + case X_SELinuxGetDeviceContext: + return ProcSELinuxGetDeviceContext(client); + case X_SELinuxSetWindowCreateContext: + return ProcSELinuxSetCreateContext(client, CTX_WIN); + case X_SELinuxGetWindowCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_WIN); + case X_SELinuxGetWindowContext: + return ProcSELinuxGetWindowContext(client); + case X_SELinuxSetPropertyCreateContext: + return ProcSELinuxSetCreateContext(client, CTX_PRP); + case X_SELinuxGetPropertyCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_PRP); + case X_SELinuxSetPropertyUseContext: + return ProcSELinuxSetCreateContext(client, USE_PRP); + case X_SELinuxGetPropertyUseContext: + return ProcSELinuxGetCreateContext(client, USE_PRP); + case X_SELinuxGetPropertyContext: + return ProcSELinuxGetPropertyContext(client, objectKey); + case X_SELinuxGetPropertyDataContext: + return ProcSELinuxGetPropertyContext(client, dataKey); + case X_SELinuxListProperties: + return ProcSELinuxListProperties(client); + case X_SELinuxSetSelectionCreateContext: + return ProcSELinuxSetCreateContext(client, CTX_SEL); + case X_SELinuxGetSelectionCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_SEL); + case X_SELinuxSetSelectionUseContext: + return ProcSELinuxSetCreateContext(client, USE_SEL); + case X_SELinuxGetSelectionUseContext: + return ProcSELinuxGetCreateContext(client, USE_SEL); + case X_SELinuxGetSelectionContext: + return ProcSELinuxGetSelectionContext(client, objectKey); + case X_SELinuxGetSelectionDataContext: + return ProcSELinuxGetSelectionContext(client, dataKey); + case X_SELinuxListSelections: + return ProcSELinuxListSelections(client); + case X_SELinuxGetClientContext: + return ProcSELinuxGetClientContext(client); + default: + return BadRequest; + } +} + +static int +SProcSELinuxQueryVersion(ClientPtr client) +{ + REQUEST(SELinuxQueryVersionReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxQueryVersionReq); + swaps(&stuff->client_major, n); + swaps(&stuff->client_minor, n); + return ProcSELinuxQueryVersion(client); +} + +static int +SProcSELinuxSetCreateContext(ClientPtr client, unsigned offset) +{ + REQUEST(SELinuxSetCreateContextReq); + int n; + + REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq); + swapl(&stuff->context_len, n); + return ProcSELinuxSetCreateContext(client, offset); +} + +static int +SProcSELinuxSetDeviceContext(ClientPtr client) +{ + REQUEST(SELinuxSetContextReq); + int n; + + REQUEST_AT_LEAST_SIZE(SELinuxSetContextReq); + swapl(&stuff->id, n); + swapl(&stuff->context_len, n); + return ProcSELinuxSetDeviceContext(client); +} + +static int +SProcSELinuxGetDeviceContext(ClientPtr client) +{ + REQUEST(SELinuxGetContextReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + swapl(&stuff->id, n); + return ProcSELinuxGetDeviceContext(client); +} + +static int +SProcSELinuxGetWindowContext(ClientPtr client) +{ + REQUEST(SELinuxGetContextReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + swapl(&stuff->id, n); + return ProcSELinuxGetWindowContext(client); +} + +static int +SProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey) +{ + REQUEST(SELinuxGetPropertyContextReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + return ProcSELinuxGetPropertyContext(client, privKey); +} + +static int +SProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey) +{ + REQUEST(SELinuxGetContextReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + swapl(&stuff->id, n); + return ProcSELinuxGetSelectionContext(client, privKey); +} + +static int +SProcSELinuxListProperties(ClientPtr client) +{ + REQUEST(SELinuxGetContextReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + swapl(&stuff->id, n); + return ProcSELinuxListProperties(client); +} + +static int +SProcSELinuxGetClientContext(ClientPtr client) +{ + REQUEST(SELinuxGetContextReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + swapl(&stuff->id, n); + return ProcSELinuxGetClientContext(client); +} + +static int +SProcSELinuxDispatch(ClientPtr client) +{ + REQUEST(xReq); + int n; + + swaps(&stuff->length, n); + + switch (stuff->data) { + case X_SELinuxQueryVersion: + return SProcSELinuxQueryVersion(client); + case X_SELinuxSetDeviceCreateContext: + return SProcSELinuxSetCreateContext(client, CTX_DEV); + case X_SELinuxGetDeviceCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_DEV); + case X_SELinuxSetDeviceContext: + return SProcSELinuxSetDeviceContext(client); + case X_SELinuxGetDeviceContext: + return SProcSELinuxGetDeviceContext(client); + case X_SELinuxSetWindowCreateContext: + return SProcSELinuxSetCreateContext(client, CTX_WIN); + case X_SELinuxGetWindowCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_WIN); + case X_SELinuxGetWindowContext: + return SProcSELinuxGetWindowContext(client); + case X_SELinuxSetPropertyCreateContext: + return SProcSELinuxSetCreateContext(client, CTX_PRP); + case X_SELinuxGetPropertyCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_PRP); + case X_SELinuxSetPropertyUseContext: + return SProcSELinuxSetCreateContext(client, USE_PRP); + case X_SELinuxGetPropertyUseContext: + return ProcSELinuxGetCreateContext(client, USE_PRP); + case X_SELinuxGetPropertyContext: + return SProcSELinuxGetPropertyContext(client, objectKey); + case X_SELinuxGetPropertyDataContext: + return SProcSELinuxGetPropertyContext(client, dataKey); + case X_SELinuxListProperties: + return SProcSELinuxListProperties(client); + case X_SELinuxSetSelectionCreateContext: + return SProcSELinuxSetCreateContext(client, CTX_SEL); + case X_SELinuxGetSelectionCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_SEL); + case X_SELinuxSetSelectionUseContext: + return SProcSELinuxSetCreateContext(client, USE_SEL); + case X_SELinuxGetSelectionUseContext: + return ProcSELinuxGetCreateContext(client, USE_SEL); + case X_SELinuxGetSelectionContext: + return SProcSELinuxGetSelectionContext(client, objectKey); + case X_SELinuxGetSelectionDataContext: + return SProcSELinuxGetSelectionContext(client, dataKey); + case X_SELinuxListSelections: + return ProcSELinuxListSelections(client); + case X_SELinuxGetClientContext: + return SProcSELinuxGetClientContext(client); + default: + return BadRequest; + } +} + + +/* + * Extension Setup / Teardown + */ + +static void +SELinuxResetProc(ExtensionEntry *extEntry) +{ + SELinuxFlaskReset(); + SELinuxLabelReset(); +} + +void +SELinuxExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + + /* Check SELinux mode on system, configuration file, and boolean */ + if (!is_selinux_enabled()) { + LogMessage(X_INFO, "SELinux: Disabled on system\n"); + return; + } + if (selinuxEnforcingState == SELINUX_MODE_DISABLED) { + LogMessage(X_INFO, "SELinux: Disabled in configuration file\n"); + return; + } + if (!security_get_boolean_active("xserver_object_manager")) { + LogMessage(X_INFO, "SELinux: Disabled by boolean\n"); + return; + } + + /* Set up XACE hooks */ + SELinuxLabelInit(); + SELinuxFlaskInit(); + + /* Add extension to server */ + extEntry = AddExtension(SELINUX_EXTENSION_NAME, + SELinuxNumberEvents, SELinuxNumberErrors, + ProcSELinuxDispatch, SProcSELinuxDispatch, + SELinuxResetProc, StandardMinorOpcode); + + AddExtensionAlias("Flask", extEntry); +} diff --git a/xorg-server/Xext/xselinux_hooks.c b/xorg-server/Xext/xselinux_hooks.c new file mode 100644 index 000000000..43683ff24 --- /dev/null +++ b/xorg-server/Xext/xselinux_hooks.c @@ -0,0 +1,1030 @@ +/************************************************************ + +Author: Eamon Walsh + +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. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include +#include "selection.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "propertyst.h" +#include "extnsionst.h" +#include "xacestr.h" +#include "../os/osdep.h" +#define _XSELINUX_NEED_FLASK_MAP +#include "xselinuxint.h" + + +/* structure passed to auditing callback */ +typedef struct { + ClientPtr client; /* client */ + DeviceIntPtr dev; /* device */ + char *command; /* client's executable path */ + unsigned id; /* resource id, if any */ + int restype; /* resource type, if any */ + int event; /* event type, if any */ + Atom property; /* property name, if any */ + Atom selection; /* selection name, if any */ + char *extension; /* extension name, if any */ +} SELinuxAuditRec; + +/* private state keys */ +static int subjectKeyIndex; +DevPrivateKey subjectKey = &subjectKeyIndex; +static int objectKeyIndex; +DevPrivateKey objectKey = &objectKeyIndex; +static int dataKeyIndex; +DevPrivateKey dataKey = &dataKeyIndex; + +/* audit file descriptor */ +static int audit_fd; + +/* whether AVC is active */ +static int avc_active; + +/* atoms for window label properties */ +static Atom atom_ctx; +static Atom atom_client_ctx; + +/* The unlabeled SID */ +static security_id_t unlabeled_sid; + +/* forward declarations */ +static void SELinuxScreen(CallbackListPtr *, pointer, pointer); + +/* "true" pointer value for use as callback data */ +static pointer truep = (pointer)1; + + +/* + * Performs an SELinux permission check. + */ +static int +SELinuxDoCheck(SELinuxSubjectRec *subj, SELinuxObjectRec *obj, + security_class_t class, Mask mode, SELinuxAuditRec *auditdata) +{ + /* serverClient requests OK */ + if (subj->privileged) + return Success; + + auditdata->command = subj->command; + errno = 0; + + if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref, + auditdata) < 0) { + if (mode == DixUnknownAccess) + return Success; /* DixUnknownAccess requests OK ... for now */ + if (errno == EACCES) + return BadAccess; + ErrorF("SELinux: avc_has_perm: unexpected error %d\n", errno); + return BadValue; + } + + return Success; +} + +/* + * Labels a newly connected client. + */ +static void +SELinuxLabelClient(ClientPtr client) +{ + int fd = XaceGetConnectionNumber(client); + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + security_context_t ctx; + + subj = dixLookupPrivate(&client->devPrivates, subjectKey); + sidput(subj->sid); + obj = dixLookupPrivate(&client->devPrivates, objectKey); + sidput(obj->sid); + + /* Try to get a context from the socket */ + if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) { + /* Otherwise, fall back to a default context */ + ctx = SELinuxDefaultClientLabel(); + } + + /* For local clients, try and determine the executable name */ + if (XaceIsLocal(client)) { + struct ucred creds; + socklen_t len = sizeof(creds); + char path[PATH_MAX + 1]; + size_t bytes; + + 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; + + subj->command = xalloc(bytes); + if (!subj->command) + goto finish; + + memcpy(subj->command, path, bytes); + subj->command[bytes - 1] = 0; + } + +finish: + /* Get a SID from the context */ + if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) + FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n", + client->index, ctx); + + sidget(obj->sid = subj->sid); + freecon(ctx); +} + +/* + * Labels initial server objects. + */ +static void +SELinuxLabelInitial(void) +{ + int i; + XaceScreenAccessRec srec; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + security_context_t ctx; + pointer unused; + + /* Do the serverClient */ + subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey); + obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); + subj->privileged = 1; + sidput(subj->sid); + + /* Use the context of the X server process for the serverClient */ + if (getcon_raw(&ctx) < 0) + FatalError("SELinux: couldn't get context of X server process\n"); + + /* Get a SID from the context */ + if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) + FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx); + + sidget(obj->sid = subj->sid); + 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 */ + dixLookupResourceByType(&unused, screenInfo.screens[i]->defColormap, + RT_COLORMAP, serverClient, DixCreateAccess); + } +} + +/* + * Labels new resource objects. + */ +static int +SELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj, + SELinuxObjectRec *obj, security_class_t class) +{ + int offset; + security_id_t tsid; + + /* Check for a create context */ + if (rec->rtype == RT_WINDOW && subj->win_create_sid) { + sidget(obj->sid = subj->win_create_sid); + return Success; + } + + if (rec->parent) + offset = dixLookupPrivateOffset(rec->ptype); + + if (rec->parent && offset >= 0) { + /* Use the SID of the parent object in the labeling operation */ + PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset); + SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey); + tsid = pobj->sid; + } else { + /* Use the SID of the subject */ + tsid = subj->sid; + } + + /* Perform a transition to obtain the final SID */ + if (avc_compute_create(subj->sid, tsid, class, &obj->sid) < 0) { + ErrorF("SELinux: a compute_create call failed!\n"); + return BadValue; + } + + return Success; +} + + +/* + * Libselinux Callbacks + */ + +static int +SELinuxAudit(void *auditdata, + security_class_t class, + char *msgbuf, + size_t msgbufsize) +{ + SELinuxAuditRec *audit = auditdata; + ClientPtr client = audit->client; + char idNum[16]; + const char *propertyName, *selectionName; + int major = -1, minor = -1; + + if (client) { + REQUEST(xReq); + if (stuff) { + major = stuff->reqType; + minor = MinorOpcodeOfRequest(client); + } + } + if (audit->id) + snprintf(idNum, 16, "%x", audit->id); + + propertyName = audit->property ? NameForAtom(audit->property) : NULL; + selectionName = audit->selection ? NameForAtom(audit->selection) : NULL; + + return snprintf(msgbuf, msgbufsize, + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + (major >= 0) ? "request=" : "", + (major >= 0) ? LookupRequestName(major, minor) : "", + audit->command ? " comm=" : "", + audit->command ? audit->command : "", + audit->dev ? " xdevice=\"" : "", + audit->dev ? audit->dev->name : "", + audit->dev ? "\"" : "", + audit->id ? " resid=" : "", + audit->id ? idNum : "", + audit->restype ? " restype=" : "", + audit->restype ? LookupResourceName(audit->restype) : "", + audit->event ? " event=" : "", + audit->event ? LookupEventName(audit->event & 127) : "", + audit->property ? " property=" : "", + audit->property ? propertyName : "", + audit->selection ? " selection=" : "", + audit->selection ? selectionName : "", + audit->extension ? " extension=" : "", + audit->extension ? audit->extension : ""); +} + +static int +SELinuxLog(int type, const char *fmt, ...) +{ + va_list ap; + char buf[MAX_AUDIT_MESSAGE_LENGTH]; + int rc, aut; + + switch (type) { + case SELINUX_INFO: + aut = AUDIT_USER_MAC_POLICY_LOAD; + break; + case SELINUX_AVC: + aut = AUDIT_USER_AVC; + break; + default: + aut = AUDIT_USER_SELINUX_ERR; + break; + } + + va_start(ap, fmt); + vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap); + rc = audit_log_user_avc_message(audit_fd, aut, buf, NULL, NULL, NULL, 0); + va_end(ap); + LogMessageVerb(X_WARNING, 0, "%s", buf); + return 0; +} + +/* + * XACE Callbacks + */ + +static void +SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceDeviceAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; + security_class_t cls; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + if (rec->access_mode & DixCreateAccess) { + SELinuxSubjectRec *dsubj; + dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); + + sidput(dsubj->sid); + sidput(obj->sid); + + if (subj->dev_create_sid) { + /* Label the device with the create context */ + sidget(obj->sid = subj->dev_create_sid); + sidget(dsubj->sid = subj->dev_create_sid); + } else { + /* Label the device directly with the process SID */ + sidget(obj->sid = subj->sid); + sidget(dsubj->sid = subj->sid); + } + } + + cls = IsPointerDevice(rec->dev) ? SECCLASS_X_POINTER : SECCLASS_X_KEYBOARD; + rc = SELinuxDoCheck(subj, obj, cls, rec->access_mode, &auditdata); + if (rc != Success) + rec->status = rc; +} + +static void +SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceSendAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj, ev_sid; + SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; + security_class_t class; + int rc, i, type; + + if (rec->dev) + subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); + else + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + + obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); + + /* Check send permission on window */ + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess, + &auditdata); + if (rc != Success) + goto err; + + /* Check send permission on specific event types */ + for (i = 0; i < rec->count; i++) { + type = rec->events[i].u.u.type; + class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; + + rc = SELinuxEventToSID(type, obj->sid, &ev_sid); + if (rc != Success) + goto err; + + auditdata.event = type; + rc = SELinuxDoCheck(subj, &ev_sid, class, DixSendAccess, &auditdata); + if (rc != Success) + goto err; + } + return; +err: + rec->status = rc; +} + +static void +SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceReceiveAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj, ev_sid; + SELinuxAuditRec auditdata = { .client = NULL }; + security_class_t class; + int rc, i, type; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); + + /* Check receive permission on window */ + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess, + &auditdata); + if (rc != Success) + goto err; + + /* Check receive permission on specific event types */ + for (i = 0; i < rec->count; i++) { + type = rec->events[i].u.u.type; + class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; + + rc = SELinuxEventToSID(type, obj->sid, &ev_sid); + if (rc != Success) + goto err; + + auditdata.event = type; + rc = SELinuxDoCheck(subj, &ev_sid, class, DixReceiveAccess, &auditdata); + if (rc != Success) + goto err; + } + return; +err: + rec->status = rc; +} + +static void +SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceExtAccessRec *rec = calldata; + SELinuxSubjectRec *subj, *serv; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey); + + /* 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) { + security_id_t sid; + + serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey); + rc = SELinuxExtensionToSID(rec->ext->name, &sid); + if (rc != Success) { + rec->status = rc; + return; + } + + sidput(obj->sid); + + /* Perform a transition to obtain the final SID */ + if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION, + &obj->sid) < 0) { + ErrorF("SELinux: a SID transition call failed!\n"); + rec->status = BadValue; + return; + } + } + + /* Perform the security check */ + auditdata.extension = rec->ext->name; + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_EXTENSION, rec->access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; +} + +static void +SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceSelectionAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj, *data; + Selection *pSel = *rec->ppSel; + Atom name = pSel->selection; + Mask access_mode = rec->access_mode; + SELinuxAuditRec auditdata = { .client = rec->client, .selection = name }; + security_id_t tsid; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&pSel->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + if (access_mode & DixCreateAccess) { + sidput(obj->sid); + rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly); + if (rc != Success) + obj->sid = unlabeled_sid; + access_mode = DixSetAttrAccess; + } + /* If this is a polyinstantiated object, find the right instance */ + else if (obj->poly) { + rc = SELinuxSelectionToSID(name, subj, &tsid, NULL); + if (rc != Success) { + rec->status = rc; + return; + } + while (pSel->selection != name || obj->sid != tsid) { + if ((pSel = pSel->next) == NULL) + break; + obj = dixLookupPrivate(&pSel->devPrivates, objectKey); + } + sidput(tsid); + + if (pSel) + *rec->ppSel = pSel; + else { + rec->status = BadMatch; + return; + } + } + + /* Perform the security check */ + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; + + /* Label the content (advisory only) */ + if (access_mode & DixSetAttrAccess) { + data = dixLookupPrivate(&pSel->devPrivates, dataKey); + sidput(data->sid); + if (subj->sel_create_sid) + sidget(data->sid = subj->sel_create_sid); + else + sidget(data->sid = obj->sid); + } +} + +static void +SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XacePropertyAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj, *data; + PropertyPtr pProp = *rec->ppProp; + Atom name = pProp->propertyName; + SELinuxAuditRec auditdata = { .client = rec->client, .property = name }; + security_id_t tsid; + int rc; + + /* Don't care about the new content check */ + if (rec->access_mode & DixPostAccess) + return; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&pProp->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + if (rec->access_mode & DixCreateAccess) { + sidput(obj->sid); + rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly); + if (rc != Success) { + rec->status = rc; + return; + } + } + /* If this is a polyinstantiated object, find the right instance */ + else if (obj->poly) { + rc = SELinuxPropertyToSID(name, subj, &tsid, NULL); + if (rc != Success) { + rec->status = rc; + return; + } + while (pProp->propertyName != name || obj->sid != tsid) { + if ((pProp = pProp->next) == NULL) + break; + obj = dixLookupPrivate(&pProp->devPrivates, objectKey); + } + sidput(tsid); + + if (pProp) + *rec->ppProp = pProp; + else { + rec->status = BadMatch; + return; + } + } + + /* Perform the security check */ + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; + + /* Label the content (advisory only) */ + if (rec->access_mode & DixWriteAccess) { + data = dixLookupPrivate(&pProp->devPrivates, dataKey); + sidput(data->sid); + if (subj->prp_create_sid) + sidget(data->sid = subj->prp_create_sid); + else + sidget(data->sid = obj->sid); + } +} + +static void +SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceResourceAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + Mask access_mode = rec->access_mode; + PrivateRec **privatePtr; + security_class_t class; + int rc, offset; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + + /* 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; + obj = dixLookupPrivate(privatePtr, objectKey); + } else { + /* Yes: use the SID from the resource object itself */ + class = SELinuxTypeToClass(rec->rtype); + privatePtr = DEVPRIV_AT(rec->res, offset); + obj = dixLookupPrivate(privatePtr, objectKey); + } + + /* If this is a new object that needs labeling, do it now */ + if (access_mode & DixCreateAccess && offset >= 0) { + rc = SELinuxLabelResource(rec, subj, obj, class); + if (rc != Success) { + rec->status = rc; + return; + } + } + + /* Collapse generic resource permissions down to read/write */ + if (class == SECCLASS_X_RESOURCE) { + access_mode = !!(rec->access_mode & SELinuxReadMask); /* rd */ + access_mode |= !!(rec->access_mode & ~SELinuxReadMask) << 1; /* wr */ + } + + /* Perform the security check */ + auditdata.restype = rec->rtype; + auditdata.id = rec->id; + rc = SELinuxDoCheck(subj, obj, class, access_mode, &auditdata); + if (rc != Success) + rec->status = rc; + + /* Perform the background none check on windows */ + if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW) { + rc = SELinuxDoCheck(subj, obj, class, DixBlendAccess, &auditdata); + if (rc != Success) + ((WindowPtr)rec->res)->forcedBG = TRUE; + } +} + +static void +SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata) +{ + XaceScreenAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + Mask access_mode = rec->access_mode; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + if (access_mode & DixCreateAccess) { + sidput(obj->sid); + + /* Perform a transition to obtain the final SID */ + if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN, + &obj->sid) < 0) { + ErrorF("SELinux: a compute_create call failed!\n"); + rec->status = BadValue; + return; + } + } + + if (is_saver) + access_mode <<= 2; + + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SCREEN, access_mode, &auditdata); + if (rc != Success) + rec->status = rc; +} + +static void +SELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceClientAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->target->devPrivates, objectKey); + + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; +} + +static void +SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceServerAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); + + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; +} + + +/* + * DIX Callbacks + */ + +static void +SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + NewClientInfoRec *pci = calldata; + + switch (pci->client->clientState) { + case ClientStateInitial: + SELinuxLabelClient(pci->client); + break; + + default: + break; + } +} + +static void +SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + ResourceStateInfoRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + WindowPtr pWin; + + if (rec->type != RT_WINDOW) + return; + if (rec->state != ResourceStateAdding) + return; + + pWin = (WindowPtr)rec->value; + subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey); + + if (subj->sid) { + security_context_t ctx; + int rc = avc_sid_to_context_raw(subj->sid, &ctx); + if (rc < 0) + FatalError("SELinux: Failed to get security context!\n"); + rc = dixChangeWindowProperty(serverClient, + pWin, atom_client_ctx, XA_STRING, 8, + PropModeReplace, strlen(ctx), ctx, FALSE); + if (rc != Success) + FatalError("SELinux: Failed to set label property on window!\n"); + freecon(ctx); + } else + FatalError("SELinux: Unexpected unlabeled client found\n"); + + obj = dixLookupPrivate(&pWin->devPrivates, objectKey); + + if (obj->sid) { + security_context_t ctx; + int rc = avc_sid_to_context_raw(obj->sid, &ctx); + if (rc < 0) + FatalError("SELinux: Failed to get security context!\n"); + rc = dixChangeWindowProperty(serverClient, + pWin, atom_ctx, XA_STRING, 8, + PropModeReplace, strlen(ctx), ctx, FALSE); + if (rc != Success) + FatalError("SELinux: Failed to set label property on window!\n"); + freecon(ctx); + } else + FatalError("SELinux: Unexpected unlabeled window found\n"); +} + + +/* + * DevPrivates Callbacks + */ + +static void +SELinuxSubjectInit(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + PrivateCallbackRec *rec = calldata; + SELinuxSubjectRec *subj = *rec->value; + + sidget(unlabeled_sid); + 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); + + if (avc_active) { + sidput(subj->sid); + sidput(subj->dev_create_sid); + sidput(subj->win_create_sid); + sidput(subj->sel_create_sid); + sidput(subj->prp_create_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); +} + +#ifdef HAVE_AVC_NETLINK_ACQUIRE_FD +static int netlink_fd; + +static void +SELinuxBlockHandler(void *data, struct timeval **tv, void *read_mask) +{ +} + +static void +SELinuxWakeupHandler(void *data, int err, void *read_mask) +{ + if (FD_ISSET(netlink_fd, (fd_set *)read_mask)) + avc_netlink_check_nb(); +} +#endif + +void +SELinuxFlaskReset(void) +{ + /* Unregister callbacks */ + DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL); + DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL); + + 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); + XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); + XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); + XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); + + /* Tear down SELinux stuff */ + audit_close(audit_fd); +#ifdef HAVE_AVC_NETLINK_ACQUIRE_FD + avc_netlink_release_fd(); + RemoveBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, + NULL); + RemoveGeneralSocket(netlink_fd); +#endif + + avc_destroy(); + avc_active = 0; +} + +void +SELinuxFlaskInit(void) +{ + struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 }; + security_context_t ctx; + int ret = TRUE; + + switch(selinuxEnforcingState) { + case SELINUX_MODE_ENFORCING: + LogMessage(X_INFO, "SELinux: Configured in enforcing mode\n"); + avc_option.value = (char *)1; + break; + case SELINUX_MODE_PERMISSIVE: + LogMessage(X_INFO, "SELinux: Configured in permissive mode\n"); + avc_option.value = (char *)0; + break; + default: + avc_option.type = AVC_OPT_UNUSED; + break; + } + + /* Set up SELinux stuff */ + selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)SELinuxLog); + selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)SELinuxAudit); + + if (selinux_set_mapping(map) < 0) { + if (errno == EINVAL) { + ErrorF("SELinux: Invalid object class mapping, disabling SELinux support.\n"); + return; + } + FatalError("SELinux: Failed to set up security class mapping\n"); + } + + if (avc_open(&avc_option, 1) < 0) + FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n"); + avc_active = 1; + + if (security_get_initial_context_raw("unlabeled", &ctx) < 0) + FatalError("SELinux: Failed to look up unlabeled context\n"); + if (avc_context_to_sid_raw(ctx, &unlabeled_sid) < 0) + FatalError("SELinux: a context_to_SID call failed!\n"); + freecon(ctx); + + /* Prepare for auditing */ + audit_fd = audit_open(); + if (audit_fd < 0) + FatalError("SELinux: Failed to open the system audit log\n"); + + /* Allocate private storage */ + if (!dixRequestPrivate(subjectKey, sizeof(SELinuxSubjectRec)) || + !dixRequestPrivate(objectKey, sizeof(SELinuxObjectRec)) || + !dixRequestPrivate(dataKey, sizeof(SELinuxObjectRec))) + FatalError("SELinux: Failed to allocate private storage.\n"); + + /* Create atoms for doing window labeling */ + atom_ctx = MakeAtom("_SELINUX_CONTEXT", 16, TRUE); + if (atom_ctx == BAD_RESOURCE) + FatalError("SELinux: Failed to create atom\n"); + atom_client_ctx = MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE); + if (atom_client_ctx == BAD_RESOURCE) + FatalError("SELinux: Failed to create atom\n"); + +#ifdef HAVE_AVC_NETLINK_ACQUIRE_FD + netlink_fd = avc_netlink_acquire_fd(); + AddGeneralSocket(netlink_fd); + RegisterBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, + NULL); +#endif + + /* Register callbacks */ + ret &= dixRegisterPrivateInitFunc(subjectKey, SELinuxSubjectInit, NULL); + ret &= dixRegisterPrivateDeleteFunc(subjectKey, SELinuxSubjectFree, NULL); + ret &= dixRegisterPrivateInitFunc(objectKey, SELinuxObjectInit, NULL); + ret &= dixRegisterPrivateDeleteFunc(objectKey, SELinuxObjectFree, NULL); + ret &= dixRegisterPrivateInitFunc(dataKey, SELinuxObjectInit, NULL); + ret &= dixRegisterPrivateDeleteFunc(dataKey, SELinuxObjectFree, NULL); + + ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL); + ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL); + + 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); + ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); + ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); + ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); + if (!ret) + FatalError("SELinux: Failed to register one or more callbacks\n"); + + /* Label objects that were created before we could register ourself */ + SELinuxLabelInitial(); +} diff --git a/xorg-server/Xext/xselinux_label.c b/xorg-server/Xext/xselinux_label.c new file mode 100644 index 000000000..239536cf3 --- /dev/null +++ b/xorg-server/Xext/xselinux_label.c @@ -0,0 +1,381 @@ +/************************************************************ + +Author: Eamon Walsh + +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. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "registry.h" +#include "xselinuxint.h" + +/* selection and property atom cache */ +typedef struct { + SELinuxObjectRec prp; + SELinuxObjectRec sel; +} SELinuxAtomRec; + +/* dynamic array */ +typedef struct { + unsigned size; + void **array; +} SELinuxArrayRec; + +/* labeling handle */ +static struct selabel_handle *label_hnd; + +/* Array of object classes indexed by resource type */ +SELinuxArrayRec arr_types; +/* Array of event SIDs indexed by event type */ +SELinuxArrayRec arr_events; +/* Array of property and selection SID structures */ +SELinuxArrayRec arr_atoms; + +/* + * Dynamic array helpers + */ +static void * +SELinuxArrayGet(SELinuxArrayRec *rec, unsigned key) +{ + return (rec->size > key) ? rec->array[key] : 0; +} + +static int +SELinuxArraySet(SELinuxArrayRec *rec, unsigned key, void *val) +{ + if (key >= rec->size) { + /* Need to increase size of array */ + rec->array = xrealloc(rec->array, (key + 1) * sizeof(val)); + if (!rec->array) + return FALSE; + memset(rec->array + rec->size, 0, (key - rec->size + 1) * sizeof(val)); + rec->size = key + 1; + } + + rec->array[key] = val; + return TRUE; +} + +static void +SELinuxArrayFree(SELinuxArrayRec *rec, int free_elements) +{ + if (free_elements) { + unsigned i = rec->size; + while (i) + xfree(rec->array[--i]); + } + + xfree(rec->array); + rec->size = 0; + rec->array = NULL; +} + +/* + * Looks up a name in the selection or property mappings + */ +static int +SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec *obj, int map, int polymap) +{ + const char *name = NameForAtom(atom); + security_context_t ctx; + int rc = Success; + + obj->poly = 1; + + /* Look in the mappings of names to contexts */ + if (selabel_lookup_raw(label_hnd, &ctx, name, map) == 0) { + obj->poly = 0; + } else if (errno != ENOENT) { + ErrorF("SELinux: a property label lookup failed!\n"); + return BadValue; + } else if (selabel_lookup_raw(label_hnd, &ctx, name, polymap) < 0) { + ErrorF("SELinux: a property label lookup failed!\n"); + return BadValue; + } + + /* Get a SID for context */ + if (avc_context_to_sid_raw(ctx, &obj->sid) < 0) { + ErrorF("SELinux: a context_to_SID_raw call failed!\n"); + rc = BadAlloc; + } + + freecon(ctx); + return rc; +} + +/* + * Looks up the SID corresponding to the given property or selection atom + */ +int +SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn) +{ + SELinuxAtomRec *rec; + SELinuxObjectRec *obj; + int rc, map, polymap; + + rec = SELinuxArrayGet(&arr_atoms, atom); + if (!rec) { + rec = xcalloc(1, sizeof(SELinuxAtomRec)); + if (!rec || !SELinuxArraySet(&arr_atoms, atom, rec)) + return BadAlloc; + } + + if (prop) { + obj = &rec->prp; + map = SELABEL_X_PROP; + polymap = SELABEL_X_POLYPROP; + } else { + obj = &rec->sel; + map = SELABEL_X_SELN; + polymap = SELABEL_X_POLYSELN; + } + + if (!obj->sid) { + rc = SELinuxAtomToSIDLookup(atom, obj, map, polymap); + if (rc != Success) + goto out; + } + + *obj_rtn = obj; + rc = Success; +out: + return rc; +} + +/* + * Looks up a SID for a selection/subject pair + */ +int +SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec *subj, + security_id_t *sid_rtn, int *poly_rtn) +{ + int rc; + SELinuxObjectRec *obj; + security_id_t tsid; + + /* Get the default context and polyinstantiation bit */ + rc = SELinuxAtomToSID(selection, 0, &obj); + if (rc != Success) + return rc; + + /* Check for an override context next */ + if (subj->sel_use_sid) { + sidget(tsid = subj->sel_use_sid); + goto out; + } + + sidget(tsid = obj->sid); + + /* Polyinstantiate if necessary to obtain the final SID */ + if (obj->poly) { + sidput(tsid); + if (avc_compute_member(subj->sid, obj->sid, + SECCLASS_X_SELECTION, &tsid) < 0) { + ErrorF("SELinux: a compute_member call failed!\n"); + return BadValue; + } + } +out: + *sid_rtn = tsid; + if (poly_rtn) + *poly_rtn = obj->poly; + return Success; +} + +/* + * Looks up a SID for a property/subject pair + */ +int +SELinuxPropertyToSID(Atom property, SELinuxSubjectRec *subj, + security_id_t *sid_rtn, int *poly_rtn) +{ + int rc; + SELinuxObjectRec *obj; + security_id_t tsid, tsid2; + + /* Get the default context and polyinstantiation bit */ + rc = SELinuxAtomToSID(property, 1, &obj); + if (rc != Success) + return rc; + + /* Check for an override context next */ + if (subj->prp_use_sid) { + sidget(tsid = subj->prp_use_sid); + goto out; + } + + /* Perform a transition */ + if (avc_compute_create(subj->sid, obj->sid, + SECCLASS_X_PROPERTY, &tsid) < 0) { + ErrorF("SELinux: a compute_create call failed!\n"); + return BadValue; + } + + /* Polyinstantiate if necessary to obtain the final SID */ + if (obj->poly) { + tsid2 = tsid; + if (avc_compute_member(subj->sid, tsid2, + SECCLASS_X_PROPERTY, &tsid) < 0) { + ErrorF("SELinux: a compute_member call failed!\n"); + sidput(tsid2); + return BadValue; + } + sidput(tsid2); + } +out: + *sid_rtn = tsid; + if (poly_rtn) + *poly_rtn = obj->poly; + return Success; +} + +/* + * Looks up the SID corresponding to the given event type + */ +int +SELinuxEventToSID(unsigned type, security_id_t sid_of_window, + SELinuxObjectRec *sid_return) +{ + const char *name = LookupEventName(type); + security_id_t sid; + security_context_t ctx; + type &= 127; + + sid = SELinuxArrayGet(&arr_events, type); + if (!sid) { + /* Look in the mappings of event names to contexts */ + if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EVENT) < 0) { + ErrorF("SELinux: an event label lookup failed!\n"); + return BadValue; + } + /* Get a SID for context */ + if (avc_context_to_sid_raw(ctx, &sid) < 0) { + ErrorF("SELinux: a context_to_SID_raw call failed!\n"); + freecon(ctx); + return BadAlloc; + } + freecon(ctx); + /* Cache the SID value */ + if (!SELinuxArraySet(&arr_events, type, sid)) { + sidput(sid); + return BadAlloc; + } + } + + /* Perform a transition to obtain the final SID */ + if (avc_compute_create(sid_of_window, sid, SECCLASS_X_EVENT, + &sid_return->sid) < 0) { + ErrorF("SELinux: a compute_create call failed!\n"); + return BadValue; + } + + return Success; +} + +int +SELinuxExtensionToSID(const char *name, security_id_t *sid_rtn) +{ + security_context_t ctx; + + /* Look in the mappings of extension names to contexts */ + if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EXT) < 0) { + ErrorF("SELinux: a property label lookup failed!\n"); + return BadValue; + } + /* Get a SID for context */ + if (avc_context_to_sid_raw(ctx, sid_rtn) < 0) { + ErrorF("SELinux: a context_to_SID_raw call failed!\n"); + freecon(ctx); + return BadAlloc; + } + freecon(ctx); + return Success; +} + +/* + * Returns the object class corresponding to the given resource type. + */ +security_class_t +SELinuxTypeToClass(RESTYPE type) +{ + void *tmp; + + tmp = SELinuxArrayGet(&arr_types, type & TypeMask); + if (!tmp) { + unsigned long class = SECCLASS_X_RESOURCE; + + if (type & RC_DRAWABLE) + class = SECCLASS_X_DRAWABLE; + else if (type == RT_GC) + class = SECCLASS_X_GC; + else if (type == RT_FONT) + class = SECCLASS_X_FONT; + else if (type == RT_CURSOR) + class = SECCLASS_X_CURSOR; + else if (type == RT_COLORMAP) + class = SECCLASS_X_COLORMAP; + else { + /* Need to do a string lookup */ + const char *str = LookupResourceName(type); + if (!strcmp(str, "PICTURE")) + class = SECCLASS_X_DRAWABLE; + else if (!strcmp(str, "GLYPHSET")) + class = SECCLASS_X_FONT; + } + + tmp = (void *)class; + SELinuxArraySet(&arr_types, type & TypeMask, tmp); + } + + return (security_class_t)(unsigned long)tmp; +} + +security_context_t +SELinuxDefaultClientLabel(void) +{ + security_context_t ctx; + + if (selabel_lookup_raw(label_hnd, &ctx, "remote", SELABEL_X_CLIENT) < 0) + FatalError("SELinux: failed to look up remote-client context\n"); + + return ctx; +} + +void +SELinuxLabelInit(void) +{ + struct selinux_opt selabel_option = { SELABEL_OPT_VALIDATE, (char *)1 }; + + label_hnd = selabel_open(SELABEL_CTX_X, &selabel_option, 1); + if (!label_hnd) + FatalError("SELinux: Failed to open x_contexts mapping in policy\n"); +} + +void +SELinuxLabelReset(void) +{ + selabel_close(label_hnd); + label_hnd = NULL; + + /* Free local state */ + SELinuxArrayFree(&arr_types, 0); + SELinuxArrayFree(&arr_events, 0); + SELinuxArrayFree(&arr_atoms, 1); +} diff --git a/xorg-server/Xext/xselinuxint.h b/xorg-server/Xext/xselinuxint.h new file mode 100644 index 000000000..854a57dd7 --- /dev/null +++ b/xorg-server/Xext/xselinuxint.h @@ -0,0 +1,556 @@ +/************************************************************ + +Author: Eamon Walsh + +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. + +********************************************************/ + +#ifndef _XSELINUXINT_H +#define _XSELINUXINT_H + +#include +#include + +#include "globals.h" +#include "dixaccess.h" +#include "dixstruct.h" +#include "privates.h" +#include "resource.h" +#include "registry.h" +#include "inputstr.h" +#include "xselinux.h" + +/* + * Types + */ + +/* subject state (clients and devices only) */ +typedef struct { + security_id_t sid; + security_id_t dev_create_sid; + security_id_t win_create_sid; + security_id_t sel_create_sid; + security_id_t prp_create_sid; + security_id_t sel_use_sid; + security_id_t prp_use_sid; + struct avc_entry_ref aeref; + char *command; + int privileged; +} SELinuxSubjectRec; + +/* object state */ +typedef struct { + security_id_t sid; + int poly; +} SELinuxObjectRec; + +/* + * Globals + */ + +extern DevPrivateKey subjectKey; +extern DevPrivateKey objectKey; +extern DevPrivateKey dataKey; + +/* + * Label functions + */ + +int +SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn); + +int +SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec *subj, + security_id_t *sid_rtn, int *poly_rtn); + +int +SELinuxPropertyToSID(Atom property, SELinuxSubjectRec *subj, + security_id_t *sid_rtn, int *poly_rtn); + +int +SELinuxEventToSID(unsigned type, security_id_t sid_of_window, + SELinuxObjectRec *sid_return); + +int +SELinuxExtensionToSID(const char *name, security_id_t *sid_rtn); + +security_class_t +SELinuxTypeToClass(RESTYPE type); + +security_context_t +SELinuxDefaultClientLabel(void); + +void +SELinuxLabelInit(void); + +void +SELinuxLabelReset(void); + +/* + * Security module functions + */ + +void +SELinuxFlaskInit(void); + +void +SELinuxFlaskReset(void); + + +/* + * Private Flask definitions + */ + +/* Security class constants */ +#define SECCLASS_X_DRAWABLE 1 +#define SECCLASS_X_SCREEN 2 +#define SECCLASS_X_GC 3 +#define SECCLASS_X_FONT 4 +#define SECCLASS_X_COLORMAP 5 +#define SECCLASS_X_PROPERTY 6 +#define SECCLASS_X_SELECTION 7 +#define SECCLASS_X_CURSOR 8 +#define SECCLASS_X_CLIENT 9 +#define SECCLASS_X_POINTER 10 +#define SECCLASS_X_KEYBOARD 11 +#define SECCLASS_X_SERVER 12 +#define SECCLASS_X_EXTENSION 13 +#define SECCLASS_X_EVENT 14 +#define SECCLASS_X_FAKEEVENT 15 +#define SECCLASS_X_RESOURCE 16 + +#ifdef _XSELINUX_NEED_FLASK_MAP +/* Mapping from DixAccess bits to Flask permissions */ +static struct security_class_mapping map[] = { + { "x_drawable", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "list_property", /* DixListPropAccess */ + "get_property", /* DixGetPropAccess */ + "set_property", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "list_child", /* DixListAccess */ + "add_child", /* DixAddAccess */ + "remove_child", /* DixRemoveAccess */ + "hide", /* DixHideAccess */ + "show", /* DixShowAccess */ + "blend", /* DixBlendAccess */ + "override", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "send", /* DixSendAccess */ + "receive", /* DixReceiveAccess */ + "", /* DixUseAccess */ + "manage", /* DixManageAccess */ + NULL }}, + { "x_screen", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "", /* DixDestroyAccess */ + "", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "saver_getattr", /* DixListPropAccess */ + "saver_setattr", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "hide_cursor", /* DixHideAccess */ + "show_cursor", /* DixShowAccess */ + "saver_hide", /* DixBlendAccess */ + "saver_show", /* DixGrabAccess */ + NULL }}, + { "x_gc", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + NULL }}, + { "x_font", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "add_glyph", /* DixAddAccess */ + "remove_glyph", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + NULL }}, + { "x_colormap", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "add_color", /* DixAddAccess */ + "remove_color", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "install", /* DixInstallAccess */ + "uninstall", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + NULL }}, + { "x_property", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "write", /* DixBlendAccess */ + NULL }}, + { "x_selection", + { "read", /* DixReadAccess */ + "", /* DixWriteAccess */ + "", /* DixDestroyAccess */ + "setattr", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + NULL }}, + { "x_cursor", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + NULL }}, + { "x_client", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "", /* DixUseAccess */ + "manage", /* DixManageAccess */ + NULL }}, + { "x_pointer", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "list_property", /* DixListPropAccess */ + "get_property", /* DixGetPropAccess */ + "set_property", /* DixSetPropAccess */ + "getfocus", /* DixGetFocusAccess */ + "setfocus", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "add", /* DixAddAccess */ + "remove", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "grab", /* DixGrabAccess */ + "freeze", /* DixFreezeAccess */ + "force_cursor", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + "manage", /* DixManageAccess */ + "", /* DixDebugAccess */ + "bell", /* DixBellAccess */ + NULL }}, + { "x_keyboard", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "list_property", /* DixListPropAccess */ + "get_property", /* DixGetPropAccess */ + "set_property", /* DixSetPropAccess */ + "getfocus", /* DixGetFocusAccess */ + "setfocus", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "add", /* DixAddAccess */ + "remove", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "grab", /* DixGrabAccess */ + "freeze", /* DixFreezeAccess */ + "force_cursor", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + "manage", /* DixManageAccess */ + "", /* DixDebugAccess */ + "bell", /* DixBellAccess */ + NULL }}, + { "x_server", + { "record", /* DixReadAccess */ + "", /* DixWriteAccess */ + "", /* DixDestroyAccess */ + "", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "grab", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "", /* DixUseAccess */ + "manage", /* DixManageAccess */ + "debug", /* DixDebugAccess */ + NULL }}, + { "x_extension", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "", /* DixDestroyAccess */ + "", /* DixCreateAccess */ + "query", /* DixGetAttrAccess */ + "", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + NULL }}, + { "x_event", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "", /* DixDestroyAccess */ + "", /* DixCreateAccess */ + "", /* DixGetAttrAccess */ + "", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "send", /* DixSendAccess */ + "receive", /* DixReceiveAccess */ + NULL }}, + { "x_synthetic_event", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "", /* DixDestroyAccess */ + "", /* DixCreateAccess */ + "", /* DixGetAttrAccess */ + "", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "send", /* DixSendAccess */ + "receive", /* DixReceiveAccess */ + NULL }}, + { "x_resource", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "write", /* DixDestroyAccess */ + "write", /* DixCreateAccess */ + "read", /* DixGetAttrAccess */ + "write", /* DixSetAttrAccess */ + "read", /* DixListPropAccess */ + "read", /* DixGetPropAccess */ + "write", /* DixSetPropAccess */ + "read", /* DixGetFocusAccess */ + "write", /* DixSetFocusAccess */ + "read", /* DixListAccess */ + "write", /* DixAddAccess */ + "write", /* DixRemoveAccess */ + "write", /* DixHideAccess */ + "read", /* DixShowAccess */ + "read", /* DixBlendAccess */ + "write", /* DixGrabAccess */ + "write", /* DixFreezeAccess */ + "write", /* DixForceAccess */ + "write", /* DixInstallAccess */ + "write", /* DixUninstallAccess */ + "write", /* DixSendAccess */ + "read", /* DixReceiveAccess */ + "read", /* DixUseAccess */ + "write", /* DixManageAccess */ + "read", /* DixDebugAccess */ + "write", /* DixBellAccess */ + NULL }}, + { NULL } +}; + +/* x_resource "read" bits from the list above */ +#define SELinuxReadMask (DixReadAccess|DixGetAttrAccess|DixListPropAccess| \ + DixGetPropAccess|DixGetFocusAccess|DixListAccess| \ + DixShowAccess|DixBlendAccess|DixReceiveAccess| \ + DixUseAccess|DixDebugAccess) + +#endif /* _XSELINUX_NEED_FLASK_MAP */ +#endif /* _XSELINUXINT_H */ diff --git a/xorg-server/Xext/xtest.c b/xorg-server/Xext/xtest.c index 6b0e9fd14..5af2b5c83 100644 --- a/xorg-server/Xext/xtest.c +++ b/xorg-server/Xext/xtest.c @@ -640,8 +640,8 @@ int AllocXTestDevice (ClientPtr client, char* name, retval = AllocDevicePair( client, xtestname, ptr, keybd, CorePointerProc, CoreKeyboardProc, FALSE); if ( retval == Success ){ - dixSetPrivate(&((*ptr)->devPrivates), XTestDevicePrivateKey, (void *)master_ptr->id); - dixSetPrivate(&((*keybd)->devPrivates), XTestDevicePrivateKey, (void *)master_keybd->id); + dixSetPrivate(&((*ptr)->devPrivates), XTestDevicePrivateKey, (void *)(intptr_t)master_ptr->id); + dixSetPrivate(&((*keybd)->devPrivates), XTestDevicePrivateKey, (void *)(intptr_t)master_keybd->id); XIChangeDeviceProperty(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), XA_INTEGER, 8, PropModeReplace, 1, &dummy, @@ -677,7 +677,7 @@ IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master) return is_XTest; tmp = dixLookupPrivate(&dev->devPrivates, XTestDevicePrivateKey); - mid = (int)tmp; + mid = (intptr_t)tmp; /* deviceid 0 is reserved for XIAllDevices, non-zero mid means XTest * device */ diff --git a/xorg-server/Xext/xvdisp.c b/xorg-server/Xext/xvdisp.c index 04cd11a3f..5229916a9 100644 --- a/xorg-server/Xext/xvdisp.c +++ b/xorg-server/Xext/xvdisp.c @@ -1912,7 +1912,7 @@ void XineramifyXv(void) if((pAdapt->type & XvImageMask) && (pAdapt->nImages > 0)) { hasOverlay = FALSE; for(l = 0; l < pAdapt->nAttributes; l++) { - if(!strcmp(pAdapt->name, "XV_COLORKEY")) { + if(!strcmp(pAdapt->pAttributes[l].name, "XV_COLORKEY")) { hasOverlay = TRUE; break; } -- cgit v1.2.3