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