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
*/
if (args->offset > obj->size || args->size > obj->size ||
args->offset + args->size > obj->size) {
*/
if (args->offset > obj->size || args->size > obj->size ||
args->offset + args->size > obj->size) {
- drm_gem_object_unreference_unlocked(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)) {
}
if (i915_gem_object_needs_bit17_swizzle(obj)) {
drm_gem_object_unreference_unlocked(obj);
drm_gem_object_unreference_unlocked(obj);
user_data = (char __user *) (uintptr_t) args->data_ptr;
remain = args->size;
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);
mutex_lock(&dev->struct_mutex);
*/
if (args->offset > obj->size || args->size > obj->size ||
args->offset + args->size > obj->size) {
*/
if (args->offset > obj->size || args->size > obj->size ||
args->offset + args->size > obj->size) {
- drm_gem_object_unreference_unlocked(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
}
/* We can only do the GTT pwrite on untiled buffers, as otherwise
DRM_INFO("pwrite failed %d\n", ret);
#endif
DRM_INFO("pwrite failed %d\n", ret);
#endif
drm_gem_object_unreference_unlocked(obj);
drm_gem_object_unreference_unlocked(obj);