diff options
-rw-r--r-- | arch/x86/include/asm/uaccess_32.h | 19 | ||||
-rw-r--r-- | arch/x86/include/asm/uaccess_64.h | 19 | ||||
-rw-r--r-- | arch/x86/kernel/x8664_ksyms_64.c | 2 | ||||
-rw-r--r-- | arch/x86/lib/copy_user_64.S | 4 | ||||
-rw-r--r-- | arch/x86/lib/usercopy_32.c | 4 | ||||
-rw-r--r-- | include/linux/compiler-gcc4.h | 2 | ||||
-rw-r--r-- | include/linux/compiler.h | 4 |
7 files changed, 47 insertions, 7 deletions
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h index 632fb44b4cb5..582d6aef7417 100644 --- a/arch/x86/include/asm/uaccess_32.h +++ b/arch/x86/include/asm/uaccess_32.h | |||
@@ -187,9 +187,26 @@ __copy_from_user_inatomic_nocache(void *to, const void __user *from, | |||
187 | 187 | ||
188 | unsigned long __must_check copy_to_user(void __user *to, | 188 | unsigned long __must_check copy_to_user(void __user *to, |
189 | const void *from, unsigned long n); | 189 | const void *from, unsigned long n); |
190 | unsigned long __must_check copy_from_user(void *to, | 190 | unsigned long __must_check _copy_from_user(void *to, |
191 | const void __user *from, | 191 | const void __user *from, |
192 | unsigned long n); | 192 | unsigned long n); |
193 | |||
194 | static inline unsigned long __must_check copy_from_user(void *to, | ||
195 | const void __user *from, | ||
196 | unsigned long n) | ||
197 | { | ||
198 | int sz = __compiletime_object_size(to); | ||
199 | int ret = -EFAULT; | ||
200 | |||
201 | if (likely(sz == -1 || sz >= n)) | ||
202 | ret = _copy_from_user(to, from, n); | ||
203 | #ifdef CONFIG_DEBUG_VM | ||
204 | else | ||
205 | WARN(1, "Buffer overflow detected!\n"); | ||
206 | #endif | ||
207 | return ret; | ||
208 | } | ||
209 | |||
193 | long __must_check strncpy_from_user(char *dst, const char __user *src, | 210 | long __must_check strncpy_from_user(char *dst, const char __user *src, |
194 | long count); | 211 | long count); |
195 | long __must_check __strncpy_from_user(char *dst, | 212 | long __must_check __strncpy_from_user(char *dst, |
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index db24b215fc50..ce6fec7ce38d 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h | |||
@@ -21,10 +21,27 @@ copy_user_generic(void *to, const void *from, unsigned len); | |||
21 | __must_check unsigned long | 21 | __must_check unsigned long |
22 | copy_to_user(void __user *to, const void *from, unsigned len); | 22 | copy_to_user(void __user *to, const void *from, unsigned len); |
23 | __must_check unsigned long | 23 | __must_check unsigned long |
24 | copy_from_user(void *to, const void __user *from, unsigned len); | 24 | _copy_from_user(void *to, const void __user *from, unsigned len); |
25 | __must_check unsigned long | 25 | __must_check unsigned long |
26 | copy_in_user(void __user *to, const void __user *from, unsigned len); | 26 | copy_in_user(void __user *to, const void __user *from, unsigned len); |
27 | 27 | ||
28 | static inline unsigned long __must_check copy_from_user(void *to, | ||
29 | const void __user *from, | ||
30 | unsigned long n) | ||
31 | { | ||
32 | int sz = __compiletime_object_size(to); | ||
33 | int ret = -EFAULT; | ||
34 | |||
35 | if (likely(sz == -1 || sz >= n)) | ||
36 | ret = _copy_from_user(to, from, n); | ||
37 | #ifdef CONFIG_DEBUG_VM | ||
38 | else | ||
39 | WARN(1, "Buffer overflow detected!\n"); | ||
40 | #endif | ||
41 | return ret; | ||
42 | } | ||
43 | |||
44 | |||
28 | static __always_inline __must_check | 45 | static __always_inline __must_check |
29 | int __copy_from_user(void *dst, const void __user *src, unsigned size) | 46 | int __copy_from_user(void *dst, const void __user *src, unsigned size) |
30 | { | 47 | { |
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c index 3909e3ba5ce3..a0cdd8cc1d67 100644 --- a/arch/x86/kernel/x8664_ksyms_64.c +++ b/arch/x86/kernel/x8664_ksyms_64.c | |||
@@ -30,7 +30,7 @@ EXPORT_SYMBOL(__put_user_8); | |||
30 | 30 | ||
31 | EXPORT_SYMBOL(copy_user_generic); | 31 | EXPORT_SYMBOL(copy_user_generic); |
32 | EXPORT_SYMBOL(__copy_user_nocache); | 32 | EXPORT_SYMBOL(__copy_user_nocache); |
33 | EXPORT_SYMBOL(copy_from_user); | 33 | EXPORT_SYMBOL(_copy_from_user); |
34 | EXPORT_SYMBOL(copy_to_user); | 34 | EXPORT_SYMBOL(copy_to_user); |
35 | EXPORT_SYMBOL(__copy_from_user_inatomic); | 35 | EXPORT_SYMBOL(__copy_from_user_inatomic); |
36 | 36 | ||
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S index 6ba0f7bb85ea..4be3c415b3e9 100644 --- a/arch/x86/lib/copy_user_64.S +++ b/arch/x86/lib/copy_user_64.S | |||
@@ -78,7 +78,7 @@ ENTRY(copy_to_user) | |||
78 | ENDPROC(copy_to_user) | 78 | ENDPROC(copy_to_user) |
79 | 79 | ||
80 | /* Standard copy_from_user with segment limit checking */ | 80 | /* Standard copy_from_user with segment limit checking */ |
81 | ENTRY(copy_from_user) | 81 | ENTRY(_copy_from_user) |
82 | CFI_STARTPROC | 82 | CFI_STARTPROC |
83 | GET_THREAD_INFO(%rax) | 83 | GET_THREAD_INFO(%rax) |
84 | movq %rsi,%rcx | 84 | movq %rsi,%rcx |
@@ -88,7 +88,7 @@ ENTRY(copy_from_user) | |||
88 | jae bad_from_user | 88 | jae bad_from_user |
89 | ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string | 89 | ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string |
90 | CFI_ENDPROC | 90 | CFI_ENDPROC |
91 | ENDPROC(copy_from_user) | 91 | ENDPROC(_copy_from_user) |
92 | 92 | ||
93 | ENTRY(copy_user_generic) | 93 | ENTRY(copy_user_generic) |
94 | CFI_STARTPROC | 94 | CFI_STARTPROC |
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c index 1f118d462acc..8498684e45b0 100644 --- a/arch/x86/lib/usercopy_32.c +++ b/arch/x86/lib/usercopy_32.c | |||
@@ -874,7 +874,7 @@ EXPORT_SYMBOL(copy_to_user); | |||
874 | * data to the requested size using zero bytes. | 874 | * data to the requested size using zero bytes. |
875 | */ | 875 | */ |
876 | unsigned long | 876 | unsigned long |
877 | copy_from_user(void *to, const void __user *from, unsigned long n) | 877 | _copy_from_user(void *to, const void __user *from, unsigned long n) |
878 | { | 878 | { |
879 | if (access_ok(VERIFY_READ, from, n)) | 879 | if (access_ok(VERIFY_READ, from, n)) |
880 | n = __copy_from_user(to, from, n); | 880 | n = __copy_from_user(to, from, n); |
@@ -882,4 +882,4 @@ copy_from_user(void *to, const void __user *from, unsigned long n) | |||
882 | memset(to, 0, n); | 882 | memset(to, 0, n); |
883 | return n; | 883 | return n; |
884 | } | 884 | } |
885 | EXPORT_SYMBOL(copy_from_user); | 885 | EXPORT_SYMBOL(_copy_from_user); |
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index 450fa597c94d..a3aef5d55dba 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h | |||
@@ -37,3 +37,5 @@ | |||
37 | #define __cold __attribute__((__cold__)) | 37 | #define __cold __attribute__((__cold__)) |
38 | 38 | ||
39 | #endif | 39 | #endif |
40 | |||
41 | #define __compiletime_object_size(obj) __builtin_object_size(obj, 0) | ||
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 04fb5135b4e1..8e54108688f9 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h | |||
@@ -266,6 +266,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); | |||
266 | # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) | 266 | # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) |
267 | #endif | 267 | #endif |
268 | 268 | ||
269 | /* Compile time object size, -1 for unknown */ | ||
270 | #ifndef __compiletime_object_size | ||
271 | # define __compiletime_object_size(obj) -1 | ||
272 | #endif | ||
269 | /* | 273 | /* |
270 | * Prevent the compiler from merging or refetching accesses. The compiler | 274 | * Prevent the compiler from merging or refetching accesses. The compiler |
271 | * is also forbidden from reordering successive instances of ACCESS_ONCE(), | 275 | * is also forbidden from reordering successive instances of ACCESS_ONCE(), |