Commit ce9d419d authored by Chris Wilson's avatar Chris Wilson

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: default avatarKees Cook <kees@ubuntu.com>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: stable@kernel.org
parent ab7ad7f6
...@@ -477,8 +477,15 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, ...@@ -477,8 +477,15 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
*/ */
if (args->offset > obj->size || args->size > obj->size || if (args->offset > obj->size || args->size > obj->size ||
args->offset + args->size > obj->size) { args->offset + args->size > obj->size) {
drm_gem_object_unreference_unlocked(obj); ret = -EINVAL;
return -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)) { if (i915_gem_object_needs_bit17_swizzle(obj)) {
...@@ -490,8 +497,8 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, ...@@ -490,8 +497,8 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
file_priv); file_priv);
} }
err:
drm_gem_object_unreference_unlocked(obj); drm_gem_object_unreference_unlocked(obj);
return ret; return ret;
} }
...@@ -580,8 +587,6 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, ...@@ -580,8 +587,6 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
user_data = (char __user *) (uintptr_t) args->data_ptr; user_data = (char __user *) (uintptr_t) args->data_ptr;
remain = args->size; remain = args->size;
if (!access_ok(VERIFY_READ, user_data, remain))
return -EFAULT;
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
...@@ -940,8 +945,15 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, ...@@ -940,8 +945,15 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
*/ */
if (args->offset > obj->size || args->size > obj->size || if (args->offset > obj->size || args->size > obj->size ||
args->offset + args->size > obj->size) { args->offset + args->size > obj->size) {
drm_gem_object_unreference_unlocked(obj); ret = -EINVAL;
return -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 /* 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,8 +987,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
DRM_INFO("pwrite failed %d\n", ret); DRM_INFO("pwrite failed %d\n", ret);
#endif #endif
err:
drm_gem_object_unreference_unlocked(obj); drm_gem_object_unreference_unlocked(obj);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment