Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 9 Mar 2014 19:08:02 +0100
From:      Alexander Leidinger <Alexander@Leidinger.net>
To:        Tom Evans <tevans.uk@googlemail.com>
Cc:        "freebsd-hackers@freebsd.org" <freebsd-hackers@freebsd.org>, "freebsd-x11@freebsd.org" <freebsd-x11@freebsd.org>, jamie@freebsd.org, uqs@FreeBSD.org
Subject:   Re: [PATCH] Xorg in a jail
Message-ID:  <20140309190802.00006452@unknown>
In-Reply-To: <CAFHbX1JUzM%2BN9Zx=eCQdejvz1jAWcXNHepB2=5ZRuunu1gAG6g@mail.gmail.com>
References:  <CAFHbX1JUzM%2BN9Zx=eCQdejvz1jAWcXNHepB2=5ZRuunu1gAG6g@mail.gmail.com>

index | next in thread | previous in thread | raw e-mail

[-- Attachment #1 --]
On Sun, 9 Mar 2014 01:26:40 +0000
Tom Evans <tevans.uk@googlemail.com> wrote:

> 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.

Seems you have an old one. Attached is what I was sending to jamie not
long ago (but this is not in the FreeBSD tree due to the conclusion that
such a huge impact on the security part should not be a simple allow.xxx
switch).

> 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.

I use it with NVidia hardware (FreeBSD 11-current shortly after the
switch to 11-current), I also have an old machine with a radeon card
where the patch works too (with a very old 10-current).

> 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.

This is correct.

> 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.

The attached patch uses "allow.kmem_access" for both.

> 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...

Some parts are not needed, you don't need the console, and with nvidia
hardware you need the nvidia devices. It's also enough to have the tty
you want to use Xorg on (by default ttyv8, my rules also have ttyv0,
but I haven't tested if it is really needed... it's still "naturally
grown" for ttyv0).

>   [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

See the attached rules. I have two desktop entries (the second one is
for jails with zfs datasets) in there. Normally you want to have audio
devices, a mouse and a keyboard for a desktop. There are some more
permissions, I also give access to optical drives and USB memory
sticks and a TV tuner, you may not want to give that broad permissions
(remove the cuse/cam/usb part).

> 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

Do NOT use the sysctls in this patch, they allow all jails to access the
devices, if the devfs rules are appropriate. The attached patch doesn't
have them anymore.

I had them in in the first implementation, then jamie introduced the
allow.XXX and I transitioned to this but forgot to remove the sysctls
after migrating my jail. I removed them recently before sending the
patch to jamie after his kmem change.

> 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"

With the attached patch this is ="allow.dev_kmem_access" (you don't
need the "=1" part).

> 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.

Correct.

> Install and use xorg in the jail as you would normally.

Bye,
Alexander.

-- 
http://www.Leidinger.net    Alexander @ Leidinger.net: PGP ID = B0063FE7
http://www.FreeBSD.org       netchild @ FreeBSD.org  : PGP ID = 72077137
[-- Attachment #2 --]
Index: sys/dev/drm/drmP.h
===================================================================
--- sys/dev/drm/drmP.h	(revision 260159)
+++ 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_KMEM_WRITE) == 0)
 #else
 #define DRM_SUSER(p)		(suser(p) == 0)
 #endif
Index: sys/kern/kern_jail.c
===================================================================
--- sys/kern/kern_jail.c	(revision 260159)
+++ sys/kern/kern_jail.c	(working copy)
@@ -208,6 +208,7 @@
 	"allow.mount.zfs",
 	"allow.mount.procfs",
 	"allow.mount.tmpfs",
+	"allow.kmem_access",
 };
 const size_t pr_allow_names_size = sizeof(pr_allow_names);
 
@@ -224,6 +225,7 @@
 	"allow.mount.nozfs",
 	"allow.mount.noprocfs",
 	"allow.mount.notmpfs",
+	"allow.nokmem_access",
 };
 const size_t pr_allow_nonames_size = sizeof(pr_allow_nonames);
 
