Chuck Ebbert 643d353
From ce9d419dbecc292cc3e06e8b1d6d123d3fa813a4 Mon Sep 17 00:00:00 2001
Chuck Ebbert 643d353
From: Chris Wilson <chris@chris-wilson.co.uk>
Chuck Ebbert 643d353
Date: Sun, 26 Sep 2010 20:50:05 +0100
Chuck Ebbert 643d353
Subject: drm/i915: Sanity check pread/pwrite
Chuck Ebbert 643d353
Chuck Ebbert 643d353
From: Chris Wilson <chris@chris-wilson.co.uk>
Chuck Ebbert 643d353
Chuck Ebbert 643d353
commit ce9d419dbecc292cc3e06e8b1d6d123d3fa813a4 upstream.
Chuck Ebbert 643d353
Chuck Ebbert 643d353
Move the access control up from the fast paths, which are no longer
Chuck Ebbert 643d353
universally taken first, up into the caller. This then duplicates some
Chuck Ebbert 643d353
sanity checking along the slow paths, but is much simpler.
Chuck Ebbert 643d353
Tracked as CVE-2010-2962.
Chuck Ebbert 643d353
Chuck Ebbert 643d353
Reported-by: Kees Cook <kees@ubuntu.com>
Chuck Ebbert 643d353
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Chuck Ebbert 643d353
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Chuck Ebbert 643d353
Chuck Ebbert 643d353
---
Chuck Ebbert 643d353
 drivers/gpu/drm/i915/i915_gem.c |   28 ++++++++++++++++++++--------
Chuck Ebbert 643d353
 1 file changed, 20 insertions(+), 8 deletions(-)
Chuck Ebbert 643d353
Chuck Ebbert 643d353
--- a/drivers/gpu/drm/i915/i915_gem.c
Chuck Ebbert 643d353
+++ b/drivers/gpu/drm/i915/i915_gem.c
Chuck Ebbert 643d353
@@ -465,8 +465,15 @@ i915_gem_pread_ioctl(struct drm_device *
Chuck Ebbert 643d353
 	 */
Chuck Ebbert 643d353
 	if (args->offset > obj->size || args->size > obj->size ||
Chuck Ebbert 643d353
 	    args->offset + args->size > obj->size) {
Chuck Ebbert 643d353
-		drm_gem_object_unreference_unlocked(obj);
Chuck Ebbert 643d353
-		return -EINVAL;
Chuck Ebbert 643d353
+		ret = -EINVAL;
Chuck Ebbert 643d353
+		goto err;
Chuck Ebbert 643d353
+	}
Chuck Ebbert 643d353
+
Chuck Ebbert 643d353
+	if (!access_ok(VERIFY_WRITE,
Chuck Ebbert 643d353
+		       (char __user *)(uintptr_t)args->data_ptr,
Chuck Ebbert 643d353
+		       args->size)) {
Chuck Ebbert 643d353
+		ret = -EFAULT;
Chuck Ebbert 643d353
+		goto err;
Chuck Ebbert 643d353
 	}
Chuck Ebbert 643d353
 
Chuck Ebbert 643d353
 	if (i915_gem_object_needs_bit17_swizzle(obj)) {
Chuck Ebbert 643d353
@@ -478,8 +485,8 @@ i915_gem_pread_ioctl(struct drm_device *
Chuck Ebbert 643d353
 							file_priv);
Chuck Ebbert 643d353
 	}
Chuck Ebbert 643d353
 
Chuck Ebbert 643d353
+err:
Chuck Ebbert 643d353
 	drm_gem_object_unreference_unlocked(obj);
Chuck Ebbert 643d353
-
Chuck Ebbert 643d353
 	return ret;
Chuck Ebbert 643d353
 }
Chuck Ebbert 643d353
 
Chuck Ebbert 643d353
@@ -568,8 +575,6 @@ i915_gem_gtt_pwrite_fast(struct drm_devi
Chuck Ebbert 643d353
 
Chuck Ebbert 643d353
 	user_data = (char __user *) (uintptr_t) args->data_ptr;
Chuck Ebbert 643d353
 	remain = args->size;
Chuck Ebbert 643d353
-	if (!access_ok(VERIFY_READ, user_data, remain))
Chuck Ebbert 643d353
-		return -EFAULT;
Chuck Ebbert 643d353
 
Chuck Ebbert 643d353
 
Chuck Ebbert 643d353
 	mutex_lock(&dev->struct_mutex);
Chuck Ebbert 643d353
@@ -928,8 +933,15 @@ i915_gem_pwrite_ioctl(struct drm_device
Chuck Ebbert 643d353
 	 */
Chuck Ebbert 643d353
 	if (args->offset > obj->size || args->size > obj->size ||
Chuck Ebbert 643d353
 	    args->offset + args->size > obj->size) {
Chuck Ebbert 643d353
-		drm_gem_object_unreference_unlocked(obj);
Chuck Ebbert 643d353
-		return -EINVAL;
Chuck Ebbert 643d353
+		ret = -EINVAL;
Chuck Ebbert 643d353
+		goto err;
Chuck Ebbert 643d353
+	}
Chuck Ebbert 643d353
+
Chuck Ebbert 643d353
+	if (!access_ok(VERIFY_READ,
Chuck Ebbert 643d353
+		       (char __user *)(uintptr_t)args->data_ptr,
Chuck Ebbert 643d353
+		       args->size)) {
Chuck Ebbert 643d353
+		ret = -EFAULT;
Chuck Ebbert 643d353
+		goto err;
Chuck Ebbert 643d353
 	}
Chuck Ebbert 643d353
 
Chuck Ebbert 643d353
 	/* We can only do the GTT pwrite on untiled buffers, as otherwise
Chuck Ebbert 643d353
@@ -963,8 +975,8 @@ i915_gem_pwrite_ioctl(struct drm_device
Chuck Ebbert 643d353
 		DRM_INFO("pwrite failed %d\n", ret);
Chuck Ebbert 643d353
 #endif
Chuck Ebbert 643d353
 
Chuck Ebbert 643d353
+err:
Chuck Ebbert 643d353
 	drm_gem_object_unreference_unlocked(obj);
Chuck Ebbert 643d353
-
Chuck Ebbert 643d353
 	return ret;
Chuck Ebbert 643d353
 }
Chuck Ebbert 643d353