xserver: Branch 'XACE-SELINUX' - 10 commits
Eamon Walsh
ewalsh at kemper.freedesktop.org
Fri Sep 8 22:26:55 EEST 2006
Xext/Makefile.am | 19
Xext/XSELinuxConfig | 83 +
Xext/security.c | 6
Xext/xace.c | 4
Xext/xselinux.c | 1884 ++++++++++++++++++++++++++++++++++++
Xext/xselinux.h | 29
configure.ac | 16
dix/dispatch.c | 9
dix/extension.c | 6
hw/xfree86/dixmods/extmod/modinit.h | 5
include/dix-config.h.in | 3
mi/miinitext.c | 16
12 files changed, 2063 insertions(+), 17 deletions(-)
New commits:
diff-tree 6950267dd690ef8e29b1c32a157dd64c9b79c06d (from fb34c02861ab3629c1c85c156e73b158518db7c7)
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date: Fri Sep 8 15:31:18 2006 -0400
Add SELinux extension configure-time support.
diff --git a/Xext/Makefile.am b/Xext/Makefile.am
index 6ea3d74..be04c84 100644
--- a/Xext/Makefile.am
+++ b/Xext/Makefile.am
@@ -76,6 +76,16 @@ if XACE
BUILTIN_SRCS += $(XACE_SRCS)
endif
+# SELinux extension: provides SELinux policy support for X objects
+# requires X-ACE extension
+XSELINUX_SRCS = xselinux.c xselinux.h
+if XSELINUX
+BUILTIN_SRCS += $(XSELINUX_SRCS)
+
+SERVERCONFIG_DATA += XSELinuxConfig
+AM_CFLAGS += -DXSELINUXCONFIGFILE=\"$(SERVERCONFIGdir)/XSELinuxConfig\"
+endif
+
# Security extension: multi-level security to protect clients from each other
XCSECURITY_SRCS = security.c securitysrv.h
if XCSECURITY
diff-tree fb34c02861ab3629c1c85c156e73b158518db7c7 (from parents)
Merge: 9c503f09ce78d952d0ece77c424e42b6df3fa9ad d1110c5c83a7f439158f369ab2f3ae614fa9d2a5
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date: Fri Sep 8 15:30:12 2006 -0400
Merge branch 'my-XACE-modular' into my-XACE-SELINUX
diff-tree d1110c5c83a7f439158f369ab2f3ae614fa9d2a5 (from 9deb579dc9366590203afe0576bf88643ab36c89)
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date: Fri Sep 8 15:28:48 2006 -0400
Generalize the handling of configuration files that ship with extensions.
diff --git a/Xext/Makefile.am b/Xext/Makefile.am
index 4deb8e5..6ea3d74 100644
--- a/Xext/Makefile.am
+++ b/Xext/Makefile.am
@@ -33,6 +33,10 @@ MODULE_SRCS = \
sync.c \
xcmisc.c
+# Extra configuration files ship with some extensions
+SERVERCONFIGdir = $(libdir)/xserver
+SERVERCONFIG_DATA =
+
# Optional sources included if extension enabled by configure.ac rules
# MIT Shared Memory extension
@@ -77,8 +81,7 @@ XCSECURITY_SRCS = security.c securitysrv
if XCSECURITY
BUILTIN_SRCS += $(XCSECURITY_SRCS)
-SERVERCONFIGdir = $(libdir)/xserver
-SERVERCONFIG_DATA = SecurityPolicy
+SERVERCONFIG_DATA += SecurityPolicy
AM_CFLAGS += -DDEFAULTPOLICYFILE=\"$(SERVERCONFIGdir)/SecurityPolicy\"
endif
@@ -157,7 +160,7 @@ libXextmodule_la_SOURCES = $(MODULE_SRCS
endif
EXTRA_DIST = \
- SecurityPolicy \
+ $(SERVERCONFIG_DATA) \
$(MITSHM_SRCS) \
$(XV_SRCS) \
$(RES_SRCS) \
diff-tree 9deb579dc9366590203afe0576bf88643ab36c89 (from cec392656cda1c938d5462e1949e6eef489f9168)
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date: Fri Sep 8 15:25:17 2006 -0400
Zero out newly created ExtensionEntry structures, but only after the
devPrivates have been initialized.
diff --git a/dix/extension.c b/dix/extension.c
index ee00ab9..f58c731 100644
--- a/dix/extension.c
+++ b/dix/extension.c
@@ -80,7 +80,7 @@ extern int extensionPrivateLen;
extern unsigned *extensionPrivateSizes;
extern unsigned totalExtensionSize;
-static int
+static void
InitExtensionPrivates(ExtensionEntry *ext)
{
register char *ptr;
@@ -107,7 +107,6 @@ InitExtensionPrivates(ExtensionEntry *ex
else
ppriv->ptr = (pointer)NULL;
}
- return 1;
}
_X_EXPORT ExtensionEntry *
@@ -127,9 +126,10 @@ AddExtension(char *name, int NumEvents,
return((ExtensionEntry *) NULL);
ext = (ExtensionEntry *) xalloc(totalExtensionSize);
- if (!ext || !InitExtensionPrivates(ext))
+ if (!ext)
return((ExtensionEntry *) NULL);
bzero(ext, totalExtensionSize);
+ InitExtensionPrivates(ext);
ext->name = (char *)xalloc(strlen(name) + 1);
ext->num_aliases = 0;
ext->aliases = (char **)NULL;
diff-tree cec392656cda1c938d5462e1949e6eef489f9168 (from 0fba09cdfcc78161f5c92bef6cca53e5309656bd)
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date: Fri Sep 8 15:24:23 2006 -0400
Zero out newly allocated ClientRec structures.
This is required to initialize the devPrivates to a known state.
diff --git a/dix/dispatch.c b/dix/dispatch.c
index aa67dc4..7c4d539 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3612,8 +3612,13 @@ CloseDownRetainedResources()
}
}
+extern int clientPrivateLen;
+extern unsigned *clientPrivateSizes;
+extern unsigned totalClientSize;
+
void InitClient(ClientPtr client, int i, pointer ospriv)
{
+ bzero(client, totalClientSize);
client->index = i;
client->sequence = 0;
client->clientAsMask = ((Mask)i) << CLIENTOFFSET;
@@ -3664,10 +3669,6 @@ void InitClient(ClientPtr client, int i,
#endif
}
-extern int clientPrivateLen;
-extern unsigned *clientPrivateSizes;
-extern unsigned totalClientSize;
-
int
InitClientPrivates(ClientPtr client)
{
diff-tree 0fba09cdfcc78161f5c92bef6cca53e5309656bd (from c93877100eb98647c5b6b8556730d54677f730b6)
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date: Fri Sep 8 15:23:06 2006 -0400
Include dix-config.h.
diff --git a/Xext/xace.c b/Xext/xace.c
index 44aaa42..14a5e79 100644
--- a/Xext/xace.c
+++ b/Xext/xace.c
@@ -17,6 +17,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE
********************************************************/
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
#include <stdarg.h>
#include "windowstr.h"
#include "scrnintstr.h"
diff-tree c93877100eb98647c5b6b8556730d54677f730b6 (from 0b81fccd2ee4e054e5cffb739de07460ff2c13f7)
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date: Fri Sep 8 15:21:57 2006 -0400
Don't need to allocate memory now that devPrivates are being used.
diff --git a/Xext/security.c b/Xext/security.c
index 43f32fc..54a2b3e 100644
--- a/Xext/security.c
+++ b/Xext/security.c
@@ -1131,12 +1131,6 @@ CALLBACK(SecurityClientStateCallback)
XID authId = AuthorizationIDOfClient(client);
SecurityAuthorizationPtr pAuth;
- /* allocate space for security state */
- STATEPTR(client) = xalloc(sizeof(SecurityClientStateRec));
- if (!STATEPTR(client))
- FatalError("Client %d: couldn't allocate security state\n",
- client->index);
-
TRUSTLEVEL(client) = XSecurityClientTrusted;
AUTHID(client) = authId;
pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId,
diff-tree 9c503f09ce78d952d0ece77c424e42b6df3fa9ad (from 9aa44e3e4c321f42d8e64f83c7f0932470593c26)
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date: Fri Sep 8 15:17:01 2006 -0400
Add SELinux extension to the module/extension loader.
diff --git a/hw/xfree86/dixmods/extmod/modinit.h b/hw/xfree86/dixmods/extmod/modinit.h
index 41f060b..131b9e6 100644
--- a/hw/xfree86/dixmods/extmod/modinit.h
+++ b/hw/xfree86/dixmods/extmod/modinit.h
@@ -129,6 +129,11 @@ extern void ShmRegisterFuncs(
extern void XaceExtensionInit(INITARGS);
#endif
+#ifdef XSELINUX
+extern void XSELinuxExtensionSetup(INITARGS);
+extern void XSELinuxExtensionInit(INITARGS);
+#endif
+
#if 1
extern void SecurityExtensionSetup(INITARGS);
extern void SecurityExtensionInit(INITARGS);
diff --git a/mi/miinitext.c b/mi/miinitext.c
index aafd014..bab45cd 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -248,6 +248,9 @@ typedef void (*InitExtension)(INITARGS);
#include "securitysrv.h"
#include <X11/extensions/securstr.h>
#endif
+#ifdef XSELINUX
+#include "xselinux.h"
+#endif
#ifdef PANORAMIX
#include <X11/extensions/panoramiXproto.h>
#endif
@@ -321,6 +324,10 @@ extern void XaceExtensionInit(INITARGS);
extern void SecurityExtensionSetup(INITARGS);
extern void SecurityExtensionInit(INITARGS);
#endif
+#ifdef XSELINUX
+extern void XSELinuxExtensionSetup(INITARGS);
+extern void XSELinuxExtensionInit(INITARGS);
+#endif
#ifdef XPRINT
extern void XpExtensionInit(INITARGS);
#endif
@@ -532,6 +539,9 @@ InitExtensions(argc, argv)
#ifdef XCSECURITY
SecurityExtensionSetup();
#endif
+#ifdef XSELINUX
+ XSELinuxExtensionSetup();
+#endif
#ifdef PANORAMIX
# if !defined(PRINT_ONLY_SERVER) && !defined(NO_PANORAMIX)
if (!noPanoramiXExtension) PanoramiXExtensionInit();
@@ -600,6 +610,9 @@ InitExtensions(argc, argv)
#ifdef XCSECURITY
if (!noSecurityExtension) SecurityExtensionInit();
#endif
+#ifdef XSELINUX
+ XSELinuxExtensionInit();
+#endif
#ifdef XPRINT
XpExtensionInit(); /* server-specific extension, cannot be disabled */
#endif
@@ -705,6 +718,9 @@ static ExtensionModule staticExtensions[
#ifdef XCSECURITY
{ SecurityExtensionInit, SECURITY_EXTENSION_NAME, &noSecurityExtension, SecurityExtensionSetup, NULL },
#endif
+#ifdef XSELINUX
+ { XSELinuxExtensionInit, XSELINUX_EXTENSION_NAME, NULL, XSELinuxExtensionSetup, NULL },
+#endif
#ifdef XPRINT
{ XpExtensionInit, XP_PRINTNAME, NULL, NULL, NULL },
#endif
diff-tree 9aa44e3e4c321f42d8e64f83c7f0932470593c26 (from 150eabc4c8a08c81c48493583f922a1240b7e91c)
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date: Fri Sep 8 15:15:19 2006 -0400
Add SELinux extension configure-time support.
diff --git a/configure.ac b/configure.ac
index 49dfad2..cf838b8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -414,6 +414,7 @@ AC_ARG_ENABLE(xinerama, AS_HELP_ST
AC_ARG_ENABLE(xf86vidmode, AS_HELP_STRING([--disable-xf86vidmode], [Build XF86VidMode extension (default: enabled)]), [XF86VIDMODE=$enableval], [XF86VIDMODE=yes])
AC_ARG_ENABLE(xf86misc, AS_HELP_STRING([--disable-xf86misc], [Build XF86Misc extension (default: enabled)]), [XF86MISC=$enableval], [XF86MISC=yes])
AC_ARG_ENABLE(xace, AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes])
+AC_ARG_ENABLE(xselinux, AS_HELP_STRING([--disable-xselinux], [Build SELinux extension (default: enabled)]), [XSELINUX=$enableval], [XSELINUX=$XACE])
AC_ARG_ENABLE(xcsecurity, AS_HELP_STRING([--disable-xcsecurity], [Build Security extension (default: enabled)]), [XCSECURITY=$enableval], [XCSECURITY=$XACE])
AC_ARG_ENABLE(appgroup, AS_HELP_STRING([--disable-appgroup], [Build XC-APPGROUP extension (default: enabled)]), [APPGROUP=$enableval], [APPGROUP=$XCSECURITY])
AC_ARG_ENABLE(xcalibrate, AS_HELP_STRING([--enable-xcalibrate], [Build XCalibrate extension (default: disabled)]), [XCALIBRATE=$enableval], [XCALIBRATE=no])
@@ -627,6 +628,19 @@ if test "x$XACE" = xyes; then
AC_DEFINE(XACE, 1, [Build X-ACE extension])
fi
+AM_CONDITIONAL(XSELINUX, [test "x$XSELINUX" = xyes])
+if test "x$XSELINUX" = xyes; then
+ if test "x$XACE" != xyes; then
+ AC_MSG_ERROR([cannot build SELinux extension without X-ACE])
+ fi
+ AC_CHECK_HEADERS([selinux/selinux.h selinux/avc.h], [], AC_MSG_ERROR([SELinux include files not found]))
+ AC_CHECK_LIB(selinux, avc_init, [], AC_MSG_ERROR([SELinux library not found]))
+ AC_CHECK_HEADERS([libaudit.h], [], AC_MSG_ERROR([SELinux extension requires audit system headers]))
+ AC_CHECK_LIB(audit, audit_log_avc, [], AC_MSG_ERROR([SELinux extension requires audit system library]))
+ AC_DEFINE(XSELINUX, 1, [Build SELinux extension])
+ SELINUX_LIB="-lselinux -laudit"
+fi
+
AM_CONDITIONAL(XCSECURITY, [test "x$XCSECURITY" = xyes])
if test "x$XCSECURITY" = xyes; then
if test "x$XACE" != xyes; then
@@ -1042,7 +1056,7 @@ if test "x$XORG" = xyes -o "x$XGL" = xye
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
XORG_INCS="$XORG_DDXINCS $XORG_OSINCS"
XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H"
- XORG_LIBS="$COMPOSITE_LIB $MI_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XPSTUBS_LIB $OS_LIB"
+ XORG_LIBS="$COMPOSITE_LIB $MI_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XPSTUBS_LIB $SELINUX_LIB $OS_LIB"
dnl Check to see if dlopen is in default libraries (like Solaris, which
dnl has it in libc), or if libdl is needed to get it.
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 571a867..f664548 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -311,6 +311,9 @@
/* Build X-ACE extension */
#undef XACE
+/* Build SELinux extension */
+#undef XSELINUX
+
/* Support XCMisc extension */
#undef XCMISC
diff-tree 150eabc4c8a08c81c48493583f922a1240b7e91c (from 0b81fccd2ee4e054e5cffb739de07460ff2c13f7)
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date: Fri Sep 8 15:11:04 2006 -0400
Add SELinux extension source files.
diff --git a/Xext/XSELinuxConfig b/Xext/XSELinuxConfig
new file mode 100644
index 0000000..faf815e
--- /dev/null
+++ b/Xext/XSELinuxConfig
@@ -0,0 +1,83 @@
+#
+# Config file for XSELinux extension
+#
+
+#
+# The nonlocal_context rule defines a context to be used for all clients
+# connecting to the server from a remote host. The nonlocal context must
+# be defined, and it must be a valid context according to the SELinux
+# security policy. Only one nonlocal_context rule may be defined.
+#
+nonlocal_context system_u:object_r:remote_xclient_t:s1
+
+#
+# Property rules map a property name to a SELinux type. The type must
+# be valid according to the SELinux security policy. There can be any
+# number of property rules. Additionally, a default property type can be
+# defined for all properties not explicitly listed. The default
+# property type may not be omitted. The default rule may appear in
+# any position (it need not be the last property rule listed).
+#
+property WM_NAME wm_property_t
+property WM_CLASS wm_property_t
+property WM_ICON_NAME wm_property_t
+property WM_HINTS wm_property_t
+property WM_NORMAL_HINTS wm_property_t
+property WM_COMMAND wm_property_t
+
+property CUT_BUFFER0 cut_buffer_property_t
+property CUT_BUFFER1 cut_buffer_property_t
+property CUT_BUFFER2 cut_buffer_property_t
+property CUT_BUFFER3 cut_buffer_property_t
+property CUT_BUFFER4 cut_buffer_property_t
+property CUT_BUFFER5 cut_buffer_property_t
+property CUT_BUFFER6 cut_buffer_property_t
+property CUT_BUFFER7 cut_buffer_property_t
+
+property default unknown_property_t
+
+#
+# Extension rules map an extension name to a SELinux type. The type must
+# be valid according to the SELinux security policy. There can be any
+# number of extension rules. Additionally, a default extension type can
+# be defined for all extensions not explicitly listed. The default
+# extension type may not be omitted. The default rule may appear in
+# any position (it need not be the last extension rule listed).
+#
+extension BIG-REQUESTS std_ext_t
+extension DOUBLE-BUFFER std_ext_t
+extension DPMS screensaver_ext_t
+extension Extended-Visual-Information std_ext_t
+extension FontCache font_ext_t
+extension GLX std_ext_t
+extension LBX std_ext_t
+extension MIT-SCREEN-SAVER screensaver_ext_t
+extension MIT-SHM shmem_ext_t
+extension MIT-SUNDRY-NONSTANDARD std_ext_t
+extension NV-CONTROL accelgraphics_ext_t
+extension NV-GLX accelgraphics_ext_t
+extension NVIDIA-GLX accelgraphics_ext_t
+extension RANDR std_ext_t
+extension RECORD debug_ext_t
+extension RENDER std_ext_t
+extension SECURITY security_ext_t
+extension SELinux security_ext_t
+extension SHAPE std_ext_t
+extension SYNC sync_ext_t
+extension TOG-CUP windowmgr_ext_t
+extension X-Resource debug_ext_t
+extension XAccessControlExtension security_ext_t
+extension XACEUSR security_ext_t
+extension XC-APPGROUP security_ext_t
+extension XC-MISC std_ext_t
+extension XFree86-Bigfont font_ext_t
+extension XFree86-DGA accelgraphics_ext_t
+extension XFree86-Misc std_ext_t
+extension XFree86-VidModeExtension video_ext_t
+extension XInputExtension input_ext_t
+extension XKEYBOARD input_ext_t
+extension XpExtension std_ext_t
+extension XTEST debug_ext_t
+extension XVideo video_ext_t
+extension XVideo-MotionCompensation video_ext_t
+extension default unknown_ext_t
diff --git a/Xext/xselinux.c b/Xext/xselinux.c
new file mode 100644
index 0000000..5a6d2ef
--- /dev/null
+++ b/Xext/xselinux.c
@@ -0,0 +1,1884 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh at epoch.ncsc.mil>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+this permission notice appear in supporting documentation. This permission
+notice shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+********************************************************/
+
+/*
+ * Portions of this code copyright (c) 2005 by Trusted Computer Solutions, Inc.
+ * All rights reserved.
+ */
+
+#include <selinux/flask.h>
+#include <selinux/av_permissions.h>
+#include <selinux/selinux.h>
+#include <selinux/context.h>
+#include <selinux/avc.h>
+
+#include <libaudit.h>
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xfuncproto.h>
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "resource.h"
+#include "selection.h"
+#include "xacestr.h"
+#include "xselinux.h"
+#define XSERV_t
+#define TRANS_SERVER
+#include <X11/Xtrans/Xtrans.h>
+#include "../os/osdep.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include "modinit.h"
+
+#ifndef XSELINUXCONFIGFILE
+#warning "XSELinux Policy file is not defined"
+#define XSELINUXCONFIGFILE NULL
+#endif
+
+
+/* Make sure a locally connecting client has a valid context. The context
+ * for this client is retrieved again later on in AssignClientState(), but
+ * by that point it's too late to reject the client.
+ */
+static char *
+XSELinuxValidContext (ClientPtr client)
+{
+ security_context_t ctx = NULL;
+ XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn;
+ char reason[256];
+ char *ret = (char *)NULL;
+
+ if (_XSERVTransIsLocal(ci))
+ {
+ int fd = _XSERVTransGetConnectionNumber(ci);
+ if (getpeercon(fd, &ctx) < 0)
+ {
+ snprintf(reason, sizeof(reason), "Failed to retrieve SELinux context from socket");
+ ret = reason;
+ goto out;
+ }
+ if (security_check_context(ctx))
+ {
+ snprintf(reason, sizeof(reason), "Client's SELinux context is invalid: %s", ctx);
+ ret = reason;
+ }
+
+ freecon(ctx);
+ }
+
+out:
+ return ret;
+}
+
+
+/* devPrivates in client and extension */
+static int clientPrivateIndex;
+static int extnsnPrivateIndex;
+
+/* audit file descriptor */
+static int audit_fd;
+
+/* structure passed to auditing callback */
+typedef struct {
+ ClientPtr client; /* client */
+ char *property; /* property name, if any */
+ char *extension; /* extension name, if any */
+} XSELinuxAuditRec;
+
+/*
+ * Table of SELinux types for property names.
+ */
+static char **propertyTypes = NULL;
+static int propertyTypesCount = 0;
+char *XSELinuxPropertyTypeDefault = NULL;
+
+/*
+ * Table of SELinux types for each extension.
+ */
+static char **extensionTypes = NULL;
+static int extensionTypesCount = 0;
+static char *XSELinuxExtensionTypeDefault = NULL;
+
+/* security context for non-local clients */
+static char *XSELinuxNonlocalContextDefault = NULL;
+
+/* security context for the root window */
+static char *XSELinuxRootWindowContext = NULL;
+
+/* Selection stuff from dix */
+extern Selection *CurrentSelections;
+extern int NumCurrentSelections;
+
+/*
+ * list of classes corresponding to SIDs in the
+ * rsid array of the security state structure (below).
+ *
+ * XXX SIDs should be stored in their native objects, not all
+ * bunched together in the client structure. However, this will
+ * require modification to the resource manager.
+ */
+static security_class_t sClasses[] = {
+ SECCLASS_WINDOW,
+ SECCLASS_DRAWABLE,
+ SECCLASS_GC,
+ SECCLASS_CURSOR,
+ SECCLASS_FONT,
+ SECCLASS_COLORMAP,
+ SECCLASS_PROPERTY,
+ SECCLASS_XCLIENT,
+ SECCLASS_XINPUT
+};
+#define NRES (sizeof(sClasses)/sizeof(sClasses[0]))
+
+/* This is what we store for client security state */
+typedef struct {
+ int haveState;
+ security_id_t sid;
+ security_id_t rsid[NRES];
+ struct avc_entry_ref aeref;
+} XSELinuxClientStateRec;
+
+/* Convenience macros for accessing security state fields */
+#define STATEPTR(client) \
+ ((client)->devPrivates[clientPrivateIndex].ptr)
+#define HAVESTATE(client) \
+ (((XSELinuxClientStateRec*)STATEPTR(client))->haveState)
+#define SID(client) \
+ (((XSELinuxClientStateRec*)STATEPTR(client))->sid)
+#define RSID(client,n) \
+ (((XSELinuxClientStateRec*)STATEPTR(client))->rsid[n])
+#define AEREF(client) \
+ (((XSELinuxClientStateRec*)STATEPTR(client))->aeref)
+#define EXTENSIONSID(ext) \
+ ((ext)->devPrivates[extnsnPrivateIndex].ptr)
+
+/*
+ * Returns the index into the rsid array where the SID for the
+ * given class is stored.
+ */
+static int
+IndexByClass(security_class_t class)
+{
+ int i;
+ for (i=0; i<NRES; i++)
+ if (class == sClasses[i])
+ return i;
+ return 0;
+}
+
+/*
+ * Does sanity checking on a resource ID. This can be removed after
+ * testing.
+ */
+static void
+CheckXID(XID id)
+{
+ /*
+ XID c = CLIENT_ID(id);
+
+ if (c > 10)
+ ErrorF("Warning: possibly mangled ID %x\n", id);
+
+ c = id & RESOURCE_ID_MASK;
+ if (c > 100)
+ ErrorF("Warning: possibly mangled ID %x\n", id);
+ */
+}
+
+/*
+ * Byte-swap a CARD32 id if necessary.
+ */
+static XID
+SwapXID(ClientPtr client, XID id)
+{
+ register char n;
+ if (client->swapped)
+ swapl(&id, n);
+ return id;
+}
+
+/*
+ * ServerPerm - check access permissions on a server-owned object.
+ *
+ * Arguments:
+ * client: Client doing the request.
+ * class: Security class of the server object being accessed.
+ * perm: Permissions required on the object.
+ *
+ * Returns: boolean TRUE=allowed, FALSE=denied.
+ */
+static int
+ServerPerm(ClientPtr client,
+ security_class_t class,
+ access_vector_t perm)
+{
+ int idx = IndexByClass(class);
+ if (HAVESTATE(client))
+ {
+ XSELinuxAuditRec auditdata;
+ auditdata.client = client;
+ auditdata.property = NULL;
+ auditdata.extension = NULL;
+ errno = 0;
+ if (avc_has_perm(SID(client), RSID(serverClient,idx), class,
+ perm, &AEREF(client), &auditdata) < 0)
+ {
+ if (errno != EACCES)
+ ErrorF("ServerPerm: unexpected error %d\n", errno);
+ return FALSE;
+ }
+ }
+ else
+ {
+ ErrorF("No client state in server-perm check!\n");
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * IDPerm - check access permissions on a resource.
+ *
+ * Arguments:
+ * client: Client doing the request.
+ * id: resource id of the resource being accessed.
+ * class: Security class of the resource being accessed.
+ * perm: Permissions required on the resource.
+ *
+ * Returns: boolean TRUE=allowed, FALSE=denied.
+ */
+static int
+IDPerm(ClientPtr sclient,
+ XID id,
+ security_class_t class,
+ access_vector_t perm)
+{
+ ClientPtr tclient;
+ int idx = IndexByClass(class);
+ XSELinuxAuditRec auditdata;
+
+ if (id == None)
+ return TRUE;
+
+ CheckXID(id);
+ tclient = clients[CLIENT_ID(id)];
+
+ /*
+ * This happens in the case where a client has
+ * disconnected. XXX might want to make the server
+ * own orphaned resources...
+ */
+ if (!tclient || !HAVESTATE(tclient) || !HAVESTATE(sclient))
+ {
+ return TRUE;
+ }
+
+ auditdata.client = sclient;
+ auditdata.property = NULL;
+ auditdata.extension = NULL;
+ errno = 0;
+ if (avc_has_perm(SID(sclient), RSID(tclient,idx), class,
+ perm, &AEREF(sclient), &auditdata) < 0)
+ {
+ if (errno != EACCES)
+ ErrorF("IDPerm: unexpected error %d\n", errno);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * ObjectSIDByLabel - get SID for an extension or property.
+ *
+ * Arguments:
+ * class: should be SECCLASS_XEXTENSION or SECCLASS_PROPERTY.
+ * name: name of the extension or property.
+ *
+ * Returns: proper SID for the object or NULL on error.
+ */
+static security_id_t
+ObjectSIDByLabel(security_context_t basecontext, security_class_t class,
+ const char *name)
+{
+ security_context_t base, new;
+ context_t con;
+ security_id_t sid = NULL;
+ char **ptr, *type = NULL;
+
+ if (basecontext != NULL)
+ {
+ /* use the supplied context */
+ base = strdup(basecontext);
+ if (base == NULL)
+ goto out;
+ }
+ else
+ {
+ /* get server context */
+ if (getcon(&base) < 0)
+ goto out;
+ }
+
+ /* make a new context-manipulation object */
+ con = context_new(base);
+ if (!con)
+ goto out2;
+
+ /* look in the mappings of names to types */
+ ptr = (class == SECCLASS_PROPERTY) ? propertyTypes : extensionTypes;
+ for (; *ptr; ptr+=2)
+ if (!strcmp(*ptr, name))
+ break;
+ type = ptr[1];
+
+ /* set the role and type in the context (user unchanged) */
+ if (context_type_set(con, type) ||
+ context_role_set(con, "object_r"))
+ goto out3;
+
+ /* get a context string from the context-manipulation object */
+ new = context_str(con);
+ if (!new)
+ goto out3;
+
+ /* get a SID for the context */
+ if (avc_context_to_sid(new, &sid) < 0)
+ goto out3;
+
+ out3:
+ context_free(con);
+ out2:
+ freecon(base);
+ out:
+ return sid;
+}
+
+/*
+ * AssignClientState - set up client security state.
+ *
+ * Arguments:
+ * client: client to set up (can be serverClient).
+ */
+static void
+AssignClientState(ClientPtr client)
+{
+ int i, needToFree = 0;
+ security_context_t basectx, objctx;
+ XSELinuxClientStateRec *state = (XSELinuxClientStateRec*)STATEPTR(client);
+ Bool isServerClient = FALSE;
+
+ avc_entry_ref_init(&state->aeref);
+
+ if (client->index > 0)
+ {
+ XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn;
+ if (_XSERVTransIsLocal(ci)) {
+ /* for local clients, can get context from the socket */
+ int fd = _XSERVTransGetConnectionNumber(ci);
+ if (getpeercon(fd, &basectx) < 0)
+ {
+ FatalError("Client %d: couldn't get context from socket\n",
+ client->index);
+ }
+ needToFree = 1;
+ }
+ else
+ {
+ /* for remote clients, need to use a default context */
+ basectx = XSELinuxNonlocalContextDefault;
+ }
+ }
+ else
+ {
+ isServerClient = TRUE;
+
+ /* use the context of the X server process for the serverClient */
+ if (getcon(&basectx) < 0)
+ {
+ FatalError("Couldn't get context of X server process\n");
+ }
+ needToFree = 1;
+ }
+
+ /* get a SID from the context */
+ if (avc_context_to_sid(basectx, &state->sid) < 0)
+ {
+ FatalError("Client %d: couldn't get security ID for client\n",
+ client->index);
+ }
+
+ /* get contexts and then SIDs for each resource type */
+ for (i=0; i<NRES; i++)
+ {
+ if (security_compute_create(basectx, basectx, sClasses[i],
+ &objctx) < 0)
+ {
+ FatalError("Client %d: couldn't get context for class %x\n",
+ client->index, sClasses[i]);
+ }
+ else if (avc_context_to_sid(objctx, &state->rsid[i]) < 0)
+ {
+ FatalError("Client %d: couldn't get SID for class %x\n",
+ client->index, sClasses[i]);
+ }
+ freecon(objctx);
+ }
+
+ /* special handling for serverClient windows (that is, root windows) */
+ if (isServerClient == TRUE)
+ {
+ i = IndexByClass(SECCLASS_WINDOW);
+ sidput(state->rsid[i]);
+ if (avc_context_to_sid(XSELinuxRootWindowContext, &state->rsid[i]))
+ {
+ FatalError("Failed to set SID for root window\n");
+ }
+ }
+
+ /* mark as set up, free base context if necessary, and return */
+ state->haveState = TRUE;
+ if (needToFree)
+ freecon(basectx);
+}
+
+/*
+ * FreeClientState - tear down client security state.
+ *
+ * Arguments:
+ * client: client to release (can be serverClient).
+ */
+static void
+FreeClientState(ClientPtr client)
+{
+ int i;
+ XSELinuxClientStateRec *state = (XSELinuxClientStateRec*)STATEPTR(client);
+
+ /* client state may not be set up if its auth was rejected */
+ if (state->haveState) {
+ state = (XSELinuxClientStateRec*)STATEPTR(client);
+ sidput(state->sid);
+ for (i=0; i<NRES; i++)
+ sidput(state->rsid[i]);
+ state->haveState = FALSE;
+ }
+}
+
+#define REQUEST_SIZE_CHECK(client, req) \
+ (client->req_len >= (sizeof(req) >> 2))
+#define IDPERM(client, req, field, class, perm) \
+ (REQUEST_SIZE_CHECK(client,req) && \
+ IDPerm(client, SwapXID(client,((req*)stuff)->field), class, perm))
+#define CALLBACK(name) static void \
+name(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
+
+static int
+CheckSendEventPerms(ClientPtr client)
+{
+ register char n;
+ access_vector_t perm = 0;
+ REQUEST(xSendEventReq);
+
+ /* might need type bounds checking here */
+ if (!REQUEST_SIZE_CHECK(client, xSendEventReq))
+ return FALSE;
+
+ switch (stuff->event.u.u.type) {
+ case SelectionClear:
+ case SelectionNotify:
+ case SelectionRequest:
+ case ClientMessage:
+ case PropertyNotify:
+ perm = WINDOW__CLIENTCOMEVENT;
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ case KeyPress:
+ case KeyRelease:
+ case KeymapNotify:
+ case MotionNotify:
+ case EnterNotify:
+ case LeaveNotify:
+ case FocusIn:
+ case FocusOut:
+ perm = WINDOW__INPUTEVENT;
+ break;
+ case Expose:
+ case GraphicsExpose:
+ case NoExpose:
+ case VisibilityNotify:
+ perm = WINDOW__DRAWEVENT;
+ break;
+ case CirculateNotify:
+ case ConfigureNotify:
+ case CreateNotify:
+ case DestroyNotify:
+ case MapNotify:
+ case UnmapNotify:
+ case GravityNotify:
+ case ReparentNotify:
+ perm = WINDOW__WINDOWCHANGEEVENT;
+ break;
+ case CirculateRequest:
+ case ConfigureRequest:
+ case MapRequest:
+ case ResizeRequest:
+ perm = WINDOW__WINDOWCHANGEREQUEST;
+ break;
+ case ColormapNotify:
+ case MappingNotify:
+ perm = WINDOW__SERVERCHANGEEVENT;
+ break;
+ default:
+ perm = WINDOW__EXTENSIONEVENT;
+ break;
+ }
+ if (client->swapped)
+ swapl(&stuff->destination, n);
+ return IDPerm(client, stuff->destination, SECCLASS_WINDOW, perm);
+}
+
+static int
+CheckConvertSelectionPerms(ClientPtr client)
+{
+ register char n;
+ int rval = TRUE;
+ REQUEST(xConvertSelectionReq);
+
+ if (!REQUEST_SIZE_CHECK(client, xConvertSelectionReq))
+ return FALSE;
+
+ if (client->swapped)
+ {
+ swapl(&stuff->selection, n);
+ swapl(&stuff->requestor, n);
+ }
+
+ if (ValidAtom(stuff->selection))
+ {
+ int i = 0;
+ while ((i < NumCurrentSelections) &&
+ CurrentSelections[i].selection != stuff->selection) i++;
+ if (i < NumCurrentSelections)
+ rval = rval && IDPerm(client, CurrentSelections[i].window,
+ SECCLASS_WINDOW, WINDOW__CLIENTCOMEVENT);
+ }
+ rval = rval && IDPerm(client, stuff->requestor,
+ SECCLASS_WINDOW, WINDOW__CLIENTCOMEVENT);
+ return rval;
+}
+
+static int
+CheckSetSelectionOwnerPerms(ClientPtr client)
+{
+ register char n;
+ int rval = TRUE;
+ REQUEST(xSetSelectionOwnerReq);
+
+ if (!REQUEST_SIZE_CHECK(client, xSetSelectionOwnerReq))
+ return FALSE;
+
+ if (client->swapped)
+ {
+ swapl(&stuff->selection, n);
+ swapl(&stuff->window, n);
+ }
+
+ if (ValidAtom(stuff->selection))
+ {
+ int i = 0;
+ while ((i < NumCurrentSelections) &&
+ CurrentSelections[i].selection != stuff->selection) i++;
+ if (i < NumCurrentSelections)
+ rval = rval && IDPerm(client, CurrentSelections[i].window,
+ SECCLASS_WINDOW, WINDOW__CHSELECTION);
+ }
+ rval = rval && IDPerm(client, stuff->window,
+ SECCLASS_WINDOW, WINDOW__CHSELECTION);
+ return rval;
+}
+
+CALLBACK(XSELinuxCoreDispatch)
+{
+ XaceCoreDispatchRec *rec = (XaceCoreDispatchRec*)calldata;
+ ClientPtr client = rec->client;
+ REQUEST(xReq);
+ Bool rval;
+
+ switch(stuff->reqType) {
+ /* Drawable class control requirements */
+ case X_ClearArea:
+ rval = IDPERM(client, xClearAreaReq, window,
+ SECCLASS_DRAWABLE, DRAWABLE__DRAW);
+ break;
+ case X_PolySegment:
+ case X_PolyRectangle:
+ case X_PolyArc:
+ case X_PolyFillRectangle:
+ case X_PolyFillArc:
+ rval = IDPERM(client, xPolySegmentReq, drawable,
+ SECCLASS_DRAWABLE, DRAWABLE__DRAW);
+ break;
+ case X_PolyPoint:
+ case X_PolyLine:
+ rval = IDPERM(client, xPolyPointReq, drawable,
+ SECCLASS_DRAWABLE, DRAWABLE__DRAW);
+ break;
+ case X_FillPoly:
+ rval = IDPERM(client, xFillPolyReq, drawable,
+ SECCLASS_DRAWABLE, DRAWABLE__DRAW);
+ break;
+ case X_PutImage:
+ rval = IDPERM(client, xPutImageReq, drawable,
+ SECCLASS_DRAWABLE, DRAWABLE__DRAW);
+ break;
+ case X_CopyArea:
+ case X_CopyPlane:
+ rval = IDPERM(client, xCopyAreaReq, srcDrawable,
+ SECCLASS_DRAWABLE, DRAWABLE__COPY)
+ && IDPERM(client, xCopyAreaReq, dstDrawable,
+ SECCLASS_DRAWABLE, DRAWABLE__DRAW);
+ break;
+ case X_GetImage:
+ rval = IDPERM(client, xGetImageReq, drawable,
+ SECCLASS_DRAWABLE, DRAWABLE__COPY);
+ break;
+ case X_GetGeometry:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_DRAWABLE, DRAWABLE__GETATTR);
+ break;
+
+ /* Window class control requirements */
+ case X_ChangeProperty:
+ rval = IDPERM(client, xChangePropertyReq, window,
+ SECCLASS_WINDOW,
+ WINDOW__CHPROPLIST | WINDOW__CHPROP |
+ WINDOW__LISTPROP);
+ break;
+ case X_ChangeSaveSet:
+ rval = IDPERM(client, xChangeSaveSetReq, window,
+ SECCLASS_WINDOW,
+ WINDOW__CTRLLIFE | WINDOW__CHPARENT);
+ break;
+ case X_ChangeWindowAttributes:
+ rval = IDPERM(client, xChangeWindowAttributesReq, window,
+ SECCLASS_WINDOW, WINDOW__SETATTR);
+ break;
+ case X_CirculateWindow:
+ rval = IDPERM(client, xCirculateWindowReq, window,
+ SECCLASS_WINDOW, WINDOW__CHSTACK);
+ break;
+ case X_ConfigureWindow:
+ rval = IDPERM(client, xConfigureWindowReq, window,
+ SECCLASS_WINDOW,
+ WINDOW__SETATTR | WINDOW__MOVE | WINDOW__CHSTACK);
+ break;
+ case X_ConvertSelection:
+ rval = CheckConvertSelectionPerms(client);
+ break;
+ case X_CreateWindow:
+ rval = IDPERM(client, xCreateWindowReq, wid,
+ SECCLASS_WINDOW,
+ WINDOW__CREATE | WINDOW__SETATTR | WINDOW__MOVE)
+ && IDPERM(client, xCreateWindowReq, parent,
+ SECCLASS_WINDOW,
+ WINDOW__CHSTACK | WINDOW__ADDCHILD)
+ && IDPERM(client, xCreateWindowReq, wid,
+ SECCLASS_DRAWABLE, DRAWABLE__CREATE);
+ break;
+ case X_DeleteProperty:
+ rval = IDPERM(client, xDeletePropertyReq, window,
+ SECCLASS_WINDOW,
+ WINDOW__CHPROP | WINDOW__CHPROPLIST);
+ break;
+ case X_DestroyWindow:
+ case X_DestroySubwindows:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_WINDOW,
+ WINDOW__ENUMERATE | WINDOW__UNMAP | WINDOW__DESTROY)
+ && IDPERM(client, xResourceReq, id,
+ SECCLASS_DRAWABLE, DRAWABLE__DESTROY);
+ break;
+ case X_GetMotionEvents:
+ rval = IDPERM(client, xGetMotionEventsReq, window,
+ SECCLASS_WINDOW, WINDOW__MOUSEMOTION);
+ break;
+ case X_GetProperty:
+ rval = IDPERM(client, xGetPropertyReq, window,
+ SECCLASS_WINDOW, WINDOW__LISTPROP);
+ break;
+ case X_GetWindowAttributes:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_WINDOW, WINDOW__GETATTR);
+ break;
+ case X_KillClient:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_XCLIENT, XCLIENT__KILL);
+ break;
+ case X_ListProperties:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_WINDOW, WINDOW__LISTPROP);
+ break;
+ case X_MapWindow:
+ case X_MapSubwindows:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_WINDOW,
+ WINDOW__ENUMERATE | WINDOW__GETATTR | WINDOW__MAP);
+ break;
+ case X_QueryTree:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_WINDOW, WINDOW__ENUMERATE | WINDOW__GETATTR);
+ break;
+ case X_RotateProperties:
+ rval = IDPERM(client, xRotatePropertiesReq, window,
+ SECCLASS_WINDOW, WINDOW__CHPROP | WINDOW__CHPROPLIST);
+ break;
+ case X_ReparentWindow:
+ rval = IDPERM(client, xReparentWindowReq, window,
+ SECCLASS_WINDOW, WINDOW__CHPARENT | WINDOW__MOVE)
+ && IDPERM(client, xReparentWindowReq, parent,
+ SECCLASS_WINDOW, WINDOW__CHSTACK | WINDOW__ADDCHILD);
+ break;
+ case X_SendEvent:
+ rval = CheckSendEventPerms(client);
+ break;
+ case X_SetInputFocus:
+ rval = IDPERM(client, xSetInputFocusReq, focus,
+ SECCLASS_WINDOW, WINDOW__SETFOCUS)
+ && ServerPerm(client, SECCLASS_XINPUT, XINPUT__SETFOCUS);
+ break;
+ case X_SetSelectionOwner:
+ rval = CheckSetSelectionOwnerPerms(client);
+ break;
+ case X_TranslateCoords:
+ rval = IDPERM(client, xTranslateCoordsReq, srcWid,
+ SECCLASS_WINDOW, WINDOW__GETATTR)
+ && IDPERM(client, xTranslateCoordsReq, dstWid,
+ SECCLASS_WINDOW, WINDOW__GETATTR);
+ break;
+ case X_UnmapWindow:
+ case X_UnmapSubwindows:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_WINDOW,
+ WINDOW__ENUMERATE | WINDOW__GETATTR |
+ WINDOW__UNMAP);
+ break;
+ case X_WarpPointer:
+ rval = IDPERM(client, xWarpPointerReq, srcWid,
+ SECCLASS_WINDOW, WINDOW__GETATTR)
+ && IDPERM(client, xWarpPointerReq, dstWid,
+ SECCLASS_WINDOW, WINDOW__GETATTR)
+ && ServerPerm(client, SECCLASS_XINPUT, XINPUT__WARPPOINTER);
+ break;
+
+ /* Input class control requirements */
+ case X_GrabButton:
+ case X_GrabKey:
+ rval = ServerPerm(client, SECCLASS_XINPUT, XINPUT__PASSIVEGRAB);
+ break;
+ case X_GrabKeyboard:
+ case X_GrabPointer:
+ case X_ChangeActivePointerGrab:
+ rval = ServerPerm(client, SECCLASS_XINPUT, XINPUT__ACTIVEGRAB);
+ break;
+ case X_AllowEvents:
+ case X_UngrabButton:
+ case X_UngrabKey:
+ case X_UngrabKeyboard:
+ case X_UngrabPointer:
+ rval = ServerPerm(client, SECCLASS_XINPUT, XINPUT__UNGRAB);
+ break;
+ case X_GetKeyboardControl:
+ case X_GetKeyboardMapping:
+ case X_GetPointerControl:
+ case X_GetPointerMapping:
+ case X_GetModifierMapping:
+ case X_QueryKeymap:
+ case X_QueryPointer:
+ rval = ServerPerm(client, SECCLASS_XINPUT, XINPUT__GETATTR);
+ break;
+ case X_ChangeKeyboardControl:
+ case X_ChangePointerControl:
+ case X_ChangeKeyboardMapping:
+ case X_SetModifierMapping:
+ case X_SetPointerMapping:
+ rval = ServerPerm(client, SECCLASS_XINPUT, XINPUT__SETATTR);
+ break;
+ case X_Bell:
+ rval = ServerPerm(client, SECCLASS_XINPUT, XINPUT__BELL);
+ break;
+
+ /* Colormap class control requirements */
+ case X_AllocColor:
+ case X_AllocColorCells:
+ case X_AllocColorPlanes:
+ case X_AllocNamedColor:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_COLORMAP,
+ COLORMAP__READ | COLORMAP__STORE);
+ break;
+ case X_CopyColormapAndFree:
+ rval = IDPERM(client, xCopyColormapAndFreeReq, mid,
+ SECCLASS_COLORMAP, COLORMAP__CREATE)
+ && IDPERM(client, xCopyColormapAndFreeReq, srcCmap,
+ SECCLASS_COLORMAP,
+ COLORMAP__READ | COLORMAP__FREE);
+ break;
+ case X_CreateColormap:
+ rval = IDPERM(client, xCreateColormapReq, mid,
+ SECCLASS_COLORMAP, COLORMAP__CREATE)
+ && IDPERM(client, xCreateColormapReq, window,
+ SECCLASS_DRAWABLE, DRAWABLE__DRAW);
+ break;
+ case X_FreeColormap:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_COLORMAP, COLORMAP__FREE);
+ break;
+ case X_FreeColors:
+ rval = IDPERM(client, xFreeColorsReq, cmap,
+ SECCLASS_COLORMAP, COLORMAP__STORE);
+ break;
+ case X_InstallColormap:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_COLORMAP, COLORMAP__INSTALL)
+ && ServerPerm(client, SECCLASS_COLORMAP, COLORMAP__INSTALL);
+ break;
+ case X_ListInstalledColormaps:
+ rval = ServerPerm(client, SECCLASS_COLORMAP, COLORMAP__LIST);
+ break;
+ case X_LookupColor:
+ case X_QueryColors:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_COLORMAP, COLORMAP__READ);
+ break;
+ case X_StoreColors:
+ case X_StoreNamedColor:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_COLORMAP, COLORMAP__STORE);
+ break;
+ case X_UninstallColormap:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_COLORMAP, COLORMAP__UNINSTALL)
+ && ServerPerm(client, SECCLASS_COLORMAP, COLORMAP__UNINSTALL);
+ break;
+
+ /* Font class control requirements */
+ case X_CloseFont:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_FONT, FONT__FREE);
+ break;
+ case X_ImageText8:
+ case X_ImageText16:
+ /* Font accesses checked through the resource manager */
+ rval = IDPERM(client, xImageTextReq, drawable,
+ SECCLASS_DRAWABLE, DRAWABLE__DRAW);
+ break;
+ case X_OpenFont:
+ rval = ServerPerm(client, SECCLASS_FONT, FONT__LOAD)
+ && IDPERM(client, xOpenFontReq, fid,
+ SECCLASS_FONT, FONT__USE);
+ break;
+ case X_PolyText8:
+ case X_PolyText16:
+ /* Font accesses checked through the resource manager */
+ rval = ServerPerm(client, SECCLASS_FONT, FONT__LOAD)
+ && IDPERM(client, xPolyTextReq, gc,
+ SECCLASS_GC, GC__SETATTR)
+ && IDPERM(client, xPolyTextReq, drawable,
+ SECCLASS_DRAWABLE, DRAWABLE__DRAW);
+ break;
+
+ /* Pixmap class control requirements */
+ case X_CreatePixmap:
+ rval = IDPERM(client, xCreatePixmapReq, pid,
+ SECCLASS_DRAWABLE, DRAWABLE__CREATE);
+ break;
+ case X_FreePixmap:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_DRAWABLE, DRAWABLE__DESTROY);
+ break;
+
+ /* Cursor class control requirements */
+ case X_CreateCursor:
+ rval = IDPERM(client, xCreateCursorReq, cid,
+ SECCLASS_CURSOR, CURSOR__CREATE)
+ && IDPERM(client, xCreateCursorReq, source,
+ SECCLASS_DRAWABLE, DRAWABLE__DRAW)
+ && IDPERM(client, xCreateCursorReq, mask,
+ SECCLASS_DRAWABLE, DRAWABLE__COPY);
+ break;
+ case X_CreateGlyphCursor:
+ rval = IDPERM(client, xCreateGlyphCursorReq, cid,
+ SECCLASS_CURSOR, CURSOR__CREATEGLYPH)
+ && IDPERM(client, xCreateGlyphCursorReq, source,
+ SECCLASS_FONT, FONT__USE)
+ && IDPERM(client, xCreateGlyphCursorReq, mask,
+ SECCLASS_FONT, FONT__USE);
+ break;
+ case X_RecolorCursor:
+ rval = IDPERM(client, xRecolorCursorReq, cursor,
+ SECCLASS_CURSOR, CURSOR__SETATTR);
+ break;
+ case X_FreeCursor:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_CURSOR, CURSOR__FREE);
+ break;
+
+ /* GC class control requirements */
+ case X_CreateGC:
+ rval = IDPERM(client, xCreateGCReq, gc,
+ SECCLASS_GC, GC__CREATE | GC__SETATTR);
+ break;
+ case X_ChangeGC:
+ case X_SetDashes:
+ case X_SetClipRectangles:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_GC, GC__SETATTR);
+ break;
+ case X_CopyGC:
+ rval = IDPERM(client, xCopyGCReq, srcGC,
+ SECCLASS_GC, GC__GETATTR)
+ && IDPERM(client, xCopyGCReq, dstGC,
+ SECCLASS_GC, GC__SETATTR);
+ break;
+ case X_FreeGC:
+ rval = IDPERM(client, xResourceReq, id,
+ SECCLASS_GC, GC__FREE);
+ break;
+
+ /* Server class control requirements */
+ case X_GrabServer:
+ rval = ServerPerm(client, SECCLASS_XSERVER, XSERVER__GRAB);
+ break;
+ case X_UngrabServer:
+ rval = ServerPerm(client, SECCLASS_XSERVER, XSERVER__UNGRAB);
+ break;
+ case X_ForceScreenSaver:
+ case X_GetScreenSaver:
+ case X_SetScreenSaver:
+ rval = ServerPerm(client, SECCLASS_XSERVER, XSERVER__SCREENSAVER);
+ break;
+ case X_ListHosts:
+ rval = ServerPerm(client, SECCLASS_XSERVER, XSERVER__GETHOSTLIST);
+ break;
+ case X_ChangeHosts:
+ case X_SetAccessControl:
+ rval = ServerPerm(client, SECCLASS_XSERVER, XSERVER__SETHOSTLIST);
+ break;
+ case X_GetFontPath:
+ rval = ServerPerm(client, SECCLASS_XSERVER, XSERVER__GETFONTPATH);
+ break;
+ case X_SetFontPath:
+ rval = ServerPerm(client, SECCLASS_XSERVER, XSERVER__SETFONTPATH);
+ break;
+ case X_QueryBestSize:
+ rval = ServerPerm(client, SECCLASS_XSERVER, XSERVER__GETATTR);
+ break;
+
+ default:
+ rval = TRUE;
+ break;
+ }
+ if (!rval)
+ rec->rval = FALSE;
+}
+
+CALLBACK(XSELinuxExtDispatch)
+{
+ XaceExtAccessRec *rec = (XaceExtAccessRec*)calldata;
+ ClientPtr client = rec->client;
+ ExtensionEntry *ext = rec->ext;
+ security_id_t extsid;
+ access_vector_t perm;
+ REQUEST(xReq);
+
+ /* XXX there should be a separate callback for this */
+ if (!EXTENSIONSID(ext))
+ {
+ extsid = ObjectSIDByLabel(NULL, SECCLASS_XEXTENSION, ext->name);
+ if (!extsid)
+ return;
+ EXTENSIONSID(ext) = extsid;
+ }
+
+ extsid = (security_id_t)EXTENSIONSID(ext);
+ perm = ((stuff->reqType == X_QueryExtension) ||
+ (stuff->reqType == X_ListExtensions)) ?
+ XEXTENSION__QUERY : XEXTENSION__USE;
+
+ if (HAVESTATE(client))
+ {
+ XSELinuxAuditRec auditdata;
+ auditdata.client = client;
+ auditdata.property = NULL;
+ auditdata.extension = ext->name;
+ errno = 0;
+ if (avc_has_perm(SID(client), extsid, SECCLASS_XEXTENSION,
+ perm, &AEREF(client), &auditdata) < 0)
+ {
+ if (errno != EACCES)
+ ErrorF("ExtDispatch: unexpected error %d\n", errno);
+ rec->rval = FALSE;
+ }
+ } else
+ ErrorF("No client state in extension dispatcher!\n");
+} /* XSELinuxExtDispatch */
+
+CALLBACK(XSELinuxProperty)
+{
+ XacePropertyAccessRec *rec = (XacePropertyAccessRec*)calldata;
+ WindowPtr pWin = rec->pWin;
+ ClientPtr client = rec->client;
+ ClientPtr tclient;
+ access_vector_t perm = 0;
+ security_id_t propsid;
+ char *propname = NameForAtom(rec->propertyName);
+
+ tclient = wClient(pWin);
+ if (!tclient || !HAVESTATE(tclient))
+ return;
+
+ propsid = ObjectSIDByLabel(SID(tclient)->ctx, SECCLASS_PROPERTY, propname);
+ if (!propsid)
+ return;
+
+ if (rec->access_mode & SecurityReadAccess)
+ perm |= PROPERTY__READ;
+ if (rec->access_mode & SecurityWriteAccess)
+ perm |= PROPERTY__WRITE;
+ if (rec->access_mode & SecurityDestroyAccess)
+ perm |= PROPERTY__FREE;
+ if (!rec->access_mode)
+ perm = PROPERTY__READ | PROPERTY__WRITE | PROPERTY__FREE;
+
+ if (HAVESTATE(client))
+ {
+ XSELinuxAuditRec auditdata;
+ auditdata.client = client;
+ auditdata.property = propname;
+ auditdata.extension = NULL;
+ errno = 0;
+ if (avc_has_perm(SID(client), propsid, SECCLASS_PROPERTY,
+ perm, &AEREF(client), &auditdata) < 0)
+ {
+ if (errno != EACCES)
+ ErrorF("Property: unexpected error %d\n", errno);
+ rec->rval = SecurityIgnoreOperation;
+ }
+ } else
+ ErrorF("No client state in property callback!\n");
+
+ /* XXX this should be saved in the property structure */
+ sidput(propsid);
+} /* XSELinuxProperty */
+
+CALLBACK(XSELinuxResLookup)
+{
+ XaceResourceAccessRec *rec = (XaceResourceAccessRec*)calldata;
+ ClientPtr client = rec->client;
+ REQUEST(xReq);
+ access_vector_t perm = 0;
+ Bool rval = TRUE;
+
+ /* serverClient requests OK */
+ if (client->index == 0)
+ return;
+
+ switch(rec->rtype) {
+ case RT_FONT: {
+ switch(stuff->reqType) {
+ case X_ImageText8:
+ case X_ImageText16:
+ case X_PolyText8:
+ case X_PolyText16:
+ perm = FONT__USE;
+ break;
+ case X_ListFonts:
+ case X_ListFontsWithInfo:
+ case X_QueryFont:
+ case X_QueryTextExtents:
+ perm = FONT__GETATTR;
+ break;
+ default:
+ break;
+ }
+ if (perm)
+ rval = IDPerm(client, rec->id, SECCLASS_FONT, perm);
+ break;
+ }
+ default:
+ break;
+ }
+ if (!rval)
+ rec->rval = FALSE;
+} /* XSELinuxResLookup */
+
+CALLBACK(XSELinuxMap)
+{
+ XaceMapAccessRec *rec = (XaceMapAccessRec*)calldata;
+ if (!IDPerm(rec->client, rec->pWin->drawable.id,
+ SECCLASS_WINDOW, WINDOW__MAP))
+ rec->rval = FALSE;
+} /* XSELinuxMap */
+
+CALLBACK(XSELinuxBackgrnd)
+{
+ XaceMapAccessRec *rec = (XaceMapAccessRec*)calldata;
+ if (!IDPerm(rec->client, rec->pWin->drawable.id,
+ SECCLASS_WINDOW, WINDOW__TRANSPARENT))
+ rec->rval = FALSE;
+} /* XSELinuxBackgrnd */
+
+CALLBACK(XSELinuxDrawable)
+{
+ XaceDrawableAccessRec *rec = (XaceDrawableAccessRec*)calldata;
+ if (!IDPerm(rec->client, rec->pDraw->id,
+ SECCLASS_DRAWABLE, DRAWABLE__COPY))
+ rec->rval = FALSE;
+} /* XSELinuxDrawable */
+
+CALLBACK(XSELinuxHostlist)
+{
+ XaceHostlistAccessRec *rec = (XaceHostlistAccessRec*)calldata;
+ access_vector_t perm = (rec->access_mode == SecurityReadAccess) ?
+ XSERVER__GETHOSTLIST : XSERVER__SETHOSTLIST;
+
+ if (!ServerPerm(rec->client, SECCLASS_XSERVER, perm))
+ rec->rval = FALSE;
+} /* XSELinuxHostlist */
+
+/* Extension callbacks */
+CALLBACK(XSELinuxClientState)
+{
+ NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
+ ClientPtr client = pci->client;
+
+ switch(client->clientState)
+ {
+ case ClientStateInitial:
+ AssignClientState(serverClient);
+ break;
+
+ case ClientStateRunning:
+ {
+ AssignClientState(client);
+ break;
+ }
+ case ClientStateGone:
+ case ClientStateRetained:
+ {
+ FreeClientState(client);
+ break;
+ }
+ default: break;
+ }
+} /* XSELinuxClientState */
+
+static char *XSELinuxKeywords[] = {
+#define XSELinuxKeywordComment 0
+ "#",
+#define XSELinuxKeywordProperty 1
+ "property",
+#define XSELinuxKeywordExtension 2
+ "extension",
+#define XSELinuxKeywordNonlocalContext 3
+ "nonlocal_context",
+#define XSELinuxKeywordRootWindowContext 4
+ "root_window_context",
+#define XSELinuxKeywordDefault 5
+ "default"
+};
+
+#define NUMKEYWORDS (sizeof(XSELinuxKeywords) / sizeof(char *))
+
+#ifndef __UNIXOS2__
+#define XSELinuxIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') )
+#else
+#define XSELinuxIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r') )
+#endif
+
+static char *
+XSELinuxSkipWhitespace(
+ char *p)
+{
+ while (XSELinuxIsWhitespace(*p))
+ p++;
+ return p;
+} /* XSELinuxSkipWhitespace */
+
+static char *
+XSELinuxParseString(
+ char **rest)
+{
+ char *startOfString;
+ char *s = *rest;
+ char endChar = 0;
+
+ s = XSELinuxSkipWhitespace(s);
+
+ if (*s == '"' || *s == '\'')
+ {
+ endChar = *s++;
+ startOfString = s;
+ while (*s && (*s != endChar))
+ s++;
+ }
+ else
+ {
+ startOfString = s;
+ while (*s && !XSELinuxIsWhitespace(*s))
+ s++;
+ }
+ if (*s)
+ {
+ *s = '\0';
+ *rest = s + 1;
+ return startOfString;
+ }
+ else
+ {
+ *rest = s;
+ return (endChar) ? NULL : startOfString;
+ }
+} /* XSELinuxParseString */
+
+static int
+XSELinuxParseKeyword(
+ char **p)
+{
+ int i;
+ char *s = *p;
+ s = XSELinuxSkipWhitespace(s);
+ for (i = 0; i < NUMKEYWORDS; i++)
+ {
+ int len = strlen(XSELinuxKeywords[i]);
+ if (strncmp(s, XSELinuxKeywords[i], len) == 0)
+ {
+ *p = s + len;
+ return (i);
+ }
+ }
+ *p = s;
+ return -1;
+} /* XSELinuxParseKeyword */
+
+static Bool
+XSELinuxTypeIsValid(char *typename)
+{
+ security_context_t base, new;
+ context_t con;
+ Bool ret = FALSE;
+
+ /* get the server's context */
+ if (getcon(&base) < 0)
+ goto out;
+
+ /* make a new context-manipulation object */
+ con = context_new(base);
+ if (!con)
+ goto out_free;
+
+ /* set the role */
+ if (context_role_set(con, "object_r"))
+ goto out_free2;
+
+ /* set the type */
+ if (context_type_set(con, typename))
+ goto out_free2;
+
+ /* get a context string - note: context_str() returns a pointer
+ * to the string inside the context; the returned pointer should
+ * not be freed
+ */
+ new = context_str(con);
+ if (!new)
+ goto out_free2;
+
+ /* finally, check to see if it's valid */
+ if (security_check_context(new) == 0)
+ ret = TRUE;
+
+out_free2:
+ context_free(con);
+out_free:
+ freecon(base);
+out:
+ return ret;
+}
+
+static Bool
+XSELinuxParsePropertyTypeRule(char *p)
+{
+ int keyword;
+ char *propname = NULL, *propcopy = NULL;
+ char *typename = NULL, *typecopy = NULL;
+ char **newTypes;
+ Bool defaultPropertyType = FALSE;
+
+ /* get property name */
+ keyword = XSELinuxParseKeyword(&p);
+ if (keyword == XSELinuxKeywordDefault)
+ {
+ defaultPropertyType = TRUE;
+ }
+ else
+ {
+ propname = XSELinuxParseString(&p);
+ if (!propname || (strlen(propname) == 0))
+ {
+ return FALSE;
+ }
+ }
+
+ /* get the SELinux type corresponding to the property */
+ typename = XSELinuxParseString(&p);
+ if (!typename || (strlen(typename) == 0))
+ return FALSE;
+
+ /* validate the type */
+ if (XSELinuxTypeIsValid(typename) != TRUE)
+ return FALSE;
+
+ /* if it's the default property, save it to append to the end of the
+ * property types list
+ */
+ if (defaultPropertyType == TRUE)
+ {
+ if (XSELinuxPropertyTypeDefault != NULL)
+ {
+ return FALSE;
+ }
+ else
+ {
+ XSELinuxPropertyTypeDefault = (char *)xalloc(strlen(typename)+1);
+ if (!XSELinuxPropertyTypeDefault)
+ {
+ ErrorF("XSELinux: out of memory\n");
+ return FALSE;
+ }
+ strcpy(XSELinuxPropertyTypeDefault, typename);
+ return TRUE;
+ }
+ }
+
+ /* insert the property and type into the propertyTypes array */
+ propcopy = (char *)xalloc(strlen(propname)+1);
+ if (!propcopy)
+ {
+ ErrorF("XSELinux: out of memory\n");
+ return FALSE;
+ }
+ strcpy(propcopy, propname);
+
+ typecopy = (char *)xalloc(strlen(typename)+1);
+ if (!typecopy)
+ {
+ ErrorF("XSELinux: out of memory\n");
+ xfree(propcopy);
+ return FALSE;
+ }
+ strcpy(typecopy, typename);
+
+ newTypes = (char **)xrealloc(propertyTypes, sizeof (char *) * ((propertyTypesCount+1) * 2));
+ if (!newTypes)
+ {
+ ErrorF("XSELinux: out of memory\n");
+ xfree(propcopy);
+ xfree(typecopy);
+ return FALSE;
+ }
+
+ propertyTypesCount++;
+
+ newTypes[propertyTypesCount*2 - 2] = propcopy;
+ newTypes[propertyTypesCount*2 - 1] = typecopy;
+
+ propertyTypes = newTypes;
+
+ return TRUE;
+} /* XSELinuxParsePropertyTypeRule */
+
+static Bool
+XSELinuxParseExtensionTypeRule(char *p)
+{
+ int keyword;
+ char *extname = NULL, *extcopy = NULL;
+ char *typename = NULL, *typecopy = NULL;
+ char **newTypes;
+ Bool defaultExtensionType = FALSE;
+
+ /* get extension name */
+ keyword = XSELinuxParseKeyword(&p);
+ if (keyword == XSELinuxKeywordDefault)
+ {
+ defaultExtensionType = TRUE;
+ }
+ else
+ {
+ extname = XSELinuxParseString(&p);
+ if (!extname || (strlen(extname) == 0))
+ {
+ return FALSE;
+ }
+ }
+
+ /* get the SELinux type corresponding to the extension */
+ typename = XSELinuxParseString(&p);
+ if (!typename || (strlen(typename) == 0))
+ return FALSE;
+
+ /* validate the type */
+ if (XSELinuxTypeIsValid(typename) != TRUE)
+ return FALSE;
+
+ /* if it's the default extension, save it to append to the end of the
+ * extension types list
+ */
+ if (defaultExtensionType == TRUE)
+ {
+ if (XSELinuxExtensionTypeDefault != NULL)
+ {
+ return FALSE;
+ }
+ else
+ {
+ XSELinuxExtensionTypeDefault = (char *)xalloc(strlen(typename)+1);
+ if (!XSELinuxExtensionTypeDefault)
+ {
+ ErrorF("XSELinux: out of memory\n");
+ return FALSE;
+ }
+ strcpy(XSELinuxExtensionTypeDefault, typename);
+ return TRUE;
+ }
+ }
+
+ /* insert the extension and type into the extensionTypes array */
+ extcopy = (char *)xalloc(strlen(extname)+1);
+ if (!extcopy)
+ {
+ ErrorF("XSELinux: out of memory\n");
+ return FALSE;
+ }
+ strcpy(extcopy, extname);
+
+ typecopy = (char *)xalloc(strlen(typename)+1);
+ if (!typecopy)
+ {
+ ErrorF("XSELinux: out of memory\n");
+ xfree(extcopy);
+ return FALSE;
+ }
+ strcpy(typecopy, typename);
+
+ newTypes = (char **)xrealloc(extensionTypes, sizeof(char *) *( (extensionTypesCount+1) * 2));
+ if (!newTypes)
+ {
+ ErrorF("XSELinux: out of memory\n");
+ xfree(extcopy);
+ xfree(typecopy);
+ return FALSE;
+ }
+
+ extensionTypesCount++;
+
+ newTypes[extensionTypesCount*2 - 2] = extcopy;
+ newTypes[extensionTypesCount*2 - 1] = typecopy;
+
+ extensionTypes = newTypes;
+
+ return TRUE;
+} /* XSELinuxParseExtensionTypeRule */
+
+static Bool
+XSELinuxParseNonlocalContext(char *p)
+{
+ char *context;
+
+ context = XSELinuxParseString(&p);
+ if (!context || (strlen(context) == 0))
+ {
+ return FALSE;
+ }
+
+ if (XSELinuxNonlocalContextDefault != NULL)
+ {
+ return FALSE;
+ }
+
+ /* validate the context */
+ if (security_check_context(context))
+ {
+ return FALSE;
+ }
+
+ XSELinuxNonlocalContextDefault = (char *)xalloc(strlen(context)+1);
+ if (!XSELinuxNonlocalContextDefault)
+ {
+ ErrorF("XSELinux: out of memory\n");
+ return FALSE;
+ }
+ strcpy(XSELinuxNonlocalContextDefault, context);
+
+ return TRUE;
+} /* XSELinuxParseNonlocalContext */
+
+static Bool
+XSELinuxParseRootWindowContext(char *p)
+{
+ char *context;
+
+ context = XSELinuxParseString(&p);
+ if (!context || (strlen(context) == 0))
+ {
+ return FALSE;
+ }
+
+ if (XSELinuxRootWindowContext != NULL)
+ {
+ return FALSE;
+ }
+
+ /* validate the context */
+ if (security_check_context(context))
+ {
+ return FALSE;
+ }
+
+ XSELinuxRootWindowContext = (char *)xalloc(strlen(context)+1);
+ if (!XSELinuxRootWindowContext)
+ {
+ ErrorF("XSELinux: out of memory\n");
+ return FALSE;
+ }
+ strcpy(XSELinuxRootWindowContext, context);
+
+ return TRUE;
+} /* XSELinuxParseRootWindowContext */
+
+static Bool
+XSELinuxLoadConfigFile(void)
+{
+ FILE *f;
+ int lineNumber = 0;
+ char **newTypes;
+ Bool ret = FALSE;
+
+ if (!XSELINUXCONFIGFILE)
+ return FALSE;
+
+ /* some initial bookkeeping */
+ propertyTypesCount = extensionTypesCount = 0;
+ propertyTypes = extensionTypes = NULL;
+ XSELinuxPropertyTypeDefault = XSELinuxExtensionTypeDefault = NULL;
+ XSELinuxNonlocalContextDefault = NULL;
+ XSELinuxRootWindowContext = NULL;
+
+#ifndef __UNIXOS2__
+ f = fopen(XSELINUXCONFIGFILE, "r");
+#else
+ f = fopen((char*)__XOS2RedirRoot(XSELINUXCONFIGFILE), "r");
+#endif
+ if (!f)
+ {
+ ErrorF("Error opening XSELinux policy file %s\n", XSELINUXCONFIGFILE);
+ return FALSE;
+ }
+
+ while (!feof(f))
+ {
+ char buf[200];
+ Bool validLine;
+ char *p;
+
+ if (!(p = fgets(buf, sizeof(buf), f)))
+ break;
+ lineNumber++;
+
+ switch (XSELinuxParseKeyword(&p))
+ {
+ case XSELinuxKeywordComment:
+ validLine = TRUE;
+ break;
+
+ case XSELinuxKeywordProperty:
+ validLine = XSELinuxParsePropertyTypeRule(p);
+ break;
+
+ case XSELinuxKeywordExtension:
+ validLine = XSELinuxParseExtensionTypeRule(p);
+ break;
+
+ case XSELinuxKeywordNonlocalContext:
+ validLine = XSELinuxParseNonlocalContext(p);
+ break;
+
+ case XSELinuxKeywordRootWindowContext:
+ validLine = XSELinuxParseRootWindowContext(p);
+ break;
+
+ default:
+ validLine = (*p == '\0');
+ break;
+ }
+
+ if (!validLine)
+ {
+ ErrorF("XSELinux: Line %d of %s is invalid\n",
+ lineNumber, XSELINUXCONFIGFILE);
+ goto out;
+ }
+ }
+
+ /* check to make sure the default types and the nonlocal context
+ * were specified
+ */
+ if (XSELinuxPropertyTypeDefault == NULL)
+ {
+ ErrorF("XSELinux: No default property type specified\n");
+ goto out;
+ }
+ else if (XSELinuxExtensionTypeDefault == NULL)
+ {
+ ErrorF("XSELinux: No default extension type specified\n");
+ goto out;
+ }
+ else if (XSELinuxNonlocalContextDefault == NULL)
+ {
+ ErrorF("XSELinux: No default context for non-local clients specified\n");
+ goto out;
+ }
+ else if (XSELinuxRootWindowContext == NULL)
+ {
+ ErrorF("XSELinux: No context specified for the root window\n");
+ goto out;
+ }
+
+ /* Finally, append the default property and extension types to the
+ * bottoms of the propertyTypes and extensionTypes arrays, respectively.
+ * The 'name' of the property / extension is NULL.
+ */
+ newTypes = (char **)xrealloc(propertyTypes, sizeof(char *) *((propertyTypesCount+1) * 2));
+ if (!newTypes)
+ {
+ ErrorF("XSELinux: out of memory\n");
+ goto out;
+ }
+ propertyTypesCount++;
+ newTypes[propertyTypesCount*2 - 2] = NULL;
+ newTypes[propertyTypesCount*2 - 1] = XSELinuxPropertyTypeDefault;
+ propertyTypes = newTypes;
+
+ newTypes = (char **)xrealloc(extensionTypes, sizeof(char *) *((extensionTypesCount+1) * 2));
+ if (!newTypes)
+ {
+ ErrorF("XSELinux: out of memory\n");
+ goto out;
+ }
+ extensionTypesCount++;
+ newTypes[extensionTypesCount*2 - 2] = NULL;
+ newTypes[extensionTypesCount*2 - 1] = XSELinuxExtensionTypeDefault;
+ extensionTypes = newTypes;
+
+ ret = TRUE;
+
+out:
+ fclose(f);
+ return ret;
+} /* XSELinuxLoadConfigFile */
+
+static void
+XSELinuxFreeConfigData(void)
+{
+ char **ptr;
+
+ /* Free all the memory in the table until we reach the NULL, then
+ * skip one past the NULL and free the default type. Then take care
+ * of some bookkeeping.
+ */
+ for (ptr = propertyTypes; *ptr; ptr++)
+ xfree(*ptr);
+ ptr++;
+ xfree(*ptr);
+
+ XSELinuxPropertyTypeDefault = NULL;
+ propertyTypesCount = 0;
+
+ xfree(propertyTypes);
+ propertyTypes = NULL;
+
+ /* ... and the same for the extension type table */
+ for (ptr = extensionTypes; *ptr; ptr++)
+ xfree(*ptr);
+ ptr++;
+ xfree(*ptr);
+
+ XSELinuxExtensionTypeDefault = NULL;
+ extensionTypesCount = 0;
+
+ xfree(extensionTypes);
+ extensionTypes = NULL;
+
+ /* finally, take care of the context for non-local connections */
+ xfree(XSELinuxNonlocalContextDefault);
+ XSELinuxNonlocalContextDefault = NULL;
+
+ /* ... and for the root window */
+ xfree(XSELinuxRootWindowContext);
+ XSELinuxRootWindowContext = NULL;
+} /* XSELinuxFreeConfigData */
+
+/* Extension dispatch functions */
+static int
+ProcXSELinuxDispatch(ClientPtr client)
+{
+ return BadRequest;
+} /* ProcXSELinuxDispatch */
+
+static void
+XSELinuxResetProc(ExtensionEntry *extEntry)
+{
+ FreeClientState(serverClient);
+
+ XSELinuxFreeConfigData();
+
+ audit_close(audit_fd);
+
+ avc_destroy();
+} /* XSELinuxResetProc */
+
+static void
+XSELinuxAVCAudit(void *auditdata,
+ security_class_t class,
+ char *msgbuf,
+ size_t msgbufsize)
+{
+ XSELinuxAuditRec *audit = (XSELinuxAuditRec*)auditdata;
+ ClientPtr client = audit->client;
+ char requestNum[8];
+ REQUEST(xReq);
+
+ if (stuff)
+ snprintf(requestNum, 8, "%d", stuff->reqType);
+
+ snprintf(msgbuf, msgbufsize, "%s%s%s%s%s%s",
+ stuff ? "request=" : "",
+ stuff ? requestNum : "",
+ audit->property ? " property=" : "",
+ audit->property ? audit->property : "",
+ audit->extension ? " extension=" : "",
+ audit->extension ? audit->extension : "");
+}
+
+static void
+XSELinuxAVCLog(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ VErrorF(fmt, ap);
+ va_end(ap);
+}
+
+/* XSELinuxExtensionSetup
+ *
+ * Set up the XSELinux Extension (pre-init)
+ */
+void
+XSELinuxExtensionSetup(INITARGS)
+{
+ /* Allocate the client private index */
+ clientPrivateIndex = AllocateClientPrivateIndex();
+ if (!AllocateClientPrivate(clientPrivateIndex,
+ sizeof (XSELinuxClientStateRec)))
+ FatalError("XSELinux: Failed to allocate client private.\n");
+
+ /* Allocate the extension private index */
+ extnsnPrivateIndex = AllocateExtensionPrivateIndex();
+ if (!AllocateExtensionPrivate(extnsnPrivateIndex, 0))
+ FatalError("XSELinux: Failed to allocate extension private.\n");
+}
+
+/* XSELinuxExtensionInit
+ *
+ * Initialize the XSELinux Extension
+ */
+void
+XSELinuxExtensionInit(INITARGS)
+{
+ ExtensionEntry *extEntry;
+ struct avc_log_callback alc = {XSELinuxAVCLog, XSELinuxAVCAudit};
+
+ if (!is_selinux_enabled())
+ {
+ ErrorF("SELinux Extension failed to load: SELinux not enabled\n");
+ return;
+ }
+
+ if (avc_init("xserver", NULL, &alc, NULL, NULL) < 0)
+ {
+ FatalError("couldn't initialize SELinux userspace AVC\n");
+ }
+
+ if (!AddCallback(&ClientStateCallback, XSELinuxClientState, NULL))
+ return;
+
+ /* Load the config file. If this fails, shut down the server,
+ * since an unknown security status is worse than no security.
+ *
+ * Note that this must come before we assign a security state
+ * for the serverClient, because the serverClient's root windows
+ * are assigned a context based on data in the config file.
+ */
+ if (XSELinuxLoadConfigFile() != TRUE)
+ {
+ FatalError("XSELinux: Failed to load security policy\n");
+ }
+
+ /* prepare for auditing */
+ audit_fd = audit_open();
+ if (audit_fd < 0)
+ {
+ FatalError("XSELinux: Failed to open the system audit log\n");
+ }
+
+ /* register security callbacks */
+ XaceRegisterCallback(XACE_CORE_DISPATCH, XSELinuxCoreDispatch, NULL);
+ XaceRegisterCallback(XACE_EXT_ACCESS, XSELinuxExtDispatch, NULL);
+ XaceRegisterCallback(XACE_EXT_DISPATCH, XSELinuxExtDispatch, NULL);
+ XaceRegisterCallback(XACE_RESOURCE_ACCESS, XSELinuxResLookup, NULL);
+ XaceRegisterCallback(XACE_MAP_ACCESS, XSELinuxMap, NULL);
+ XaceRegisterCallback(XACE_HOSTLIST_ACCESS, XSELinuxHostlist, NULL);
+ XaceRegisterCallback(XACE_BACKGRND_ACCESS, XSELinuxBackgrnd, NULL);
+ XaceRegisterCallback(XACE_DRAWABLE_ACCESS, XSELinuxDrawable, NULL);
+ XaceRegisterCallback(XACE_PROPERTY_ACCESS, XSELinuxProperty, NULL);
+ /* XaceRegisterCallback(XACE_DECLARE_EXT_SECURE, XSELinuxDeclare, NULL);
+ XaceRegisterCallback(XACE_DEVICE_ACCESS, XSELinuxDevice, NULL); */
+
+ /* register extension with server */
+ extEntry = AddExtension(XSELINUX_EXTENSION_NAME,
+ XSELinuxNumberEvents, XSELinuxNumberErrors,
+ ProcXSELinuxDispatch, ProcXSELinuxDispatch,
+ XSELinuxResetProc, StandardMinorOpcode);
+}
diff --git a/Xext/xselinux.h b/Xext/xselinux.h
new file mode 100644
index 0000000..eff6db5
--- /dev/null
+++ b/Xext/xselinux.h
@@ -0,0 +1,29 @@
+/************************************************************
+
+Author: Eamon Walsh <ewalsh at epoch.ncsc.mil>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+this permission notice appear in supporting documentation. This permission
+notice shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+********************************************************/
+
+#ifndef _XSELINUX_H
+#define _XSELINUX_H
+
+#define XSELINUX_EXTENSION_NAME "SELinux"
+#define XSELINUX_MAJOR_VERSION 1
+#define XSELINUX_MINOR_VERSION 0
+#define XSELinuxNumberEvents 0
+#define XSELinuxNumberErrors 0
+
+#endif /* _XSELINUX_H */
More information about the xorg-commit
mailing list