running Xorg without root

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

running Xorg without root

Lauri Tirkkonen-2
Hi,

since the Xorg setuid bit was removed, I looked a little bit into what
it would take to run it without root privs. I have a proof of concept
put together, and things seem to work (on an X220 amd64 + modesetting
driver, inteldrm; login on ttyC0 and running xinit).  Testing the waters
here to see if anyone else is interested :)

First, we need Xorg to attempt xf86OpenConsole even when we're not uid
0. That will call xf86OpenWScons (through xf86ConsTab), which opens the
console device and does wscons ioctls on it -- succeeding if the user
running X has logged in on that console.

diff --git a/xserver/hw/xfree86/common/xf86Init.c b/xserver/hw/xfree86/common/xf86Init.c
index 2a04da045..b814eb412 100644
--- a/xserver/hw/xfree86/common/xf86Init.c
+++ b/xserver/hw/xfree86/common/xf86Init.c
@@ -967,9 +967,13 @@ OsVendorInit(void)
 #endif
 #endif
 #if defined(X_PRIVSEP)
-  if (!beenHere && !xf86KeepPriv && geteuid() == 0) {
-  xf86PrivilegedInit();
-  xf86DropPriv();
+  if (!beenHere) {
+  if(!xf86KeepPriv && geteuid() == 0) {
+  xf86PrivilegedInit();
+  xf86DropPriv();
+  } else {
+  xf86OpenConsole();
+  }
   }
 #endif
 

Next, we need the user logging in on ttyC0 to be able to access
/dev/pci0 and /dev/ttyC4:

diff --git a/etc/etc.amd64/fbtab b/etc/etc.amd64/fbtab
index 79cfb535c9f..b746b7684f7 100644
--- a/etc/etc.amd64/fbtab
+++ b/etc/etc.amd64/fbtab
@@ -1 +1 @@
-/dev/ttyC0 0600 /dev/console:/dev/wskbd:/dev/wskbd0:/dev/wsmouse:/dev/wsmouse0:/dev/ttyCcfg:/dev/drm0
+/dev/ttyC0 0600 /dev/console:/dev/wskbd:/dev/wskbd0:/dev/wsmouse:/dev/wsmouse0:/dev/ttyCcfg:/dev/drm0:/dev/pci0:/dev/ttyC4


Finally, there's a check in drm_drv.c that only allows superuser to
become a master on /dev/drm0 and fails the open for other users. I
removed the superuser check; filesystem permissions should prevent
anyone except the user logging in on ttyC0 from accessing this device
anyway. I haven't studied what exactly being the master allows here and
if there's possible privilege escalation hiding there; my reading of
drm_do_ioctl is that ioctls marked DRM_ROOT_ONLY will still fail, so I
admit I don't really know what the check was there for...

Still, this allows running X without any user processes as root (and
unbreaks xinit/startx) - is there any potential here? :)

diff --git a/sys/dev/pci/drm/drm_drv.c b/sys/dev/pci/drm/drm_drv.c
index e09380e3257..be9773b0671 100644
--- a/sys/dev/pci/drm/drm_drv.c
+++ b/sys/dev/pci/drm/drm_drv.c
@@ -745,14 +745,10 @@ drmopen(dev_t kdev, int flags, int fmt, struct proc *p)
  }
 
  mutex_lock(&dev->struct_mutex);
- /* first opener automatically becomes master if root */
- if (SPLAY_EMPTY(&dev->files) && !DRM_SUSER(p)) {
- mutex_unlock(&dev->struct_mutex);
- ret = EPERM;
- goto free_priv;
- }
-
+ /* first opener automatically becomes master */
  file_priv->is_master = SPLAY_EMPTY(&dev->files);
+ if (!file_priv->authenticated)
+ file_priv->authenticated = file_priv->is_master;
 
  SPLAY_INSERT(drm_file_tree, &dev->files, file_priv);
  mutex_unlock(&dev->struct_mutex);

--
Lauri Tirkkonen | lotheac @ IRCnet

Reply | Threaded
Open this post in threaded view
|

Re: running Xorg without root

Matthieu Herrb-7
On Wed, Dec 12, 2018 at 01:27:24AM +0200, Lauri Tirkkonen wrote:

