[PATCH] Xorg in a jail

Tom Evans tevans.uk at googlemail.com
Sun Mar 9 01:26:43 UTC 2014


I've been reinstalling my home server with 10-STABLE and wanted to
compartmentalise all the disparate tasks it does - file storage, DNS,
web servers and mplayer/xorg/media stuff in general - in to a separate
jail for each task.

For the most part, this was quite straightforward, apart from with
xorg I found that it wasn't quite supported. I found Alexander's
patch, and the work Jamie did in part integrating it, allowing kmem
read, and reworked it for 10-STABLE.

>From Jamie's emails it looked like he was working on a way of properly
integrating these permissions in a more unified way, but I had a
pressing need :)

I've tested this on 10-STABLE r262457M, intel graphics (ivy bridge,
WITH_NEW_XORG), and everything seems to work just fine. I'm going to
try out radeonkms and nvidia tomorrow also.

Also please note that whilst I want things jailed for separation and
neatness concerns rather than security, it must be pointed out that
letting one jail read and write kernel memory of the whole machine is
not at all secure! Anyone with root in this xorg jail would be able to
break free of the jail.

I'm not sure I did the jail allow parameters right, but it works for
me - I would appreciate someone more competent taking a look! Also,
dev_io_access should probably be renamed or using it to control access
to /dev/mem split out from it? Also, is the style right? vim: noet
sw=8 ts=8 is what I was using.

Cheers

Tom

PS: I haven't tested any input devices yet with this, let me know!

Instructions:

Apply patch, rebuild world and kernel, install and update jails/basejails

Create /etc/devfs.rules to unhide the pertinent devices and restart devfs
This is what I am using, it might be overkill...

  [devfsrules_unhide_xorg=8]
  add include $devfsrules_hide_all
  add include $devfsrules_unhide_basic
  add include $devfsrules_unhide_login
  add path agpgart unhide
  add path console unhide
  add path consolectl unhide
  add path dri unhide
  add path 'dri/*' unhide
  add path io unhide
  add path mem unhide
  add path pci unhide
  add path tty unhide
  add path ttyv0 unhide
  add path ttyv1 unhide
  add path ttyv8 unhide

Set sysctls on jail host to allow jails to have permission granted to
them to access (in particular) /dev/mem, /dev/io and /dev/dri/*

  security.jail.dev_io_access=1
  security.jail.dev_dri_access=1

Configure your chosen jail to use these devfs rules and allow them to
use the devices. I use ezjail, so for me this meant changing
/usr/local/etc/ezjail/<name_of_jail> and setting these lines:

  export jail_xorg_foo_com_devfs_ruleset="8"
  export jail_xorg_foo_com_parameters="allow.dev_io_access=1
allow.dev_dri_access=1"

Load any required kernel modules in the jail host - xorg in the jail
will not be able to load them for you. Therefore, make sure to load
i915kms, radeonkms or nvidia before hand.

Install and use xorg in the jail as you would normally.
-------------- next part --------------
Index: sys/dev/drm/drmP.h
===================================================================
--- sys/dev/drm/drmP.h	(revision 262457)
+++ sys/dev/drm/drmP.h	(working copy)
@@ -228,7 +228,7 @@
 #define PAGE_ALIGN(addr) round_page(addr)
 /* DRM_SUSER returns true if the user is superuser */
 #if __FreeBSD_version >= 700000
-#define DRM_SUSER(p)		(priv_check(p, PRIV_DRIVER) == 0)
+#define DRM_SUSER(p)		(priv_check(p, PRIV_DRI_DRIVER) == 0)
 #else
 #define DRM_SUSER(p)		(suser(p) == 0)
 #endif
Index: sys/dev/drm2/drmP.h
===================================================================
--- sys/dev/drm2/drmP.h	(revision 262457)
+++ sys/dev/drm2/drmP.h	(working copy)
@@ -251,7 +251,7 @@
 
 #define PAGE_ALIGN(addr) round_page(addr)
 /* DRM_SUSER returns true if the user is superuser */
-#define DRM_SUSER(p)		(priv_check(p, PRIV_DRIVER) == 0)
+#define DRM_SUSER(p)		(priv_check(p, PRIV_DRI_DRIVER) == 0)
 #define DRM_AGP_FIND_DEVICE()	agp_find_device()
 #define DRM_MTRR_WC		MDF_WRITECOMBINE
 #define jiffies			ticks
Index: sys/kern/kern_jail.c
===================================================================
--- sys/kern/kern_jail.c	(revision 262457)
+++ sys/kern/kern_jail.c	(working copy)
@@ -207,6 +207,8 @@
 	"allow.mount.zfs",
 	"allow.mount.procfs",
 	"allow.mount.tmpfs",
