Commit 888c31fc83ddc7fcd9947cb67c5718b4e3dd5e1b

Authored by Helge Deller
Committed by Kyle McMartin
1 parent a3bee03e71

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>

Showing 3 changed files with 41 additions and 3 deletions Side-by-side Diff

arch/parisc/Kconfig.debug
... ... @@ -12,5 +12,19 @@
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
arch/parisc/include/asm/uaccess.h
... ... @@ -7,6 +7,7 @@
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
13 14  
... ... @@ -234,12 +235,34 @@
234 235  
235 236 unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len);
236 237 #define __copy_to_user copy_to_user
237   -unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len);
238   -#define __copy_from_user copy_from_user
  238 +unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len);
239 239 unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len);
240 240 #define __copy_in_user copy_in_user
241 241 #define __copy_to_user_inatomic __copy_to_user
242 242 #define __copy_from_user_inatomic __copy_from_user
  243 +
  244 +extern void copy_from_user_overflow(void)
  245 +#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
  246 + __compiletime_error("copy_from_user() buffer size is not provably correct")
  247 +#else
  248 + __compiletime_warning("copy_from_user() buffer size is not provably correct")
  249 +#endif
  250 +;
  251 +
  252 +static inline unsigned long __must_check copy_from_user(void *to,
  253 + const void __user *from,
  254 + unsigned long n)
  255 +{
  256 + int sz = __compiletime_object_size(to);
  257 + int ret = -EFAULT;
  258 +
  259 + if (likely(sz == -1 || !__builtin_constant_p(n) || sz >= n))
  260 + ret = __copy_from_user(to, from, n);
  261 + else
  262 + copy_from_user_overflow();
  263 +
  264 + return ret;
  265 +}
243 266  
244 267 struct pt_regs;
245 268 int fixup_exception(struct pt_regs *regs);
arch/parisc/lib/memcpy.c
... ... @@ -475,7 +475,8 @@
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);