[RFC] non-root X

Jesse Barnes jbarnes at virtuousgeek.org
Wed Jul 1 13:11:06 PDT 2009


For Moblin, we'd like to be able to run X as a non-root user, so with
that in mind I spent a few hours looking at what it would take to get X
running w/o root perms on the latest bits using the xf86-video-intel
driver (note Dave did this about a year ago, but I guess the bits
didn't make it upstream). Turns out now that all the pieces are in
place it was really easy. X needed root on Linux for a few things:
  1) I/O probing
  2) tty/VT probing & ownership
  3) some DRM ioctls
  4) some PCI related probing
  5) input perms

However, with a KMS enabled driver that doesn't do I/O access, (1) and
(4) aren't really necessary anymore.  For (3), just a couple of ioctls
need to have their "root only" status stripped (safely I think).  And
for (2) and (5), distro pam scripts can take care of things (as long as
X is started on a tty that has had its ownership/perms modified
appropriately).

So this small patch is all that's necessary on the X side (the DRM
patch is trivial, and half of it has already been posted to dri-devel).
It's a big hackish, so I'm just requesting comments at this point.  I'd
like to do the -nohwaccess part better, but think doing it well will
require a driver ABI change (maybe just a new flags field that
indicates whether the driver needs I/O ports enabled, or we can push
the xf86EnableIO call into drivers as needed).

Beyond that, I had to fix a few things in the xf86-video-intel driver
and libpciaccess, but all of those bits are in git master of those
repos, so if you want to try things out, it should be pretty easy to
pull things together.

Anyone have thoughts on this?

Thanks,
-- 
Jesse Barnes, Intel Open Source Technology Center

diff --git a/hw/xfree86/os-support/linux/lnx_init.c b/hw/xfree86/os-support/linux/lnx_init.c
index 7f40857..cf58c01 100644
--- a/hw/xfree86/os-support/linux/lnx_init.c
+++ b/hw/xfree86/os-support/linux/lnx_init.c
@@ -49,6 +49,7 @@ static Bool KeepTty = FALSE;
 static int VTnum = -1;
 static Bool VTSwitch = TRUE;
 static Bool ShareVTs = FALSE;
+Bool NoHwAccess = FALSE;
 static int activeVT = -1;
 
 static int vtPermSave[4];
@@ -80,9 +81,11 @@ saveVtPerms(void)
 static void
 restoreVtPerms(void)
 {
-    /* Set the terminal permissions back to before we started. */
-    chown("/dev/tty0", vtPermSave[0], vtPermSave[1]);
-    chown(vtname, vtPermSave[2], vtPermSave[3]);
+    if (geteuid() == 0) {
+	 /* Set the terminal permissions back to before we started. */
+	 (void)chown("/dev/tty0", vtPermSave[0], vtPermSave[1]);
+	 (void)chown(vtname, vtPermSave[2], vtPermSave[3]);
+    }
 }
 
 static void *console_handler;
@@ -210,20 +213,22 @@ xf86OpenConsole(void)
 	        xf86Msg(X_WARNING,
 		        "xf86OpenConsole: Could not save ownership of VT\n");
 
-	    /* change ownership of the vt */
-	    if (chown(vtname, getuid(), getgid()) < 0)
-	        xf86Msg(X_WARNING,"xf86OpenConsole: chown %s failed: %s\n",
-		        vtname, strerror(errno));
-
-	    /*
-	     * the current VT device we're running on is not "console", we want
-	     * to grab all consoles too
-	     *
-	     * Why is this needed??
-	     */
-	    if (chown("/dev/tty0", getuid(), getgid()) < 0)
-	        xf86Msg(X_WARNING,"xf86OpenConsole: chown /dev/tty0 failed: %s\n",
-                    strerror(errno));
+	    if (geteuid() == 0) {
+		    /* change ownership of the vt */
+		    if (chown(vtname, getuid(), getgid()) < 0)
+			    xf86Msg(X_WARNING,"xf86OpenConsole: chown %s failed: %s\n",
+				    vtname, strerror(errno));
+
+		    /*
+		     * the current VT device we're running on is not
+		     * "console", we want to grab all consoles too
+		     *
+		     * Why is this needed??
+		     */
+		    if (chown("/dev/tty0", getuid(), getgid()) < 0)
+			    xf86Msg(X_WARNING,"xf86OpenConsole: chown /dev/tty0 failed: %s\n",
+				    strerror(errno));
+	    }
         }
 
 	/*
@@ -433,6 +438,11 @@ xf86ProcessArgument(int argc, char *argv[], int i)
                 ShareVTs = TRUE;
                 return(1);
         }
+	if (!strcmp(argv[i], "-nohwaccess"))
+	{
+		NoHwAccess = TRUE;
+		return(1);
+	}
 	if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
 	{
 		if (sscanf(argv[i], "vt%2d", &VTnum) == 0)
@@ -454,5 +464,6 @@ xf86UseMsg()
 	ErrorF("don't detach controlling tty (for debugging only)\n");
         ErrorF("-novtswitch            don't immediately switch to new VT\n");
         ErrorF("-sharevts              share VTs with another X server\n");
+	ErrorF("-nohwaccess            don't access hardware ports directly\n");
 	return;
 }
diff --git a/hw/xfree86/os-support/linux/lnx_video.c b/hw/xfree86/os-support/linux/lnx_video.c
index 688106a..34a845b 100644
--- a/hw/xfree86/os-support/linux/lnx_video.c
+++ b/hw/xfree86/os-support/linux/lnx_video.c
@@ -51,6 +51,7 @@
 #define MAP_FAILED ((void *)-1)
 #endif
 
+extern Bool NoHwAccess;
 static Bool ExtendedEnabled = FALSE;
 
 #ifdef __ia64__
@@ -509,6 +510,9 @@ xf86EnableIO(void)
 	int fd;
 	unsigned int ioBase_phys;
 #endif
+	/* Fake it... */
+	if (NoHwAccess)
+		return TRUE;
 
 	if (ExtendedEnabled)
 		return TRUE;


More information about the xorg-devel mailing list