> Hi,
>
> since the Xorg setuid bit was removed, I looked a little bit into what
> it would take to run it without root privs. I have a proof of concept
> put together, and things seem to work (on an X220 amd64 + modesetting
> driver, inteldrm; login on ttyC0 and running xinit).  Testing the waters
> here to see if anyone else is interested :)
>
> First, we need Xorg to attempt xf86OpenConsole even when we're not uid
> 0. That will call xf86OpenWScons (through xf86ConsTab), which opens the
> console device and does wscons ioctls on it -- succeeding if the user
> running X has logged in on that console.
>
> diff --git a/xserver/hw/xfree86/common/xf86Init.c b/xserver/hw/xfree86/common/xf86Init.c
> index 2a04da045..b814eb412 100644
> --- a/xserver/hw/xfree86/common/xf86Init.c
> +++ b/xserver/hw/xfree86/common/xf86Init.c
> @@ -967,9 +967,13 @@ OsVendorInit(void)
>  #endif
>  #endif
>  #if defined(X_PRIVSEP)
> -  if (!beenHere && !xf86KeepPriv && geteuid() == 0) {
> -  xf86PrivilegedInit();
> -  xf86DropPriv();
> +  if (!beenHere) {
> +  if(!xf86KeepPriv && geteuid() == 0) {
> +  xf86PrivilegedInit();
> +  xf86DropPriv();
> +  } else {
> +  xf86OpenConsole();
> +  }
>    }
>  #endif

This shouldn't be needed (And wasn't when I did my own tests with
running X without root). With startx you can re-use the virtual
console from which X was started, there won't be any other process
(like getty(8) fighting with the X server for input.

What was the issue that prompted you to make this change ?

>  
>
> Next, we need the user logging in on ttyC0 to be able to access
> /dev/pci0 and /dev/ttyC4:
>
> diff --git a/etc/etc.amd64/fbtab b/etc/etc.amd64/fbtab
> index 79cfb535c9f..b746b7684f7 100644
> --- a/etc/etc.amd64/fbtab
> +++ b/etc/etc.amd64/fbtab
> @@ -1 +1 @@
> -/dev/ttyC0 0600 /dev/console:/dev/wskbd:/dev/wskbd0:/dev/wsmouse:/dev/wsmouse0:/dev/ttyCcfg:/dev/drm0
> +/dev/ttyC0 0600 /dev/console:/dev/wskbd:/dev/wskbd0:/dev/wsmouse:/dev/wsmouse0:/dev/ttyCcfg:/dev/drm0:/dev/pci0:/dev/ttyC4
>
>
> Finally, there's a check in drm_drv.c that only allows superuser to
> become a master on /dev/drm0 and fails the open for other users. I
> removed the superuser check; filesystem permissions should prevent
> anyone except the user logging in on ttyC0 from accessing this device
> anyway. I haven't studied what exactly being the master allows here and
> if there's possible privilege escalation hiding there; my reading of
> drm_do_ioctl is that ioctls marked DRM_ROOT_ONLY will still fail, so I
> admit I don't really know what the check was there for...
>
> Still, this allows running X without any user processes as root (and
> unbreaks xinit/startx) - is there any potential here? :)

Yes. We dont wan't to do that. Mark has some plans to implement the
proper solution here.

Also note that this will only work for the modesetting
driver. Unfortnatly, even the other KMS based driver (intel and
radeon) still need more work to run without some root privileges.
And older drivers (non AMD/intel cards) will stop working completly.

>
> diff --git a/sys/dev/pci/drm/drm_drv.c b/sys/dev/pci/drm/drm_drv.c
> index e09380e3257..be9773b0671 100644
> --- a/sys/dev/pci/drm/drm_drv.c
> +++ b/sys/dev/pci/drm/drm_drv.c
> @@ -745,14 +745,10 @@ drmopen(dev_t kdev, int flags, int fmt, struct proc *p)
>   }
>  
>   mutex_lock(&dev->struct_mutex);
> - /* first opener automatically becomes master if root */
> - if (SPLAY_EMPTY(&dev->files) && !DRM_SUSER(p)) {
> - mutex_unlock(&dev->struct_mutex);
> - ret = EPERM;
> - goto free_priv;
> - }
> -
> + /* first opener automatically becomes master */
>   file_priv->is_master = SPLAY_EMPTY(&dev->files);
> + if (!file_priv->authenticated)
> + file_priv->authenticated = file_priv->is_master;
>  
>   SPLAY_INSERT(drm_file_tree, &dev->files, file_priv);
>   mutex_unlock(&dev->struct_mutex);
>
> --
> Lauri Tirkkonen | lotheac @ IRCnet

