summaryrefslogtreecommitdiffstats
path: root/chromium/docs/website/site/chromium-os/how-tos-and-troubleshooting/mainline-kernel-on-kevin-chromebook-plus/chrome-os-mainline-kernel-on-kevin-chromebook-plus/0002-CHROMIUM-drm-Add-drm_master_relax-debugfs-file-non-r.patch
blob: c4efc10606fd8826c17a078c9ddca1a86b5cde22 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
From 2291f9f43f528d8f18893ab4669bae482239f719 Mon Sep 17 00:00:00 2001
From: Nicolas Boichat <nicolas@boichat.ch>
Date: Fri, 17 Jan 2014 11:29:25 +0800
Subject: [PATCH 2/8] 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>
[tfiga: Rebase onto Linux 4.20]
Signed-off-by: Tomasz Figa <tfiga@chromium.org>
---
 drivers/gpu/drm/drm_drv.c   | 11 ++++++++++-
 drivers/gpu/drm/drm_ioctl.c | 13 ++++++++++++-
 include/drm/drm_drv.h       |  1 +
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 7e7d7e0efff083..9cf4ae4d678a9a 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -948,6 +948,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,
@@ -957,7 +960,7 @@ static const struct file_operations drm_stub_fops = {
 static void drm_core_exit(void)
 {
 	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();
@@ -983,6 +986,12 @@ static int __init drm_core_init(void)
 		goto error;
 	}
 
+	if (!debugfs_create_bool("drm_master_relax", S_IRUSR | S_IWUSR,
+				drm_debugfs_root, &drm_master_relax)) {
+		DRM_ERROR(
+			  "Cannot create /sys/kernel/debug/dri/drm_master_relax\n");
+	}
+
 	ret = register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops);
 	if (ret < 0)
 		goto error;
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 94bd872d56c48b..22a6c32e4039a8 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -790,6 +790,7 @@ long drm_ioctl(struct file *filp,
 	char *kdata = NULL;
 	unsigned int in_size, out_size, drv_size, ksize;
 	bool is_driver_ioctl;
+	int flags;
 
 	dev = file_priv->minor->dev;
 
@@ -823,6 +824,15 @@ long drm_ioctl(struct file *filp,
 		  (long)old_encode_dev(file_priv->minor->kdev->devt),
 		  file_priv->authenticated, ioctl->name);
 
+	flags = ioctl->flags;
+	if (drm_master_relax) {
+		if (nr == DRM_IOCTL_NR(DRM_IOCTL_SET_MASTER))
+			flags = DRM_AUTH;
+		else if (nr == DRM_IOCTL_NR(DRM_IOCTL_DROP_MASTER))
+			flags = DRM_MASTER;
+	}
+
+
 	/* Do not trust userspace, use our own definition */
 	func = ioctl->func;
 
@@ -850,7 +860,8 @@ long drm_ioctl(struct file *filp,
 	if (ksize > in_size)
 		memset(kdata + in_size, 0, ksize - in_size);
 
-	retcode = drm_ioctl_kernel(filp, func, kdata, ioctl->flags);
+	retcode = drm_ioctl_kernel(filp, func, kdata, flags);
+
 	if (copy_to_user((void __user *)arg, kdata, out_size) != 0)
 		retcode = -EFAULT;
 
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 252dd216cc607e..ebde29c1fc2c83 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -612,6 +612,7 @@ struct drm_driver {
 };
 
 extern unsigned int drm_debug;
+extern bool drm_master_relax;
 
 int drm_dev_init(struct drm_device *dev,
 		 struct drm_driver *driver,
-- 
2.20.0.rc2.403.gdbc3b29805-goog