Lyude Paul <ly...@redhat.com> writes:

> Looks good! One nitpick I'm not 100% sure about:

>> +#define CHECK_FOR_REQUIRED_ARGUMENT() \
>> +    if (((i + 1) >= argc) || (!argv[i + 1])) {                              
>> \
>> +      ErrorF("Required argument to %s not specified\n", argv[i]);   \
>> +      UseMsg();                                                     \
>> +      FatalError("Required argument to %s not specified\n", argv[i]);       
> Is the double printing of "Required argument to %s not specified" here
> intentional?

I copied CHECK_FOR_REQUIRED_ARGUMENT from xf86Init.c where it does the
same thing. I assume this is intended to make sure the user understands
what error caused the server to exit -- you can see it both before and
after the long usage message.

>> +    if (!xf86PrivsElevated())
>> +        ErrorF("-masterfd <fd>         use the specified fd as the DRM
>> master fd\n");
> I think it would be a better idea for us to show this argument description
> unconditionally, along with adding a note about setuid/setgid not being
> allowed with it

Sounds good. 

Here's an updated patch with the usage message change suggested. Thanks
for reviewing!

From f122451b7f5be985036cae29df7126a7f25cc891 Mon Sep 17 00:00:00 2001
From: Keith Packard <kei...@keithp.com>
Date: Thu, 18 Jan 2018 18:07:29 -0800
Subject: [PATCH xserver] modesetting: Allow a DRM fd to be passed on command
 line with -masterfd [v2]

This lets an application open a suitable DRM device and pass the file
descriptor to the mode setting driver through an X server command line
option, '-masterfd'.

There's a companion application, xlease, which creates a DRM master by
leasing an output from another X server. That is available at

	git clone git://people.freedesktop.org/~keithp/xlease

v2:
	Always print usage, but note that it can't be used if
	setuid/gid

	Suggested-by: Lyude Paul <ly...@redhat.com>

Signed-off-by: Keith Packard <kei...@keithp.com>
---
 hw/xfree86/common/xf86Globals.c         |  2 ++
 hw/xfree86/common/xf86Priv.h            |  1 +
 hw/xfree86/drivers/modesetting/driver.c | 26 ++++++++++++++++++++++++-
 hw/xfree86/drivers/modesetting/driver.h |  1 +
 hw/xfree86/os-support/linux/lnx_init.c  | 21 ++++++++++++++++++++
 5 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
index e890f05c2..7cc7401a2 100644
--- a/hw/xfree86/common/xf86Globals.c
+++ b/hw/xfree86/common/xf86Globals.c
@@ -53,6 +53,8 @@ DevPrivateKeyRec xf86ScreenKeyRec;
 ScrnInfoPtr *xf86Screens = NULL;        /* List of ScrnInfos */
 ScrnInfoPtr *xf86GPUScreens = NULL;        /* List of ScrnInfos */
 
+int xf86DRMMasterFd = -1;  /* Command line argument for DRM master file descriptor */
+
 const unsigned char byte_reversed[256] = {
     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
     0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
index 4fe2b5f33..393af3900 100644
--- a/hw/xfree86/common/xf86Priv.h
+++ b/hw/xfree86/common/xf86Priv.h
@@ -93,6 +93,7 @@ extern _X_EXPORT int xf86LogVerbose;    /* log file verbosity level */
 
 extern ScrnInfoPtr *xf86GPUScreens;      /* List of pointers to ScrnInfoRecs */
 extern int xf86NumGPUScreens;
+extern _X_EXPORT int xf86DRMMasterFd;              /* Command line argument for DRM master file descriptor */
 #ifndef DEFAULT_VERBOSE
 #define DEFAULT_VERBOSE		0
 #endif
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 306541f33..6f4637254 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -36,6 +36,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include "xf86.h"
+#include "xf86Priv.h"
 #include "xf86_OSproc.h"
 #include "compiler.h"
 #include "xf86Pci.h"
@@ -194,11 +195,24 @@ modesettingEntPtr ms_ent_priv(ScrnInfoPtr scrn)
     return pPriv->ptr;
 }
 
+static int
+get_passed_fd(void)
+{
+    if (xf86DRMMasterFd >= 0) {
+        xf86DrvMsg(-1, X_INFO, "Using passed DRM master file descriptor %d\n", xf86DRMMasterFd);
+        return dup(xf86DRMMasterFd);
+    }
+    return -1;
+}
+
 static int
 open_hw(const char *dev)
 {
     int fd;
 
+    if ((fd = get_passed_fd()) != -1)
+        return fd;
+
     if (dev)
         fd = open(dev, O_RDWR | O_CLOEXEC, 0);
     else {
@@ -818,6 +832,12 @@ ms_get_drm_master_fd(ScrnInfoPtr pScrn)
         return TRUE;
     }
 
+    ms->fd_passed = FALSE;
+    if ((ms->fd = get_passed_fd()) >= 0) {
+        ms->fd_passed = TRUE;
+        return TRUE;
+    }
+
 #ifdef XSERVER_PLATFORM_BUS
     if (pEnt->location.type == BUS_PLATFORM) {
 #ifdef XF86_PDEV_SERVER_FD
@@ -1502,6 +1522,9 @@ SetMaster(ScrnInfoPtr pScrn)
         return TRUE;
 #endif
 
+    if (ms->fd_passed)
+        return TRUE;
+
     ret = drmSetMaster(ms->fd);
     if (ret)
         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "drmSetMaster failed: %s\n",
@@ -1754,7 +1777,8 @@ LeaveVT(ScrnInfoPtr pScrn)
         return;
 #endif
 
-    drmDropMaster(ms->fd);
+    if (!ms->fd_passed)
+        drmDropMaster(ms->fd);
 }
 
 /*
diff --git a/hw/xfree86/drivers/modesetting/driver.h b/hw/xfree86/drivers/modesetting/driver.h
index 55f3400e2..c8db4b8a4 100644
--- a/hw/xfree86/drivers/modesetting/driver.h
+++ b/hw/xfree86/drivers/modesetting/driver.h
@@ -84,6 +84,7 @@ struct ms_drm_queue {
 
 typedef struct _modesettingRec {
     int fd;
+    Bool fd_passed;
 
     int Chipset;
     EntityInfoPtr pEnt;
diff --git a/hw/xfree86/os-support/linux/lnx_init.c b/hw/xfree86/os-support/linux/lnx_init.c
index a00002464..039dc4a4d 100644
--- a/hw/xfree86/os-support/linux/lnx_init.c
+++ b/hw/xfree86/os-support/linux/lnx_init.c
@@ -346,6 +346,13 @@ xf86CloseConsole(void)
     close(xf86Info.consoleFd);  /* make the vt-manager happy */
 }
 
+#define CHECK_FOR_REQUIRED_ARGUMENT() \
+    if (((i + 1) >= argc) || (!argv[i + 1])) { 				\
+      ErrorF("Required argument to %s not specified\n", argv[i]); 	\
+      UseMsg(); 							\
+      FatalError("Required argument to %s not specified\n", argv[i]);	\
+    }
+
 int
 xf86ProcessArgument(int argc, char *argv[], int i)
 {
@@ -366,6 +373,19 @@ xf86ProcessArgument(int argc, char *argv[], int i)
         }
         return 1;
     }
+
+    if (!strcmp(argv[i], "-masterfd")) {
+        CHECK_FOR_REQUIRED_ARGUMENT();
+        if (xf86PrivsElevated())
+            FatalError("\nCannot specify -masterfd when server is setuid/setgid\n");
+        if (sscanf(argv[++i], "%d", &xf86DRMMasterFd) != 1) {
+            UseMsg();
+            xf86DRMMasterFd = -1;
+            return 0;
+        }
+        return 2;
+    }
+
     return 0;
 }
 
@@ -375,4 +395,5 @@ xf86UseMsg(void)
     ErrorF("vtXX                   use the specified VT number\n");
     ErrorF("-keeptty               ");
     ErrorF("don't detach controlling tty (for debugging only)\n");
+    ErrorF("-masterfd <fd>         use the specified fd as the DRM master fd (not if setuid/gid)\n");
 }
-- 
2.17.1

-- 
-keith

Attachment: signature.asc
Description: PGP signature

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to