Skip to content

Commit

Permalink
drm/i915: Avoid NULL deref in get_pages() unwind after error.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Chris Wilson authored and Eric Anholt committed Mar 17, 2010
1 parent 59f2d0f commit 1f2b101
Showing 1 changed file with 12 additions and 9 deletions.
21 changes: 12 additions & 9 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1466,9 +1466,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]);

Expand Down Expand Up @@ -2251,7 +2248,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;
Expand All @@ -2274,18 +2270,25 @@ 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;
}

if (obj_priv->tiling_mode != I915_TILING_NONE)
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 sandybridge_write_fence_reg(struct drm_i915_fence_reg *reg)
Expand Down

0 comments on commit 1f2b101

Please sign in to comment.