+	"allow.dev_io_access",
+	"allow.dev_dri_access",
 };
 const size_t pr_allow_names_size = sizeof(pr_allow_names);
 
@@ -223,6 +225,8 @@
 	"allow.mount.nozfs",
 	"allow.mount.noprocfs",
 	"allow.mount.notmpfs",
+	"allow.nodev_io_access",
+	"allow.nodev_dri_access",
 };
 const size_t pr_allow_nonames_size = sizeof(pr_allow_nonames);
 
@@ -3950,6 +3954,27 @@
 		return (0);
 
 		/*
+		 * Allow access to /dev/io in a jail if the non-jailed admin
+		 * requests this and if /dev/io exists in the jail. This
+		 * allows Xorg to probe a card.
+		 */
+	case PRIV_IO:
+	case PRIV_KMEM_WRITE:
+		if (cred->cr_prison->pr_allow & PR_ALLOW_DEV_IO_ACCESS)
+			return (0);
+		else
+			return (EPERM);
+
+		/*
+		 * Allow low level access to DRI. This allows Xorgs to use DRI.
+		 */
+	case PRIV_DRI_DRIVER:
+		if (cred->cr_prison->pr_allow & PR_ALLOW_DEV_DRI_ACCESS)
+			return (0);
+		else
+			return (EPERM);
+
+		/*
 		 * Allow jailed root to set loginclass.
 		 */
 	case PRIV_PROC_SETLOGINCLASS:
@@ -4246,6 +4271,15 @@
     NULL, PR_ALLOW_MOUNT_ZFS, sysctl_jail_default_allow, "I",
     "Processes in jail can mount the zfs file system");
 
+SYSCTL_PROC(_security_jail, OID_AUTO, dev_io_access,
+    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
+    NULL, PR_ALLOW_DEV_IO_ACCESS, sysctl_jail_default_allow, "I",
+    "Processes in jail can access /dev/io if it exists");
+SYSCTL_PROC(_security_jail, OID_AUTO, dev_dri_access,
+    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
+    NULL, PR_ALLOW_DEV_DRI_ACCESS, sysctl_jail_default_allow, "I",
+    "Processes in jail can access /dev/dri if it exists");
+
 static int
 sysctl_jail_default_level(SYSCTL_HANDLER_ARGS)
 {
@@ -4383,6 +4417,10 @@
     "B", "Jail may set file quotas");
 SYSCTL_JAIL_PARAM(_allow, socket_af, CTLTYPE_INT | CTLFLAG_RW,
     "B", "Jail may create sockets other than just UNIX/IPv4/IPv6/route");
+SYSCTL_JAIL_PARAM(_allow, dev_io_access, CTLTYPE_INT | CTLFLAG_RW,
+    "B", "Jail may access /dev/io if it exists");
+SYSCTL_JAIL_PARAM(_allow, dev_dri_access, CTLTYPE_INT | CTLFLAG_RW,
+    "B", "Jail may access /dev/dri if it exists");
 
 SYSCTL_JAIL_PARAM_SUBNODE(allow, mount, "Jail mount/unmount permission flags");
 SYSCTL_JAIL_PARAM(_allow_mount, , CTLTYPE_INT | CTLFLAG_RW,
Index: sys/sys/jail.h
===================================================================
--- sys/sys/jail.h	(revision 262457)
+++ sys/sys/jail.h	(working copy)
@@ -228,7 +228,9 @@
 #define	PR_ALLOW_MOUNT_ZFS		0x0200
 #define	PR_ALLOW_MOUNT_PROCFS		0x0400
 #define	PR_ALLOW_MOUNT_TMPFS		0x0800
-#define	PR_ALLOW_ALL			0x0fff
+#define	PR_ALLOW_DEV_IO_ACCESS		0x1000
+#define	PR_ALLOW_DEV_DRI_ACCESS		0x2000
+#define	PR_ALLOW_ALL			0x3fff
 
 /*
  * OSD methods
Index: sys/sys/priv.h
===================================================================
--- sys/sys/priv.h	(revision 262457)
+++ sys/sys/priv.h	(working copy)
@@ -500,10 +500,11 @@
 #define	PRIV_KMEM_READ		680	/* Open mem/kmem for reading. */
 #define	PRIV_KMEM_WRITE		681	/* Open mem/kmem for writing. */
 
+#define	PRIV_DRI_DRIVER		682
 /*
  * Track end of privilege list.
  */
-#define	_PRIV_HIGHEST		682
+#define	_PRIV_HIGHEST		683
 
 /*
  * Validate that a named privilege is known by the privilege system.  Invalid


More information about the freebsd-x11 mailing list