| From 1ae71d605e6b082c25281c6aee333c500881ea6e 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 2ed2585ded3784882dd90260e070e27017a6d1f2..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_pid(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.rc2.451.g8631bc7472-goog |
| |