aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-03-12 14:52:55 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-04-01 19:01:51 -0400
commit67c538878517bc45d1ac523fde97c8b12e180754 (patch)
treef8aa0510d82202c258e549a6d23787ba05ec86fb /drivers/gpu/drm/i915
parent211dfa81845fb609e91816791df78d60426777c0 (diff)
drm/i915: Avoid NULL deref in get_pages() unwind after error.
commit 1f2b10131f83f7caa67bf1273cec126b4283015d upstream. Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=15527 NULL pointer dereference in i915_gem_object_save_bit_17_swizzle BUG: unable to handle kernel NULL pointer dereference at (null) IP: [<f82b5d2b>] i915_gem_object_save_bit_17_swizzle+0x5b/0xc0 [i915] Call Trace: [<f82aea55>] ? i915_gem_object_put_pages+0x125/0x150 [i915] [<f82aeb71>] ? i915_gem_object_get_pages+0xf1/0x110 [i915] [<f82b0de8>] ? i915_gem_object_bind_to_gtt+0xb8/0x2a0 [i915] [<c02db74d>] ? drm_mm_get_block_generic+0x4d/0x180 [<f82b11cd>] ? i915_gem_mmap_gtt_ioctl+0x16d/0x240 [i915] [<f82ae786>] ? i915_gem_madvise_ioctl+0x86/0x120 [i915] Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Reported-by: maciej.rutecki@gmail.com Cc: stable@kernel.org Reviewed-by: Eric Anholt <eric@anholt.net> Signed-off-by: Eric Anholt <eric@anholt.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index ec8a0d7ffa39..fd099a1e9df0 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1470,9 +1470,6 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
1470 obj_priv->dirty = 0; 1470 obj_priv->dirty = 0;
1471 1471
1472 for (i = 0; i < page_count; i++) { 1472 for (i = 0; i < page_count; i++) {
1473 if (obj_priv->pages[i] == NULL)
1474 break;
1475
1476 if (obj_priv->dirty) 1473 if (obj_priv->dirty)
1477 set_page_dirty(obj_priv->pages[i]); 1474 set_page_dirty(obj_priv->pages[i]);
1478 1475
@@ -2228,7 +2225,6 @@ i915_gem_object_get_pages(struct drm_gem_object *obj,
2228 struct address_space *mapping; 2225 struct address_space *mapping;
2229 struct inode *inode; 2226 struct inode *inode;
2230 struct page *page; 2227 struct page *page;
2231 int ret;
2232 2228
2233 if (obj_priv->pages_refcount++ != 0) 2229 if (obj_priv->pages_refcount++ != 0)
2234 return 0; 2230 return 0;
@@ -2251,11 +2247,9 @@ i915_gem_object_get_pages(struct drm_gem_object *obj,
2251 mapping_gfp_mask (mapping) | 2247 mapping_gfp_mask (mapping) |
2252 __GFP_COLD | 2248 __GFP_COLD |
2253 gfpmask); 2249 gfpmask);
2254 if (IS_ERR(page)) { 2250 if (IS_ERR(page))
2255 ret = PTR_ERR(page); 2251 goto err_pages;
2256 i915_gem_object_put_pages(obj); 2252
2257 return ret;
2258 }
2259 obj_priv->pages[i] = page; 2253 obj_priv->pages[i] = page;
2260 } 2254 }
2261 2255
@@ -2263,6 +2257,15 @@ i915_gem_object_get_pages(struct drm_gem_object *obj,
2263 i915_gem_object_do_bit_17_swizzle(obj); 2257 i915_gem_object_do_bit_17_swizzle(obj);
2264 2258
2265 return 0; 2259 return 0;
2260
2261err_pages:
2262 while (i--)
2263 page_cache_release(obj_priv->pages[i]);
2264
2265 drm_free_large(obj_priv->pages);
2266 obj_priv->pages = NULL;
2267 obj_priv->pages_refcount--;
2268 return PTR_ERR(page);
2266} 2269}
2267 2270
2268static void i965_write_fence_reg(struct drm_i915_fence_reg *reg) 2271static void i965_write_fence_reg(struct drm_i915_fence_reg *reg)