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
8 drm/r128: Add test for initialisation to all ioctls that require it
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
16 This adds a macro for the common initialisation test and changes all
17 ioctl implementations that require prior initialisation to use that
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.
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>
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(-)
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
40 + if (dev->dev_private) {
41 + DRM_DEBUG("called when already initialized\n");
45 dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER);
48 @@ -651,6 +656,8 @@ int r128_cce_start(struct drm_device *de
50 LOCK_TEST_WITH_RETURN(dev, file_priv);
52 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
54 if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
55 DRM_DEBUG("while CCE running\n");
57 @@ -673,6 +680,8 @@ int r128_cce_stop(struct drm_device *dev
59 LOCK_TEST_WITH_RETURN(dev, file_priv);
61 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
63 /* Flush any pending CCE commands. This ensures any outstanding
64 * commands are exectuted by the engine before we turn it off.
66 @@ -710,10 +719,7 @@ int r128_cce_reset(struct drm_device *de
68 LOCK_TEST_WITH_RETURN(dev, file_priv);
71 - DRM_DEBUG("called before init done\n");
74 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
76 r128_do_cce_reset(dev_priv);
78 @@ -730,6 +736,8 @@ int r128_cce_idle(struct drm_device *dev
80 LOCK_TEST_WITH_RETURN(dev, file_priv);
82 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
84 if (dev_priv->cce_running) {
85 r128_do_cce_flush(dev_priv);
87 @@ -743,6 +751,8 @@ int r128_engine_reset(struct drm_device
89 LOCK_TEST_WITH_RETURN(dev, file_priv);
91 + DEV_INIT_TEST_WITH_RETURN(dev->dev_private);
93 return r128_do_engine_reset(dev);
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_
102 +#define DEV_INIT_TEST_WITH_RETURN(_dev_priv) \
104 + if (!_dev_priv) { \
105 + DRM_ERROR("called with no initialization\n"); \
110 #define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \
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)
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;
124 LOCK_TEST_WITH_RETURN(dev, file_priv);
126 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
128 RING_SPACE_TEST_WITH_RETURN(dev_priv);
130 + sarea_priv = dev_priv->sarea_priv;
132 if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
133 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
135 @@ -1312,6 +1316,8 @@ static int r128_cce_flip(struct drm_devi
137 LOCK_TEST_WITH_RETURN(dev, file_priv);
139 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
141 RING_SPACE_TEST_WITH_RETURN(dev_priv);
143 if (!dev_priv->page_flipping)
144 @@ -1331,6 +1337,8 @@ static int r128_cce_swap(struct drm_devi
146 LOCK_TEST_WITH_RETURN(dev, file_priv);
148 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
150 RING_SPACE_TEST_WITH_RETURN(dev_priv);
152 if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
153 @@ -1354,10 +1362,7 @@ static int r128_cce_vertex(struct drm_de
155 LOCK_TEST_WITH_RETURN(dev, file_priv);
158 - DRM_ERROR("called with no initialization\n");
161 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
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
167 LOCK_TEST_WITH_RETURN(dev, file_priv);
170 - DRM_ERROR("called with no initialization\n");
173 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
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
179 LOCK_TEST_WITH_RETURN(dev, file_priv);
181 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
183 DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx);
185 if (blit->idx < 0 || blit->idx >= dma->buf_count) {
186 @@ -1501,6 +1505,8 @@ static int r128_cce_depth(struct drm_dev
188 LOCK_TEST_WITH_RETURN(dev, file_priv);
190 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
192 RING_SPACE_TEST_WITH_RETURN(dev_priv);
195 @@ -1531,6 +1537,8 @@ static int r128_cce_stipple(struct drm_d
197 LOCK_TEST_WITH_RETURN(dev, file_priv);
199 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
201 if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
204 @@ -1555,10 +1563,7 @@ static int r128_cce_indirect(struct drm_
206 LOCK_TEST_WITH_RETURN(dev, file_priv);
209 - DRM_ERROR("called with no initialization\n");
212 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
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;
221 - DRM_ERROR("called with no initialization\n");
224 + DEV_INIT_TEST_WITH_RETURN(dev_priv);
226 DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);