]>
Commit | Line | Data |
---|---|---|
945f7f36 GKH |
1 | From 7dc482dfeeeefcfd000d4271c4626937406756d7 Mon Sep 17 00:00:00 2001 |
2 | From: Ben Hutchings <ben@decadent.org.uk> | |
3 | Date: Sun, 23 Aug 2009 16:59:04 +0100 | |
4 | Subject: drm/r128: Add test for initialisation to all ioctls that require it | |
5 | ||
6 | From: Ben Hutchings <ben@decadent.org.uk> | |
7 | ||
8 | commit 7dc482dfeeeefcfd000d4271c4626937406756d7 upstream. | |
9 | ||
10 | Almost all r128's private ioctls require that the CCE state has | |
11 | already been initialised. However, most do not test that this has | |
12 | been done, and will proceed to dereference a null pointer. This may | |
13 | result in a security vulnerability, since some ioctls are | |
14 | unprivileged. | |
15 | ||
16 | This adds a macro for the common initialisation test and changes all | |
17 | ioctl implementations that require prior initialisation to use that | |
18 | macro. | |
19 | ||
20 | Also, r128_do_init_cce() does not test that the CCE state has not | |
21 | been initialised already. Repeated initialisation may lead to a crash | |
22 | or resource leak. This adds that test. | |
23 | ||
24 | Signed-off-by: Ben Hutchings <ben@decadent.org.uk> | |
25 | Signed-off-by: Dave Airlie <airlied@redhat.com> | |
26 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
27 | ||
28 | ||
29 | --- | |
30 | drivers/gpu/drm/r128/r128_cce.c | 18 ++++++++++++++---- | |
31 | drivers/gpu/drm/r128/r128_drv.h | 8 ++++++++ | |
32 | drivers/gpu/drm/r128/r128_state.c | 36 +++++++++++++++++++----------------- | |
33 | 3 files changed, 41 insertions(+), 21 deletions(-) | |
34 | ||
35 | --- a/drivers/gpu/drm/r128/r128_cce.c | |
36 | +++ b/drivers/gpu/drm/r128/r128_cce.c | |
37 | @@ -353,6 +353,11 @@ static int r128_do_init_cce(struct drm_d | |
38 | ||
39 | DRM_DEBUG("\n"); | |
40 | ||
41 | + if (dev->dev_private) { | |
42 | + DRM_DEBUG("called when already initialized\n"); | |
43 | + return -EINVAL; | |
44 | + } | |
45 | + | |
46 | dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER); | |
47 | if (dev_priv == NULL) | |
48 | return -ENOMEM; | |
49 | @@ -651,6 +656,8 @@ int r128_cce_start(struct drm_device *de | |
50 | ||
51 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
52 | ||
53 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
54 | + | |
55 | if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) { | |
56 | DRM_DEBUG("while CCE running\n"); | |
57 | return 0; | |
58 | @@ -673,6 +680,8 @@ int r128_cce_stop(struct drm_device *dev | |
59 | ||
60 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
61 | ||
62 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
63 | + | |
64 | /* Flush any pending CCE commands. This ensures any outstanding | |
65 | * commands are exectuted by the engine before we turn it off. | |
66 | */ | |
67 | @@ -710,10 +719,7 @@ int r128_cce_reset(struct drm_device *de | |
68 | ||
69 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
70 | ||
71 | - if (!dev_priv) { | |
72 | - DRM_DEBUG("called before init done\n"); | |
73 | - return -EINVAL; | |
74 | - } | |
75 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
76 | ||
77 | r128_do_cce_reset(dev_priv); | |
78 | ||
79 | @@ -730,6 +736,8 @@ int r128_cce_idle(struct drm_device *dev | |
80 | ||
81 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
82 | ||
83 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
84 | + | |
85 | if (dev_priv->cce_running) { | |
86 | r128_do_cce_flush(dev_priv); | |
87 | } | |
88 | @@ -743,6 +751,8 @@ int r128_engine_reset(struct drm_device | |
89 | ||
90 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
91 | ||
92 | + DEV_INIT_TEST_WITH_RETURN(dev->dev_private); | |
93 | + | |
94 | return r128_do_engine_reset(dev); | |
95 | } | |
96 | ||
97 | --- a/drivers/gpu/drm/r128/r128_drv.h | |
98 | +++ b/drivers/gpu/drm/r128/r128_drv.h | |
99 | @@ -418,6 +418,14 @@ static __inline__ void r128_update_ring_ | |
100 | * Misc helper macros | |
101 | */ | |
102 | ||
103 | +#define DEV_INIT_TEST_WITH_RETURN(_dev_priv) \ | |
104 | +do { \ | |
105 | + if (!_dev_priv) { \ | |
106 | + DRM_ERROR("called with no initialization\n"); \ | |
107 | + return -EINVAL; \ | |
108 | + } \ | |
109 | +} while (0) | |
110 | + | |
111 | #define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \ | |
112 | do { \ | |
113 | drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; \ | |
114 | --- a/drivers/gpu/drm/r128/r128_state.c | |
115 | +++ b/drivers/gpu/drm/r128/r128_state.c | |
116 | @@ -1244,14 +1244,18 @@ static void r128_cce_dispatch_stipple(st | |
117 | static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) | |
118 | { | |
119 | drm_r128_private_t *dev_priv = dev->dev_private; | |
120 | - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; | |
121 | + drm_r128_sarea_t *sarea_priv; | |
122 | drm_r128_clear_t *clear = data; | |
123 | DRM_DEBUG("\n"); | |
124 | ||
125 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
126 | ||
127 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
128 | + | |
129 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | |
130 | ||
131 | + sarea_priv = dev_priv->sarea_priv; | |
132 | + | |
133 | if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS) | |
134 | sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; | |
135 | ||
136 | @@ -1312,6 +1316,8 @@ static int r128_cce_flip(struct drm_devi | |
137 | ||
138 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
139 | ||
140 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
141 | + | |
142 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | |
143 | ||
144 | if (!dev_priv->page_flipping) | |
145 | @@ -1331,6 +1337,8 @@ static int r128_cce_swap(struct drm_devi | |
146 | ||
147 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
148 | ||
149 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
150 | + | |
151 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | |
152 | ||
153 | if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS) | |
154 | @@ -1354,10 +1362,7 @@ static int r128_cce_vertex(struct drm_de | |
155 | ||
156 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
157 | ||
158 | - if (!dev_priv) { | |
159 | - DRM_ERROR("called with no initialization\n"); | |
160 | - return -EINVAL; | |
161 | - } | |
162 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
163 | ||
164 | DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", | |
165 | DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard); | |
166 | @@ -1410,10 +1415,7 @@ static int r128_cce_indices(struct drm_d | |
167 | ||
168 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
169 | ||
170 | - if (!dev_priv) { | |
171 | - DRM_ERROR("called with no initialization\n"); | |
172 | - return -EINVAL; | |
173 | - } | |
174 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
175 | ||
176 | DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID, | |
177 | elts->idx, elts->start, elts->end, elts->discard); | |
178 | @@ -1476,6 +1478,8 @@ static int r128_cce_blit(struct drm_devi | |
179 | ||
180 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
181 | ||
182 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
183 | + | |
184 | DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx); | |
185 | ||
186 | if (blit->idx < 0 || blit->idx >= dma->buf_count) { | |
187 | @@ -1501,6 +1505,8 @@ static int r128_cce_depth(struct drm_dev | |
188 | ||
189 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
190 | ||
191 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
192 | + | |
193 | RING_SPACE_TEST_WITH_RETURN(dev_priv); | |
194 | ||
195 | ret = -EINVAL; | |
196 | @@ -1531,6 +1537,8 @@ static int r128_cce_stipple(struct drm_d | |
197 | ||
198 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
199 | ||
200 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
201 | + | |
202 | if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32))) | |
203 | return -EFAULT; | |
204 | ||
205 | @@ -1555,10 +1563,7 @@ static int r128_cce_indirect(struct drm_ | |
206 | ||
207 | LOCK_TEST_WITH_RETURN(dev, file_priv); | |
208 | ||
209 | - if (!dev_priv) { | |
210 | - DRM_ERROR("called with no initialization\n"); | |
211 | - return -EINVAL; | |
212 | - } | |
213 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
214 | ||
215 | DRM_DEBUG("idx=%d s=%d e=%d d=%d\n", | |
216 | indirect->idx, indirect->start, indirect->end, | |
217 | @@ -1620,10 +1625,7 @@ static int r128_getparam(struct drm_devi | |
218 | drm_r128_getparam_t *param = data; | |
219 | int value; | |
220 | ||
221 | - if (!dev_priv) { | |
222 | - DRM_ERROR("called with no initialization\n"); | |
223 | - return -EINVAL; | |
224 | - } | |
225 | + DEV_INIT_TEST_WITH_RETURN(dev_priv); | |
226 | ||
227 | DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); | |
228 |