From c647df3e017a1a61b57ca83c210e27d1a1479f2a Mon Sep 17 00:00:00 2001 From: Alexei Colin Date: Fri, 26 Dec 2014 23:15:28 -0500 Subject: [PATCH 2/2] xfree86: systemd-logind and pre-SUPPORTS_SERVER_FD drivers Drivers that without SUPPORTS_SERVER_FD (e.g. armsoc) *and* without 'platformProbe' method (only with legacy 'Probe' method) are denied access to the DRM device while the server holds a file descriptor to the device obtained from systemd-logind. The driver's requests that require the 'master' privilege are denied by kernel drm module because systemd-logind sets its file object to be the master upon opening it. The server acquires file descriptors without regard to the SUPPORTS_SERVER_FD capability of the driver during bus probing. The code to release these file descriptors for drivers without SUPPORTS_SERVER_FD was already present, but only for drivers with platformProbe method. This commits move this code up the stack so that it takes effect for both kinds of drivers. --- hw/xfree86/common/xf86Bus.c | 2 ++ hw/xfree86/common/xf86platformBus.c | 35 ++++++++++++++++++++++++++++------- hw/xfree86/common/xf86platformBus.h | 1 + 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c index 889294f..dc68755 100644 --- a/hw/xfree86/common/xf86Bus.c +++ b/hw/xfree86/common/xf86Bus.c @@ -78,6 +78,8 @@ xf86CallDriverProbe(DriverPtr drv, Bool detect_only) Bool foundScreen = FALSE; #ifdef XSERVER_PLATFORM_BUS + xf86platformReleaseDriverFDs(drv); + if (drv->platformProbe != NULL) { foundScreen = xf86platformProbeDev(drv); } diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c index 336305c..2b13cca 100644 --- a/hw/xfree86/common/xf86platformBus.c +++ b/hw/xfree86/common/xf86platformBus.c @@ -394,13 +394,6 @@ static Bool doPlatformProbe(struct xf86_platform_device *dev, DriverPtr drvp, } } if (entity != -1) { - if ((dev->flags & XF86_PDEV_SERVER_FD) && (!drvp->driverFunc || - !drvp->driverFunc(NULL, SUPPORTS_SERVER_FDS, NULL))) { - systemd_logind_release_fd(dev->attribs->major, dev->attribs->minor, dev->attribs->fd); - dev->attribs->fd = -1; - dev->flags &= ~XF86_PDEV_SERVER_FD; - } - if (drvp->platformProbe(drvp, entity, flags, dev, match_data)) foundScreen = TRUE; else @@ -617,4 +610,32 @@ void xf86platformPrimary(void) } } } + +/* Release file descriptors for devices that belong to drivers without + * SUPPORTS_SERVER_FD support. The server might be holding file + * descriptors acquired through systemd-logind during bus probing, + * without regard to whether the driver supports server-managed FDs. + */ +void xf86platformReleaseDriverFDs(DriverPtr drvp) +{ + GDevPtr *devList; + const unsigned numDevs = xf86MatchDevice(drvp->driverName, &devList); + int i; + struct xf86_platform_device *dev; + + for (i = 0; i < numDevs; i++) { + dev = xf86_find_platform_device_by_busid(devList[i]->busID); + if (!dev) + continue; + + if ((dev->flags & XF86_PDEV_SERVER_FD) && (!drvp->driverFunc || + !drvp->driverFunc(NULL, SUPPORTS_SERVER_FDS, NULL))) + { + systemd_logind_release_fd(dev->attribs->major, dev->attribs->minor, + dev->attribs->fd); + dev->attribs->fd = -1; + dev->flags &= ~XF86_PDEV_SERVER_FD; + } + } +} #endif diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h index 073051c..64c88ce 100644 --- a/hw/xfree86/common/xf86platformBus.h +++ b/hw/xfree86/common/xf86platformBus.h @@ -158,6 +158,7 @@ xf86PlatformMatchDriver(char *matches[], int nmatches); extern void xf86platformVTProbe(void); extern void xf86platformPrimary(void); +extern void xf86platformReleaseDriverFDs(DriverPtr drvp); #endif #endif -- 2.2.1