diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-03-12 19:52:55 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-04-01 15:58:47 -0700 |
commit | 710b70e8150e412aa809fadb028147952c56a4cc (patch) | |
tree | 4006a787ef5960fc15dd119093f590bafc7dc287 /drivers/gpu | |
parent | 7b6c1753bc0ee455adf4f4ed489a367c7dc7c432 (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')
-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 04da731a70ab..1e9c66a96907 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) obj_priv->dirty = 0; for (i = 0; i < page_count; i++) { - if (obj_priv->pages[i] == NULL) - break; - if (obj_priv->dirty) set_page_dirty(obj_priv->pages[i]); @@ -2246,7 +2243,6 @@ i915_gem_object_get_pages(struct drm_gem_object *obj, struct address_space *mapping; struct inode *inode; struct page *page; - int ret; if (obj_priv->pages_refcount++ != 0) return 0; @@ -2269,11 +2265,9 @@ i915_gem_object_get_pages(struct drm_gem_object *obj, mapping_gfp_mask (mapping) | __GFP_COLD | gfpmask); - if (IS_ERR(page)) { - ret = PTR_ERR(page); - i915_gem_object_put_pages(obj); - return ret; - } + if (IS_ERR(page)) + goto err_pages; + obj_priv->pages[i] = page; } @@ -2281,6 +2275,15 @@ i915_gem_object_get_pages(struct drm_gem_object *obj, i915_gem_object_do_bit_17_swizzle(obj); return 0; + +err_pages: + while (i--) + page_cache_release(obj_priv->pages[i]); + + drm_free_large(obj_priv->pages); + obj_priv->pages = NULL; + obj_priv->pages_refcount--; + return PTR_ERR(page); } static void i965_write_fence_reg(struct drm_i915_fence_reg *reg) |