sparc: Use __builtin_object_size() to validate the buffer size for copy_from_user()

This mirrors x86 commit 9f0cf4adb6aa0bfccf675c938124e68f7f06349d
(x86: Use __builtin_object_size() to validate the buffer size for copy_from_user())

Signed-off-by: David S. Miller <davem@davemloft.net>

+56 -3
+14
arch/sparc/Kconfig.debug
··· 33 depends on MCOUNT 34 default y 35 36 endmenu
··· 33 depends on MCOUNT 34 default y 35 36 + config DEBUG_STRICT_USER_COPY_CHECKS 37 + bool "Strict copy size checks" 38 + depends on DEBUG_KERNEL && !TRACE_BRANCH_PROFILING 39 + ---help--- 40 + Enabling this option turns a certain set of sanity checks for user 41 + copy operations into compile time failures. 42 + 43 + The copy_from_user() etc checks are there to help test if there 44 + are sufficient security checks on the length argument of 45 + the copy operation, by having gcc prove that the argument is 46 + within bounds. 47 + 48 + If unsure, or if you run an older (pre 4.4) gcc, say N. 49 + 50 endmenu
+15
arch/sparc/include/asm/uaccess_32.h
··· 260 return __copy_user(to, (__force void __user *) from, n); 261 } 262 263 static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) 264 { 265 if (n && __access_ok((unsigned long) from, n)) 266 return __copy_user((__force void __user *) to, from, n); 267 else
··· 260 return __copy_user(to, (__force void __user *) from, n); 261 } 262 263 + extern void copy_from_user_overflow(void) 264 + #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS 265 + __compiletime_error("copy_from_user() buffer size is not provably correct") 266 + #else 267 + __compiletime_warning("copy_from_user() buffer size is not provably correct") 268 + #endif 269 + ; 270 + 271 static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) 272 { 273 + int sz = __compiletime_object_size(to); 274 + 275 + if (unlikely(sz != -1 && sz < n)) { 276 + copy_from_user_overflow(); 277 + return -EFAULT; 278 + } 279 + 280 if (n && __access_ok((unsigned long) from, n)) 281 return __copy_user((__force void __user *) to, from, n); 282 else
+18 -3
arch/sparc/include/asm/uaccess_64.h
··· 6 */ 7 8 #ifdef __KERNEL__ 9 #include <linux/compiler.h> 10 #include <linux/string.h> 11 #include <linux/thread_info.h> ··· 205 206 extern int __get_user_bad(void); 207 208 extern unsigned long __must_check ___copy_from_user(void *to, 209 const void __user *from, 210 unsigned long size); ··· 221 static inline unsigned long __must_check 222 copy_from_user(void *to, const void __user *from, unsigned long size) 223 { 224 - unsigned long ret = ___copy_from_user(to, from, size); 225 226 - if (unlikely(ret)) 227 - ret = copy_from_user_fixup(to, from, size); 228 return ret; 229 } 230 #define __copy_from_user copy_from_user
··· 6 */ 7 8 #ifdef __KERNEL__ 9 + #include <linux/errno.h> 10 #include <linux/compiler.h> 11 #include <linux/string.h> 12 #include <linux/thread_info.h> ··· 204 205 extern int __get_user_bad(void); 206 207 + extern void copy_from_user_overflow(void) 208 + #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS 209 + __compiletime_error("copy_from_user() buffer size is not provably correct") 210 + #else 211 + __compiletime_warning("copy_from_user() buffer size is not provably correct") 212 + #endif 213 + ; 214 + 215 extern unsigned long __must_check ___copy_from_user(void *to, 216 const void __user *from, 217 unsigned long size); ··· 212 static inline unsigned long __must_check 213 copy_from_user(void *to, const void __user *from, unsigned long size) 214 { 215 + unsigned long ret = (unsigned long) -EFAULT; 216 + int sz = __compiletime_object_size(to); 217 218 + if (likely(sz == -1 || sz >= size)) { 219 + ret = ___copy_from_user(to, from, size); 220 + if (unlikely(ret)) 221 + ret = copy_from_user_fixup(to, from, size); 222 + } else { 223 + copy_from_user_overflow(); 224 + } 225 return ret; 226 } 227 #define __copy_from_user copy_from_user
+1
arch/sparc/lib/Makefile
··· 44 obj-$(CONFIG_SPARC32) += atomic32.o 45 obj-y += ksyms.o 46 obj-$(CONFIG_SPARC64) += PeeCeeI.o
··· 44 obj-$(CONFIG_SPARC32) += atomic32.o 45 obj-y += ksyms.o 46 obj-$(CONFIG_SPARC64) += PeeCeeI.o 47 + obj-y += usercopy.o
+8
arch/sparc/lib/usercopy.c
···
··· 1 + #include <linux/module.h> 2 + #include <linux/bug.h> 3 + 4 + void copy_from_user_overflow(void) 5 + { 6 + WARN(1, "Buffer overflow detected!\n"); 7 + } 8 + EXPORT_SYMBOL(copy_from_user_overflow);