]>
Commit | Line | Data |
---|---|---|
7691b2d1 GKH |
1 | From ce9d419dbecc292cc3e06e8b1d6d123d3fa813a4 Mon Sep 17 00:00:00 2001 |
2 | From: Chris Wilson <chris@chris-wilson.co.uk> | |
3 | Date: Sun, 26 Sep 2010 20:50:05 +0100 | |
4 | Subject: drm/i915: Sanity check pread/pwrite | |
5 | ||
6 | From: Chris Wilson <chris@chris-wilson.co.uk> | |
7 | ||
8 | commit ce9d419dbecc292cc3e06e8b1d6d123d3fa813a4 upstream. | |
9 | ||
10 | Move the access control up from the fast paths, which are no longer | |
11 | universally taken first, up into the caller. This then duplicates some | |
12 | sanity checking along the slow paths, but is much simpler. | |
13 | Tracked as CVE-2010-2962. | |
14 | ||
15 | Reported-by: Kees Cook <kees@ubuntu.com> | |
16 | Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> | |
17 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
18 | ||
19 | --- | |
20 | drivers/gpu/drm/i915/i915_gem.c | 28 ++++++++++++++++++++-------- | |
21 | 1 file changed, 20 insertions(+), 8 deletions(-) | |
22 | ||
23 | --- a/drivers/gpu/drm/i915/i915_gem.c | |
24 | +++ b/drivers/gpu/drm/i915/i915_gem.c | |
25 | @@ -465,8 +465,15 @@ i915_gem_pread_ioctl(struct drm_device * | |
26 | */ | |
27 | if (args->offset > obj->size || args->size > obj->size || | |
28 | args->offset + args->size > obj->size) { | |
29 | - drm_gem_object_unreference_unlocked(obj); | |
30 | - return -EINVAL; | |
31 | + ret = -EINVAL; | |
32 | + goto err; | |
33 | + } | |
34 | + | |
35 | + if (!access_ok(VERIFY_WRITE, | |
36 | + (char __user *)(uintptr_t)args->data_ptr, | |
37 | + args->size)) { | |
38 | + ret = -EFAULT; | |
39 | + goto err; | |
40 | } | |
41 | ||
42 | if (i915_gem_object_needs_bit17_swizzle(obj)) { | |
43 | @@ -478,8 +485,8 @@ i915_gem_pread_ioctl(struct drm_device * | |
44 | file_priv); | |
45 | } | |
46 | ||
47 | +err: | |
48 | drm_gem_object_unreference_unlocked(obj); | |
49 | - | |
50 | return ret; | |
51 | } | |
52 | ||
53 | @@ -568,8 +575,6 @@ i915_gem_gtt_pwrite_fast(struct drm_devi | |
54 | ||
55 | user_data = (char __user *) (uintptr_t) args->data_ptr; | |
56 | remain = args->size; | |
57 | - if (!access_ok(VERIFY_READ, user_data, remain)) | |
58 | - return -EFAULT; | |
59 | ||
60 | ||
61 | mutex_lock(&dev->struct_mutex); | |
62 | @@ -928,8 +933,15 @@ i915_gem_pwrite_ioctl(struct drm_device | |
63 | */ | |
64 | if (args->offset > obj->size || args->size > obj->size || | |
65 | args->offset + args->size > obj->size) { | |
66 | - drm_gem_object_unreference_unlocked(obj); | |
67 | - return -EINVAL; | |
68 | + ret = -EINVAL; | |
69 | + goto err; | |
70 | + } | |
71 | + | |
72 | + if (!access_ok(VERIFY_READ, | |
73 | + (char __user *)(uintptr_t)args->data_ptr, | |
74 | + args->size)) { | |
75 | + ret = -EFAULT; | |
76 | + goto err; | |
77 | } | |
78 | ||
79 | /* We can only do the GTT pwrite on untiled buffers, as otherwise | |
80 | @@ -963,8 +975,8 @@ i915_gem_pwrite_ioctl(struct drm_device | |
81 | DRM_INFO("pwrite failed %d\n", ret); | |
82 | #endif | |
83 | ||
84 | +err: | |
85 | drm_gem_object_unreference_unlocked(obj); | |
86 | - | |
87 | return ret; | |
88 | } | |
89 |