diff options
Diffstat (limited to 'meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.33-copy-checks.patch')
-rw-r--r-- | meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.33-copy-checks.patch | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.33-copy-checks.patch b/meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.33-copy-checks.patch new file mode 100644 index 0000000000..720fda24e8 --- /dev/null +++ b/meta-moblin/packages/linux/linux-moblin-2.6.31.5/linux-2.6.33-copy-checks.patch | |||
@@ -0,0 +1,275 @@ | |||
1 | From 524a1da3c45683cec77480acc6cab1d33ae8d5cb Mon Sep 17 00:00:00 2001 | ||
2 | From: Arjan van de Ven <arjan@linux.intel.com> | ||
3 | Date: Sat, 26 Sep 2009 12:36:21 +0200 | ||
4 | Subject: [PATCH] x86: Use __builtin_object_size to validate the buffer size for copy_from_user | ||
5 | |||
6 | gcc (4.x) supports the __builtin_object_size() builtin, which reports the | ||
7 | size of an object that a pointer point to, when known at compile time. | ||
8 | If the buffer size is not known at compile time, a constant -1 is returned. | ||
9 | |||
10 | This patch uses this feature to add a sanity check to copy_from_user(); | ||
11 | if the target buffer is known to be smaller than the copy size, the copy | ||
12 | is aborted and a WARNing is emitted in memory debug mode. | ||
13 | |||
14 | These extra checks compile away when the object size is not known, | ||
15 | or if both the buffer size and the copy length are constants. | ||
16 | |||
17 | Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> | ||
18 | Reviewed-by: Ingo Molnar <mingo@elte.hu> | ||
19 | --- | ||
20 | arch/x86/include/asm/uaccess_32.h | 19 ++++++++++++++++++- | ||
21 | arch/x86/include/asm/uaccess_64.h | 19 ++++++++++++++++++- | ||
22 | arch/x86/kernel/x8664_ksyms_64.c | 2 +- | ||
23 | arch/x86/lib/copy_user_64.S | 4 ++-- | ||
24 | arch/x86/lib/usercopy_32.c | 4 ++-- | ||
25 | include/linux/compiler-gcc4.h | 2 ++ | ||
26 | include/linux/compiler.h | 4 ++++ | ||
27 | 7 files changed, 47 insertions(+), 7 deletions(-) | ||
28 | |||
29 | diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h | ||
30 | index 632fb44..582d6ae 100644 | ||
31 | --- a/arch/x86/include/asm/uaccess_32.h | ||
32 | +++ b/arch/x86/include/asm/uaccess_32.h | ||
33 | @@ -187,9 +187,26 @@ __copy_from_user_inatomic_nocache(void *to, const void __user *from, | ||
34 | |||
35 | unsigned long __must_check copy_to_user(void __user *to, | ||
36 | const void *from, unsigned long n); | ||
37 | -unsigned long __must_check copy_from_user(void *to, | ||
38 | +unsigned long __must_check _copy_from_user(void *to, | ||
39 | const void __user *from, | ||
40 | unsigned long n); | ||
41 | + | ||
42 | +static inline unsigned long __must_check copy_from_user(void *to, | ||
43 | + const void __user *from, | ||
44 | + unsigned long n) | ||
45 | +{ | ||
46 | + int sz = __compiletime_object_size(to); | ||
47 | + int ret = -EFAULT; | ||
48 | + | ||
49 | + if (likely(sz == -1 || sz >= n)) | ||
50 | + ret = _copy_from_user(to, from, n); | ||
51 | +#ifdef CONFIG_DEBUG_VM | ||
52 | + else | ||
53 | + WARN(1, "Buffer overflow detected!\n"); | ||
54 | +#endif | ||
55 | + return ret; | ||
56 | +} | ||
57 | + | ||
58 | long __must_check strncpy_from_user(char *dst, const char __user *src, | ||
59 | long count); | ||
60 | long __must_check __strncpy_from_user(char *dst, | ||
61 | diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h | ||
62 | index db24b21..ce6fec7 100644 | ||
63 | --- a/arch/x86/include/asm/uaccess_64.h | ||
64 | +++ b/arch/x86/include/asm/uaccess_64.h | ||
65 | @@ -21,10 +21,27 @@ copy_user_generic(void *to, const void *from, unsigned len); | ||
66 | __must_check unsigned long | ||
67 | copy_to_user(void __user *to, const void *from, unsigned len); | ||
68 | __must_check unsigned long | ||
69 | -copy_from_user(void *to, const void __user *from, unsigned len); | ||
70 | +_copy_from_user(void *to, const void __user *from, unsigned len); | ||
71 | __must_check unsigned long | ||
72 | copy_in_user(void __user *to, const void __user *from, unsigned len); | ||
73 | |||
74 | +static inline unsigned long __must_check copy_from_user(void *to, | ||
75 | + const void __user *from, | ||
76 | + unsigned long n) | ||
77 | +{ | ||
78 | + int sz = __compiletime_object_size(to); | ||
79 | + int ret = -EFAULT; | ||
80 | + | ||
81 | + if (likely(sz == -1 || sz >= n)) | ||
82 | + ret = _copy_from_user(to, from, n); | ||
83 | +#ifdef CONFIG_DEBUG_VM | ||
84 | + else | ||
85 | + WARN(1, "Buffer overflow detected!\n"); | ||
86 | +#endif | ||
87 | + return ret; | ||
88 | +} | ||
89 | + | ||
90 | + | ||
91 | static __always_inline __must_check | ||
92 | int __copy_from_user(void *dst, const void __user *src, unsigned size) | ||
93 | { | ||
94 | diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c | ||
95 | index 3909e3b..a0cdd8c 100644 | ||
96 | --- a/arch/x86/kernel/x8664_ksyms_64.c | ||
97 | +++ b/arch/x86/kernel/x8664_ksyms_64.c | ||
98 | @@ -30,7 +30,7 @@ EXPORT_SYMBOL(__put_user_8); | ||
99 | |||
100 | EXPORT_SYMBOL(copy_user_generic); | ||
101 | EXPORT_SYMBOL(__copy_user_nocache); | ||
102 | -EXPORT_SYMBOL(copy_from_user); | ||
103 | +EXPORT_SYMBOL(_copy_from_user); | ||
104 | EXPORT_SYMBOL(copy_to_user); | ||
105 | EXPORT_SYMBOL(__copy_from_user_inatomic); | ||
106 | |||
107 | diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S | ||
108 | index 6ba0f7b..4be3c41 100644 | ||
109 | --- a/arch/x86/lib/copy_user_64.S | ||
110 | +++ b/arch/x86/lib/copy_user_64.S | ||
111 | @@ -78,7 +78,7 @@ ENTRY(copy_to_user) | ||
112 | ENDPROC(copy_to_user) | ||
113 | |||
114 | /* Standard copy_from_user with segment limit checking */ | ||
115 | -ENTRY(copy_from_user) | ||
116 | +ENTRY(_copy_from_user) | ||
117 | CFI_STARTPROC | ||
118 | GET_THREAD_INFO(%rax) | ||
119 | movq %rsi,%rcx | ||
120 | @@ -88,7 +88,7 @@ ENTRY(copy_from_user) | ||
121 | jae bad_from_user | ||
122 | ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string | ||
123 | CFI_ENDPROC | ||
124 | -ENDPROC(copy_from_user) | ||
125 | +ENDPROC(_copy_from_user) | ||
126 | |||
127 | ENTRY(copy_user_generic) | ||
128 | CFI_STARTPROC | ||
129 | diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c | ||
130 | index 1f118d4..8498684 100644 | ||
131 | --- a/arch/x86/lib/usercopy_32.c | ||
132 | +++ b/arch/x86/lib/usercopy_32.c | ||
133 | @@ -874,7 +874,7 @@ EXPORT_SYMBOL(copy_to_user); | ||
134 | * data to the requested size using zero bytes. | ||
135 | */ | ||
136 | unsigned long | ||
137 | -copy_from_user(void *to, const void __user *from, unsigned long n) | ||
138 | +_copy_from_user(void *to, const void __user *from, unsigned long n) | ||
139 | { | ||
140 | if (access_ok(VERIFY_READ, from, n)) | ||
141 | n = __copy_from_user(to, from, n); | ||
142 | @@ -882,4 +882,4 @@ copy_from_user(void *to, const void __user *from, unsigned long n) | ||
143 | memset(to, 0, n); | ||
144 | return n; | ||
145 | } | ||
146 | -EXPORT_SYMBOL(copy_from_user); | ||
147 | +EXPORT_SYMBOL(_copy_from_user); | ||
148 | diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h | ||
149 | index 450fa59..a3aef5d 100644 | ||
150 | --- a/include/linux/compiler-gcc4.h | ||
151 | +++ b/include/linux/compiler-gcc4.h | ||
152 | @@ -37,3 +37,5 @@ | ||
153 | #define __cold __attribute__((__cold__)) | ||
154 | |||
155 | #endif | ||
156 | + | ||
157 | +#define __compiletime_object_size(obj) __builtin_object_size(obj, 0) | ||
158 | diff --git a/include/linux/compiler.h b/include/linux/compiler.h | ||
159 | index 9d4c4b0..9c42853 100644 | ||
160 | --- a/include/linux/compiler.h | ||
161 | +++ b/include/linux/compiler.h | ||
162 | @@ -185,6 +185,10 @@ extern void __chk_io_ptr(const volatile void __iomem *); | ||
163 | # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) | ||
164 | #endif | ||
165 | |||
166 | +/* Compile time object size, -1 for unknown */ | ||
167 | +#ifndef __compiletime_object_size | ||
168 | +# define __compiletime_object_size(obj) -1 | ||
169 | +#endif | ||
170 | /* | ||
171 | * Prevent the compiler from merging or refetching accesses. The compiler | ||
172 | * is also forbidden from reordering successive instances of ACCESS_ONCE(), | ||
173 | -- | ||
174 | 1.6.0.6 | ||
175 | |||
176 | From 350cf3cd513e6759ae6852946532a47249f25600 Mon Sep 17 00:00:00 2001 | ||
177 | From: Arjan van de Ven <arjan@linux.intel.com> | ||
178 | Date: Wed, 30 Sep 2009 12:57:46 +0200 | ||
179 | Subject: [PATCH] x86: Turn the copy_from_user check into an (optional) compile time warning | ||
180 | |||
181 | A previous patch added the buffer size check to copy_from_user(). | ||
182 | |||
183 | One of the things learned from analyzing the result of the previous patch | ||
184 | is that in general, gcc is really good at proving that the code contains | ||
185 | sufficient security checks to not need to do a runtime check. But that | ||
186 | for those cases where gcc could not prove this, there was a relatively | ||
187 | high percentage of real security issues. | ||
188 | |||
189 | This patch turns the case of "gcc cannot prove" into a compile time | ||
190 | warning, as long as a sufficiently new gcc is in use. | ||
191 | The objective is that these warnings will trigger developers checking | ||
192 | new cases out before a security hole enters a linux kernel release. | ||
193 | |||
194 | Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> | ||
195 | --- | ||
196 | arch/x86/include/asm/uaccess_32.h | 12 +++++++++--- | ||
197 | arch/x86/lib/usercopy_32.c | 6 ++++++ | ||
198 | include/linux/compiler-gcc4.h | 3 +++ | ||
199 | include/linux/compiler.h | 4 ++++ | ||
200 | 4 files changed, 22 insertions(+), 3 deletions(-) | ||
201 | |||
202 | diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h | ||
203 | index 582d6ae..7826639 100644 | ||
204 | --- a/arch/x86/include/asm/uaccess_32.h | ||
205 | +++ b/arch/x86/include/asm/uaccess_32.h | ||
206 | @@ -191,6 +191,13 @@ unsigned long __must_check _copy_from_user(void *to, | ||
207 | const void __user *from, | ||
208 | unsigned long n); | ||
209 | |||
210 | + | ||
211 | +extern void copy_from_user_overflow(void) | ||
212 | +#ifdef CONFIG_DEBUG_STACKOVERFLOW | ||
213 | + __compiletime_warning("copy_from_user buffer size is not provably correct") | ||
214 | +#endif | ||
215 | +; | ||
216 | + | ||
217 | static inline unsigned long __must_check copy_from_user(void *to, | ||
218 | const void __user *from, | ||
219 | unsigned long n) | ||
220 | @@ -200,10 +207,9 @@ static inline unsigned long __must_check copy_from_user(void *to, | ||
221 | |||
222 | if (likely(sz == -1 || sz >= n)) | ||
223 | ret = _copy_from_user(to, from, n); | ||
224 | -#ifdef CONFIG_DEBUG_VM | ||
225 | else | ||
226 | - WARN(1, "Buffer overflow detected!\n"); | ||
227 | -#endif | ||
228 | + copy_from_user_overflow(); | ||
229 | + | ||
230 | return ret; | ||
231 | } | ||
232 | |||
233 | diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c | ||
234 | index 8498684..e218d5d 100644 | ||
235 | --- a/arch/x86/lib/usercopy_32.c | ||
236 | +++ b/arch/x86/lib/usercopy_32.c | ||
237 | @@ -883,3 +883,9 @@ _copy_from_user(void *to, const void __user *from, unsigned long n) | ||
238 | return n; | ||
239 | } | ||
240 | EXPORT_SYMBOL(_copy_from_user); | ||
241 | + | ||
242 | +void copy_from_user_overflow(void) | ||
243 | +{ | ||
244 | + WARN(1, "Buffer overflow detected!\n"); | ||
245 | +} | ||
246 | +EXPORT_SYMBOL(copy_from_user_overflow); | ||
247 | diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h | ||
248 | index a3aef5d..f1709c1 100644 | ||
249 | --- a/include/linux/compiler-gcc4.h | ||
250 | +++ b/include/linux/compiler-gcc4.h | ||
251 | @@ -39,3 +39,6 @@ | ||
252 | #endif | ||
253 | |||
254 | #define __compiletime_object_size(obj) __builtin_object_size(obj, 0) | ||
255 | +#if __GNUC_MINOR__ >= 4 | ||
256 | +#define __compiletime_warning(message) __attribute__((warning(message))) | ||
257 | +#endif | ||
258 | diff --git a/include/linux/compiler.h b/include/linux/compiler.h | ||
259 | index 9c42853..241dfd8 100644 | ||
260 | --- a/include/linux/compiler.h | ||
261 | +++ b/include/linux/compiler.h | ||
262 | @@ -189,6 +189,10 @@ extern void __chk_io_ptr(const volatile void __iomem *); | ||
263 | #ifndef __compiletime_object_size | ||
264 | # define __compiletime_object_size(obj) -1 | ||
265 | #endif | ||
266 | +#ifndef __compiletime_warning | ||
267 | +# define __compiletime_warning(message) | ||
268 | +#endif | ||
269 | + | ||
270 | /* | ||
271 | * Prevent the compiler from merging or refetching accesses. The compiler | ||
272 | * is also forbidden from reordering successive instances of ACCESS_ONCE(), | ||
273 | -- | ||
274 | 1.6.2.5 | ||
275 | |||