diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-03-12 14:52:55 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-04-01 19:01:51 -0400 |
commit | 67c538878517bc45d1ac523fde97c8b12e180754 (patch) | |
tree | f8aa0510d82202c258e549a6d23787ba05ec86fb /drivers/gpu/drm/i915 | |
parent | 211dfa81845fb609e91816791df78d60426777c0 (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.c | 21 |
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 | |||
2261 | err_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 | ||
2268 | static void i965_write_fence_reg(struct drm_i915_fence_reg *reg) | 2271 | static void i965_write_fence_reg(struct drm_i915_fence_reg *reg) |