Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

parisc: Add hardened usercopy feature

Add hardened usercopy checks to parisc architecture and clean up
indenting.

Signed-off-by: Helge Deller <deller@gmx.de>

+41 -19
+1
arch/parisc/Kconfig
··· 23 23 select SYSCTL_ARCH_UNALIGN_ALLOW 24 24 select SYSCTL_EXCEPTION_TRACE 25 25 select HAVE_MOD_ARCH_SPECIFIC 26 + select HAVE_ARCH_HARDENED_USERCOPY 26 27 select VIRT_TO_BUS 27 28 select MODULES_USE_ELF_RELA 28 29 select CLONE_BACKWARDS
+34 -14
arch/parisc/include/asm/uaccess.h
··· 11 11 12 12 #include <linux/bug.h> 13 13 #include <linux/string.h> 14 + #include <linux/thread_info.h> 14 15 15 16 #define VERIFY_READ 0 16 17 #define VERIFY_WRITE 1 ··· 202 201 #define clear_user lclear_user 203 202 #define __clear_user lclear_user 204 203 205 - unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len); 206 - #define __copy_to_user copy_to_user 207 - unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len); 208 - unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len); 204 + unsigned long __must_check __copy_to_user(void __user *dst, const void *src, 205 + unsigned long len); 206 + unsigned long __must_check __copy_from_user(void *dst, const void __user *src, 207 + unsigned long len); 208 + unsigned long copy_in_user(void __user *dst, const void __user *src, 209 + unsigned long len); 209 210 #define __copy_in_user copy_in_user 210 211 #define __copy_to_user_inatomic __copy_to_user 211 212 #define __copy_from_user_inatomic __copy_from_user ··· 220 217 WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count); 221 218 } 222 219 223 - static inline unsigned long __must_check copy_from_user(void *to, 224 - const void __user *from, 225 - unsigned long n) 220 + static __always_inline unsigned long __must_check 221 + copy_from_user(void *to, const void __user *from, unsigned long n) 226 222 { 227 - int sz = __compiletime_object_size(to); 228 - unsigned long ret = n; 223 + int sz = __compiletime_object_size(to); 224 + unsigned long ret = n; 229 225 230 - if (likely(sz == -1 || sz >= n)) 231 - ret = __copy_from_user(to, from, n); 232 - else if (!__builtin_constant_p(n)) 226 + if (likely(sz < 0 || sz >= n)) { 227 + check_object_size(to, n, false); 228 + ret = __copy_from_user(to, from, n); 229 + } else if (!__builtin_constant_p(n)) 233 230 copy_user_overflow(sz, n); 234 231 else 235 - __bad_copy_user(); 232 + __bad_copy_user(); 236 233 237 234 if (unlikely(ret)) 238 235 memset(to + (n - ret), 0, ret); 239 - return ret; 236 + 237 + return ret; 238 + } 239 + 240 + static __always_inline unsigned long __must_check 241 + copy_to_user(void __user *to, const void *from, unsigned long n) 242 + { 243 + int sz = __compiletime_object_size(from); 244 + 245 + if (likely(sz < 0 || sz >= n)) { 246 + check_object_size(from, n, true); 247 + n = __copy_to_user(to, from, n); 248 + } else if (!__builtin_constant_p(n)) 249 + copy_user_overflow(sz, n); 250 + else 251 + __bad_copy_user(); 252 + 253 + return n; 240 254 } 241 255 242 256 struct pt_regs;
+6 -5
arch/parisc/lib/memcpy.c
··· 489 489 } 490 490 491 491 #ifdef __KERNEL__ 492 - unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len) 492 + unsigned long __copy_to_user(void __user *dst, const void *src, 493 + unsigned long len) 493 494 { 494 495 mtsp(get_kernel_space(), 1); 495 496 mtsp(get_user_space(), 2); 496 497 return pa_memcpy((void __force *)dst, src, len); 497 498 } 499 + EXPORT_SYMBOL(__copy_to_user); 498 500 499 - EXPORT_SYMBOL(__copy_from_user); 500 - unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len) 501 + unsigned long __copy_from_user(void *dst, const void __user *src, 502 + unsigned long len) 501 503 { 502 504 mtsp(get_user_space(), 1); 503 505 mtsp(get_kernel_space(), 2); 504 506 return pa_memcpy(dst, (void __force *)src, len); 505 507 } 508 + EXPORT_SYMBOL(__copy_from_user); 506 509 507 510 unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len) 508 511 { ··· 523 520 return dst; 524 521 } 525 522 526 - EXPORT_SYMBOL(copy_to_user); 527 - EXPORT_SYMBOL(copy_from_user); 528 523 EXPORT_SYMBOL(copy_in_user); 529 524 EXPORT_SYMBOL(memcpy); 530 525