@@ -3951,6 +3953,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:
+		if (cred->cr_prison->pr_allow & PR_ALLOW_KMEM_ACCESS)
+			return (0);
+		else
+			return (EPERM);
+
+		/*
+		 * Allow low level access to KMEM-like devices (e.g. to
+		 * allow Xorg to use DRI).
+		 */
+	case PRIV_KMEM_WRITE:
+		if (cred->cr_prison->pr_allow & PR_ALLOW_KMEM_ACCESS)
+			return (0);
+		else
+			return (EPERM);
+
+		/*
 		 * Allow jailed root to set loginclass.
 		 */
 	case PRIV_PROC_SETLOGINCLASS:
@@ -4384,6 +4407,8 @@
     "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, kmem_access, CTLTYPE_INT | CTLFLAG_RW,
+    "B", "Jail may access kmem-like devices (io, dri) if they exist");
 
 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 260159)
+++ sys/sys/jail.h	(working copy)
@@ -228,8 +228,10 @@
 #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_KMEM_ACCESS		0x1000
+#define	PR_ALLOW_ALL			0x1fff
 
+
 /*
  * OSD methods
  */

[-- Attachment #3 --]
[devfsrules_unhide_audio=5]
add path 'audio*' unhide
add path 'dsp*' unhide
add path midistat unhide
add path 'mixer*' unhide
add path 'music*' unhide
add path 'sequencer*' unhide
add path sndstat unhide
add path speaker unhide

[devfsrules_unhide_printers=6]
add path 'lpt*' unhide
add path 'ulpt*' unhide user 193 group 193
add path 'unlpt*' unhide user 193 group 193

[devfsrules_unhide_input=7]
add path 'atkbd*' unhide
add path 'kbd*' unhide
add path 'joy*' unhide
add path 'psm*' unhide
add path sysmouse unhide
add path 'ukbd*' unhide
add path 'ums*' unhide

[devfsrules_unhide_xorg=8]
add path agpgart unhide
#add path console unhide
add path dri unhide
add path 'dri*' unhide
add path nvidiactl unhide
add path 'nvidia*' 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

[devfsrules_unhide_cam=9]
add path 'da*' unhide
add path 'cd*' unhide
add path 'cd*' mode 0666
add path 'pass*' unhide
add path 'xpt*' unhide

[devfsrules_unhide_atacd=10]
add path 'acd*' unhide
add path 'acd*' mode 0666

[devfsrules_unhide_kmem=11]
add path kmem unhide

[devfsrules_unhide_zfs=12]
add path zfs unhide

[devfsrules_unhide_cuse=13]
add path cuse unhide
add path video unhide
add path 'video*' unhide
add path dvb unhide
add path 'dvb*' unhide
add path 'adapter*' unhide
add path input unhide
add path 'input*' unhide

[devfsrules_unhide_usb=14]
add path 'usb' unhide
add path 'usb*' unhide
add path 'ugen*' unhide

#
# This allows to run a desktop system in a jail.  Think about what you want to
# achieve before you use this, it opens up the entire machine to access from
# this jail to any sophisticated program.
#
[devfsrules_jail_desktop=15]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_unhide_audio
add include $devfsrules_unhide_input
add include $devfsrules_unhide_xorg
add include $devfsrules_unhide_cam
add include $devfsrules_unhide_kmem
add include $devfsrules_unhide_cuse
add include $devfsrules_unhide_usb

[devfsrules_jail_printserver=16]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_unhide_printers
add include $devfsrules_unhide_zfs

[devfsrules_jail_withzfs=17]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_unhide_zfs

[devfsrules_jail_desktop_withzfs=18]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_unhide_audio
add include $devfsrules_unhide_input
add include $devfsrules_unhide_xorg
add include $devfsrules_unhide_cam
add include $devfsrules_unhide_kmem
add include $devfsrules_unhide_cuse
add include $devfsrules_unhide_usb
add include $devfsrules_unhide_zfs

help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140309190802.00006452>