blob: 19b0a35557d5e0ab243e0dc9014c633fd4bc63df [file] [log] [blame]
From eb0b3c8388f6ee63266171062cb51a55eddf618c Mon Sep 17 00:00:00 2001
From: Nicolas Boichat <nicolas@boichat.ch>
Date: Fri, 17 Jan 2014 11:29:25 +0800
Subject: [PATCH] CHROMIUM: drm: Add drm_master_relax debugfs file (non-root
set/drop master ioctls)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Writing 'Y' to /sys/kernel/debug/dri/drm_master_relax allows
non-CAP_SYS_ADMIN user to call the 2 ioctls DRM_IOCTL_SET_MASTER and
DRM_IOCTL_DROP_MASTER.
This makes it possible to run 2 X11 servers at the same time, where at
least one of them runs under a non-root user (e.g. Chromium OS X server
as xorg user, and a crouton X server as root).
The behavior is not modified if /sys/kernel/debug/dri/drm_master_relax
is kept to its default value ('N').
Modifying drm_master_relax is only possible by root user, so it cannot
possibly lead to exploits. Also, even when the flag is set to 'Y',
DROP_MASTER permissions are changed to DRM_MASTER which means that only
a process that has DRM master can drop it (which is actually quite
logical), and the SET_MASTER IOCTL is changed to DRM_AUTH which allows
all authenticated DRM users to get master.
R=seanpaul@chromium.org, dbehr@chromium.org
BUG=chromium:328115
TEST=With or without the debugfs flag, WebGL examples work, and we can
switch between VT1 and VT2.
TEST=On a peppy in developer mode: With the debugfs flag to 'Y', Ubuntu
saucy chroot generated by crouton (xfce target) is able to start a
second X11 display. Switching back and forth between the two
displays works, and 3D acceleration is working in the chroot.
Signed-off-by: Nicolas Boichat <nicolas@boichat.ch>
Reviewed-on: https://chromium-review.googlesource.com/183190
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Dominik Behr <dbehr@chromium.org>
Commit-Queue: David Schneider <dnschneid@chromium.org>
Tested-by: David Schneider <dnschneid@chromium.org>
(cherry picked from commit d53b6142c2b5c742d2c547568c9814597c41ede6)
Signed-off-by: Dominik Behr <dbehr@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/189390
Reviewed-by: Haixia Shi <hshi@chromium.org>
[benzh: 3.14 rebase. Resolved trivial conflicts]
Signed-off-by: Ben Zhang <benzh@chromium.org>
[bfreed: 3.18 rebase. Resolved conflicts]
Signed-off-by: Bryan Freed <bfreed@chromium.org>
[briannorris: 4.4 rebase. Resolved conflicts; change drm_master_relax to
'bool' to match usage and debugfs_create_bool() API change]
Signed-off-by: Brian Norris <briannorris@chromium.org>
Change-Id: I7b8a00ca8e21321019875012a24cb88fea3c1317
Reviewed-on: https://chromium-review.googlesource.com/267810
Trybot-Ready: Bryan Freed <bfreed@chromium.org>
Tested-by: Bryan Freed <bfreed@chromium.org>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
Commit-Queue: Bryan Freed <bfreed@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/339283
Commit-Queue: Brian Norris <briannorris@chromium.org>
Tested-by: Brian Norris <briannorris@chromium.org>
Conflicts:
drivers/gpu/drm/drm_ioctl.c
include/drm/drmP.h (variable moved to include/drm/drm_drv.h)
[rebase412(groeck): Context conflicts]
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Conflicts:
drivers/gpu/drm/drm_ioctl.c
[rebase414(groeck): drm_ioctl() reorganized]
Signed-off-by: Guenter Roeck <groeck@chromium.org>
[rebase510(groeck):
Context conflicts (include/drm/drm_drv.h)
Adjust for changed permission handling in v5.10
]
Signed-off-by: Guenter Roeck <groeck@chromium.org>
[rebase515(groeck):
squashed:
FIXUP: CHROMIUM: drm: Add drm_master_relax debugfs file (non-root set/drop master ioctls)
]
Signed-off-by: Guenter Roeck <groeck@chromium.org>
---
drivers/gpu/drm/drm_auth.c | 8 ++++++--
drivers/gpu/drm/drm_drv.c | 8 +++++++-
include/drm/drm_drv.h | 2 ++
3 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index 6899b3dc1f12a553c52043c2b73c985e72f627b9..08fd4cf348157bfad4316a889df562825f21a260 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -235,8 +235,12 @@ static int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
static int
drm_master_check_perm(struct drm_device *dev, struct drm_file *file_priv)
{
- if (file_priv->was_master &&
- rcu_access_pointer(file_priv->pid) == task_tgid(current))
+ /*
+ * Despite the above explanation and reasoning, we still have to check
+ * drm_master_relax. With frecon, the was_master flag is true, but the
+ * file pid and the task pid pointers (and the actual PIDs) don't match.
+ */
+ if ((drm_master_relax || file_priv->pid == task_pid(current)) && file_priv->was_master)
return 0;
if (!capable(CAP_SYS_ADMIN))
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 535f16e7882e706b1e0573345b58711b7f6f2d94..b93dbf6601fef4c7e09c733cf9fd6aa00d260115 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -1064,6 +1064,9 @@ static int drm_stub_open(struct inode *inode, struct file *filp)
return err;
}
+/* When set to true, allow set/drop master ioctls as normal user */
+bool drm_master_relax;
+
static const struct file_operations drm_stub_fops = {
.owner = THIS_MODULE,
.open = drm_stub_open,
@@ -1075,7 +1078,7 @@ static void drm_core_exit(void)
drm_privacy_screen_lookup_exit();
accel_core_exit();
unregister_chrdev(DRM_MAJOR, "drm");
- debugfs_remove(drm_debugfs_root);
+ debugfs_remove_recursive(drm_debugfs_root);
drm_sysfs_destroy();
idr_destroy(&drm_minors_idr);
drm_connector_ida_destroy();
@@ -1097,6 +1100,9 @@ static int __init drm_core_init(void)
drm_debugfs_root = debugfs_create_dir("dri", NULL);
+ debugfs_create_bool("drm_master_relax", S_IRUSR | S_IWUSR,
+ drm_debugfs_root, &drm_master_relax);
+
ret = register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops);
if (ret < 0)
goto error;
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index e2640dc64e081cc9c82f4c15db3da40bfd26c6fe..d35b777c199c084ae9e9d40e38d5dd6826b8c312 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -458,6 +458,8 @@ void *__devm_drm_dev_alloc(struct device *parent,
const struct drm_driver *driver,
size_t size, size_t offset);
+extern bool drm_master_relax;
+
/**
* devm_drm_dev_alloc - Resource managed allocation of a &drm_device instance
* @parent: Parent device object
--
2.43.0.472.g3155946c3a-goog