aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-09-26 15:50:05 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2010-10-03 09:16:17 -0400
commitce9d419dbecc292cc3e06e8b1d6d123d3fa813a4 (patch)
treea65b65d58e52bb05b3f08c6610f5d6345e5f4879 /drivers/gpu/drm/i915
parentab7ad7f6451580aa7eccc0ba62807c872088a8f9 (diff)
drm/i915: Sanity check pread/pwrite
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> Cc: stable@kernel.org
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index cfe597865f5d..7749e78a7300 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -477,8 +477,15 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
477 */ 477 */
478 if (args->offset > obj->size || args->size > obj->size || 478 if (args->offset > obj->size || args->size > obj->size ||
479 args->offset + args->size > obj->size) { 479 args->offset + args->size > obj->size) {
480 drm_gem_object_unreference_unlocked(obj); 480 ret = -EINVAL;
481 return -EINVAL; 481 goto err;
482 }
483
484 if (!access_ok(VERIFY_WRITE,
485 (char __user *)(uintptr_t)args->data_ptr,
486 args->size)) {
487 ret = -EFAULT;
488 goto err;
482 } 489 }
483 490
484 if (i915_gem_object_needs_bit17_swizzle(obj)) { 491 if (i915_gem_object_needs_bit17_swizzle(obj)) {
@@ -490,8 +497,8 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
490 file_priv); 497 file_priv);
491 } 498 }
492 499
500err:
493 drm_gem_object_unreference_unlocked(obj); 501 drm_gem_object_unreference_unlocked(obj);
494
495 return ret; 502 return ret;
496} 503}
497 504
@@ -580,8 +587,6 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
580 587
581 user_data = (char __user *) (uintptr_t) args->data_ptr; 588 user_data = (char __user *) (uintptr_t) args->data_ptr;
582 remain = args->size; 589 remain = args->size;
583 if (!access_ok(VERIFY_READ, user_data, remain))
584 return -EFAULT;
585 590
586 591
587 mutex_lock(&dev->struct_mutex); 592 mutex_lock(&dev->struct_mutex);
@@ -940,8 +945,15 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
940 */ 945 */
941 if (args->offset > obj->size || args->size > obj->size || 946 if (args->offset > obj->size || args->size > obj->size ||
942 args->offset + args->size > obj->size) { 947 args->offset + args->size > obj->size) {
943 drm_gem_object_unreference_unlocked(obj); 948 ret = -EINVAL;
944 return -EINVAL; 949 goto err;
950 }
951
952 if (!access_ok(VERIFY_READ,
953 (char __user *)(uintptr_t)args->data_ptr,
954 args->size)) {
955 ret = -EFAULT;
956 goto err;
945 } 957 }
946 958
947 /* We can only do the GTT pwrite on untiled buffers, as otherwise 959 /* We can only do the GTT pwrite on untiled buffers, as otherwise
@@ -975,8 +987,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
975 DRM_INFO("pwrite failed %d\n", ret); 987 DRM_INFO("pwrite failed %d\n", ret);
976#endif 988#endif
977 989
990err:
978 drm_gem_object_unreference_unlocked(obj); 991 drm_gem_object_unreference_unlocked(obj);
979
980 return ret; 992 return ret;
981} 993}
982 994