[RFC] non-root X

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

"); - /* change ownership of the vt */ - if (chown(vtname, getuid(), getgid()) < 0) - xf86Msg(X_WARNING,"xf86OpenConsole: chown %s failed: %s

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

", - strerror(errno)); + if (geteuid() == 0) { + /* change ownership of the vt */ + if (chown(vtname, getuid(), getgid()) < 0) + xf86Msg(X_WARNING,"xf86OpenConsole: chown %s failed: %s

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

", + 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)

"); ErrorF("-novtswitch don't immediately switch to new VT

"); ErrorF("-sharevts share VTs with another X server

"); + ErrorF("-nohwaccess don't access hardware ports directly

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