--
Matthieu Herrb

Reply | Threaded
Open this post in threaded view
|

Re: running Xorg without root

Lauri Tirkkonen-2
On Wed, Dec 12 2018 09:18:45 +0100, Matthieu Herrb wrote:

> > diff --git a/xserver/hw/xfree86/common/xf86Init.c b/xserver/hw/xfree86/common/xf86Init.c
> > index 2a04da045..b814eb412 100644
> > --- a/xserver/hw/xfree86/common/xf86Init.c
> > +++ b/xserver/hw/xfree86/common/xf86Init.c
> > @@ -967,9 +967,13 @@ OsVendorInit(void)
> >  #endif
> >  #endif
> >  #if defined(X_PRIVSEP)
> > -  if (!beenHere && !xf86KeepPriv && geteuid() == 0) {
> > -  xf86PrivilegedInit();
> > -  xf86DropPriv();
> > +  if (!beenHere) {
> > +  if(!xf86KeepPriv && geteuid() == 0) {
> > +  xf86PrivilegedInit();
> > +  xf86DropPriv();
> > +  } else {
> > +  xf86OpenConsole();
> > +  }
> >    }
> >  #endif
>
> This shouldn't be needed (And wasn't when I did my own tests with
> running X without root). With startx you can re-use the virtual
> console from which X was started, there won't be any other process
> (like getty(8) fighting with the X server for input.
>
> What was the issue that prompted you to make this change ?

The console was not opened otherwise if euid==0 (xf86OpenConsole is only
called from xf86PrivilegedInit), and I saw some ioctl's on fd -1 as a
result in ktrace.

> > Finally, there's a check in drm_drv.c that only allows superuser to
> > become a master on /dev/drm0 and fails the open for other users. I
> > removed the superuser check; filesystem permissions should prevent
> > anyone except the user logging in on ttyC0 from accessing this device
> > anyway. I haven't studied what exactly being the master allows here and
> > if there's possible privilege escalation hiding there; my reading of
> > drm_do_ioctl is that ioctls marked DRM_ROOT_ONLY will still fail, so I
> > admit I don't really know what the check was there for...
> >
> > Still, this allows running X without any user processes as root (and
> > unbreaks xinit/startx) - is there any potential here? :)
>
> Yes. We dont wan't to do that. Mark has some plans to implement the
> proper solution here.

ok, thanks. It was worth a shot anyway :)

> Also note that this will only work for the modesetting
> driver. Unfortnatly, even the other KMS based driver (intel and
> radeon) still need more work to run without some root privileges.

true, I did not test other drivers.

> And older drivers (non AMD/intel cards) will stop working completly.

I don't see how that follows. This change *relaxes* the requirements for
becoming master on /dev/drm0 (they no longer have to be root), how would
that cause those older drivers to stop working?

--
Lauri Tirkkonen | lotheac @ IRCnet

Reply | Threaded
Open this post in threaded view
|

Re: running Xorg without root

Lauri Tirkkonen-2
argh:

On Wed, Dec 12 2018 10:26:42 +0200, Lauri Tirkkonen wrote:
> > What was the issue that prompted you to make this change ?
>
> The console was not opened otherwise if euid==0

euid != 0, I meant.

--
Lauri Tirkkonen | lotheac @ IRCnet

Reply | Threaded
Open this post in threaded view
|

Re: running Xorg without root

Mark Kettenis
In reply to this post by Lauri Tirkkonen-2
> Date: Wed, 12 Dec 2018 01:27:24 +0200
> From: Lauri Tirkkonen <[hidden email]>
>
> Hi,
>
> since the Xorg setuid bit was removed, I looked a little bit into what
> it would take to run it without root privs. I have a proof of concept
> put together, and things seem to work (on an X220 amd64 + modesetting
> driver, inteldrm; login on ttyC0 and running xinit).  Testing the waters
> here to see if anyone else is interested :)

I have a somewhat similar set of diffs that still need some polishing.
I have not been able to push that forward the last couple of weeks
because of lack of time.  But I hope that'll change after next
weekend.

