| From dan.carpenter@oracle.com Fri Nov 18 11:32:12 2011 |
| From: Chris Wilson <chris@chris-wilson.co.uk> |
| Date: Tue, 15 Nov 2011 09:39:33 +0300 |
| Subject: drm/i915: Sanity check pread/pwrite |
| To: stable@vger.kernel.org |
| Cc: Greg Kroah-Hartman <greg@kroah.com>, Chris Wilson <chris@chris-wilson.co.uk> |
| Message-ID: <20111115063933.GD30827@elgon.mountain> |
| Content-Disposition: inline |
| |
| From: Chris Wilson <chris@chris-wilson.co.uk> |
| |
| commit ce9d419dbecc292cc3e06e8b1d6d123d3fa813a4 upstream. |
| |
| Move the access control up from the fast paths, which are no longer |
| universally taken first, up into the caller. This then duplicates some |
| sanity checking along the slow paths, but is much simpler. |
| Tracked as CVE-2010-2962. |
| |
| Reported-by: Kees Cook <kees@ubuntu.com> |
| Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> |
| Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/gpu/drm/i915/i915_gem.c | 28 ++++++++++++++++++++-------- |
| 1 file changed, 20 insertions(+), 8 deletions(-) |
| |
| --- a/drivers/gpu/drm/i915/i915_gem.c |
| +++ b/drivers/gpu/drm/i915/i915_gem.c |
| @@ -488,8 +488,15 @@ i915_gem_pread_ioctl(struct drm_device * |
| */ |
| if (args->offset > obj->size || args->size > obj->size || |
| args->offset + args->size > obj->size) { |
| - drm_gem_object_unreference(obj); |
| - return -EINVAL; |
| + ret = -EINVAL; |
| + goto err; |
| + } |
| + |
| + if (!access_ok(VERIFY_WRITE, |
| + (char __user *)(uintptr_t)args->data_ptr, |
| + args->size)) { |
| + ret = -EFAULT; |
| + goto err; |
| } |
| |
| if (i915_gem_object_needs_bit17_swizzle(obj)) { |
| @@ -501,8 +508,8 @@ i915_gem_pread_ioctl(struct drm_device * |
| file_priv); |
| } |
| |
| +err: |
| drm_gem_object_unreference(obj); |
| - |
| return ret; |
| } |
| |
| @@ -592,8 +599,6 @@ i915_gem_gtt_pwrite_fast(struct drm_devi |
| |
| user_data = (char __user *) (uintptr_t) args->data_ptr; |
| remain = args->size; |
| - if (!access_ok(VERIFY_READ, user_data, remain)) |
| - return -EFAULT; |
| |
| |
| mutex_lock(&dev->struct_mutex); |
| @@ -961,8 +966,15 @@ i915_gem_pwrite_ioctl(struct drm_device |
| */ |
| if (args->offset > obj->size || args->size > obj->size || |
| args->offset + args->size > obj->size) { |
| - drm_gem_object_unreference(obj); |
| - return -EINVAL; |
| + ret = -EINVAL; |
| + goto err; |
| + } |
| + |
| + if (!access_ok(VERIFY_READ, |
| + (char __user *)(uintptr_t)args->data_ptr, |
| + args->size)) { |
| + ret = -EFAULT; |
| + goto err; |
| } |
| |
| /* We can only do the GTT pwrite on untiled buffers, as otherwise |
| @@ -995,8 +1007,8 @@ i915_gem_pwrite_ioctl(struct drm_device |
| DRM_INFO("pwrite failed %d\n", ret); |
| #endif |
| |
| +err: |
| drm_gem_object_unreference(obj); |
| - |
| return ret; |
| } |
| |