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

parisc: add strict copy size checks (v2)

Add CONFIG_DEBUG_STRICT_USER_COPY_CHECKS, copied from the x86
implementation. Tested with 32 and 64bit kernel.

Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Kyle McMartin <kyle@mcmartin.ca>

authored by

Helge Deller and committed by
Kyle McMartin
888c31fc a3bee03e

+41 -3
+14
arch/parisc/Kconfig.debug
··· 12 12 portion of the kernel code won't be covered by a TLB anymore. 13 13 If in doubt, say "N". 14 14 15 + config DEBUG_STRICT_USER_COPY_CHECKS 16 + bool "Strict copy size checks" 17 + depends on DEBUG_KERNEL && !TRACE_BRANCH_PROFILING 18 + ---help--- 19 + Enabling this option turns a certain set of sanity checks for user 20 + copy operations into compile time failures. 21 + 22 + The copy_from_user() etc checks are there to help test if there 23 + are sufficient security checks on the length argument of 24 + the copy operation, by having gcc prove that the argument is 25 + within bounds. 26 + 27 + If unsure, or if you run an older (pre 4.4) gcc, say N. 28 + 15 29 endmenu
+25 -2
arch/parisc/include/asm/uaccess.h
··· 7 7 #include <asm/page.h> 8 8 #include <asm/system.h> 9 9 #include <asm/cache.h> 10 + #include <asm/errno.h> 10 11 #include <asm-generic/uaccess-unaligned.h> 11 12 12 13 #define VERIFY_READ 0 ··· 235 234 236 235 unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len); 237 236 #define __copy_to_user copy_to_user 238 - unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len); 239 - #define __copy_from_user copy_from_user 237 + unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len); 240 238 unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len); 241 239 #define __copy_in_user copy_in_user 242 240 #define __copy_to_user_inatomic __copy_to_user 243 241 #define __copy_from_user_inatomic __copy_from_user 242 + 243 + extern void copy_from_user_overflow(void) 244 + #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS 245 + __compiletime_error("copy_from_user() buffer size is not provably correct") 246 + #else 247 + __compiletime_warning("copy_from_user() buffer size is not provably correct") 248 + #endif 249 + ; 250 + 251 + static inline unsigned long __must_check copy_from_user(void *to, 252 + const void __user *from, 253 + unsigned long n) 254 + { 255 + int sz = __compiletime_object_size(to); 256 + int ret = -EFAULT; 257 + 258 + if (likely(sz == -1 || !__builtin_constant_p(n) || sz >= n)) 259 + ret = __copy_from_user(to, from, n); 260 + else 261 + copy_from_user_overflow(); 262 + 263 + return ret; 264 + } 244 265 245 266 struct pt_regs; 246 267 int fixup_exception(struct pt_regs *regs);
+2 -1
arch/parisc/lib/memcpy.c
··· 475 475 return pa_memcpy((void __force *)dst, src, len); 476 476 } 477 477 478 - unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len) 478 + EXPORT_SYMBOL(__copy_from_user); 479 + unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len) 479 480 { 480 481 mtsp(get_user_space(), 1); 481 482 mtsp(get_kernel_space(), 2);