> First, we need Xorg to attempt xf86OpenConsole even when we're not uid
> 0. That will call xf86OpenWScons (through xf86ConsTab), which opens the
> console device and does wscons ioctls on it -- succeeding if the user
> running X has logged in on that console.
>
> diff --git a/xserver/hw/xfree86/common/xf86Init.c b/xserver/hw/xfree86/common/xf86Init.c
> index 2a04da045..b814eb412 100644
> --- a/xserver/hw/xfree86/common/xf86Init.c
> +++ b/xserver/hw/xfree86/common/xf86Init.c
> @@ -967,9 +967,13 @@ OsVendorInit(void)
>  #endif
>  #endif
>  #if defined(X_PRIVSEP)
> -  if (!beenHere && !xf86KeepPriv && geteuid() == 0) {
> -  xf86PrivilegedInit();
> -  xf86DropPriv();
> +  if (!beenHere) {
> +  if(!xf86KeepPriv && geteuid() == 0) {
> +  xf86PrivilegedInit();
> +  xf86DropPriv();
> +  } else {
> +  xf86OpenConsole();
> +  }
>    }
>  #endif
>  
>
> Next, we need the user logging in on ttyC0 to be able to access
> /dev/pci0 and /dev/ttyC4:
>
> diff --git a/etc/etc.amd64/fbtab b/etc/etc.amd64/fbtab
> index 79cfb535c9f..b746b7684f7 100644
> --- a/etc/etc.amd64/fbtab
> +++ b/etc/etc.amd64/fbtab
> @@ -1 +1 @@
> -/dev/ttyC0 0600 /dev/console:/dev/wskbd:/dev/wskbd0:/dev/wsmouse:/dev/wsmouse0:/dev/ttyCcfg:/dev/drm0
> +/dev/ttyC0 0600 /dev/console:/dev/wskbd:/dev/wskbd0:/dev/wsmouse:/dev/wsmouse0:/dev/ttyCcfg:/dev/drm0:/dev/pci0:/dev/ttyC4
>
>
> Finally, there's a check in drm_drv.c that only allows superuser to
> become a master on /dev/drm0 and fails the open for other users. I
> removed the superuser check; filesystem permissions should prevent
> anyone except the user logging in on ttyC0 from accessing this device
> anyway. I haven't studied what exactly being the master allows here and
> if there's possible privilege escalation hiding there; my reading of
> drm_do_ioctl is that ioctls marked DRM_ROOT_ONLY will still fail, so I
> admit I don't really know what the check was there for...
>
> Still, this allows running X without any user processes as root (and
> unbreaks xinit/startx) - is there any potential here? :)
>
> diff --git a/sys/dev/pci/drm/drm_drv.c b/sys/dev/pci/drm/drm_drv.c
> index e09380e3257..be9773b0671 100644
> --- a/sys/dev/pci/drm/drm_drv.c
> +++ b/sys/dev/pci/drm/drm_drv.c
> @@ -745,14 +745,10 @@ drmopen(dev_t kdev, int flags, int fmt, struct proc *p)
>   }
>  
>   mutex_lock(&dev->struct_mutex);
> - /* first opener automatically becomes master if root */
> - if (SPLAY_EMPTY(&dev->files) && !DRM_SUSER(p)) {
> - mutex_unlock(&dev->struct_mutex);
> - ret = EPERM;
> - goto free_priv;
> - }
> -
> + /* first opener automatically becomes master */
>   file_priv->is_master = SPLAY_EMPTY(&dev->files);
> + if (!file_priv->authenticated)
> + file_priv->authenticated = file_priv->is_master;
>  
>   SPLAY_INSERT(drm_file_tree, &dev->files, file_priv);
>   mutex_unlock(&dev->struct_mutex);
>
> --
> Lauri Tirkkonen | lotheac @ IRCnet
>
>

Reply | Threaded
Open this post in threaded view
|

Re: running Xorg without root

Lauri Tirkkonen-2
On Wed, Dec 12 2018 11:09:18 +0100, Mark Kettenis wrote:

> > Date: Wed, 12 Dec 2018 01:27:24 +0200
> > From: Lauri Tirkkonen <[hidden email]>
> >
> > Hi,
> >
> > since the Xorg setuid bit was removed, I looked a little bit into what
> > it would take to run it without root privs. I have a proof of concept
> > put together, and things seem to work (on an X220 amd64 + modesetting
> > driver, inteldrm; login on ttyC0 and running xinit).  Testing the waters
> > here to see if anyone else is interested :)
>
> I have a somewhat similar set of diffs that still need some polishing.
> I have not been able to push that forward the last couple of weeks
> because of lack of time.  But I hope that'll change after next
> weekend.

ah, nice. let me know if I can help in some way :)

--
Lauri Tirkkonen | lotheac @ IRCnet