diff options
| author | Helge Deller <deller@gmx.de> | 2010-02-01 14:56:33 -0500 |
|---|---|---|
| committer | Kyle McMartin <kyle@redhat.com> | 2010-03-06 17:54:09 -0500 |
| commit | 888c31fc83ddc7fcd9947cb67c5718b4e3dd5e1b (patch) | |
| tree | 15ef949561b6c8b319bb686eadec20c98148dfa3 | |
| parent | a3bee03e718c9251456676b71a723a34c999e891 (diff) | |
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>
| -rw-r--r-- | arch/parisc/Kconfig.debug | 14 | ||||
| -rw-r--r-- | arch/parisc/include/asm/uaccess.h | 27 | ||||
| -rw-r--r-- | arch/parisc/lib/memcpy.c | 3 |
3 files changed, 41 insertions, 3 deletions
diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug index bc989e522a04..7305ac8f7f5b 100644 --- a/arch/parisc/Kconfig.debug +++ b/arch/parisc/Kconfig.debug | |||
| @@ -12,4 +12,18 @@ config DEBUG_RODATA | |||
| 12 | portion of the kernel code won't be covered by a TLB anymore. | 12 | portion of the kernel code won't be covered by a TLB anymore. |
| 13 | If in doubt, say "N". | 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 | endmenu | 29 | endmenu |
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index 7cf799d70b4c..ff4cf9dab8d2 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <asm/page.h> | 7 | #include <asm/page.h> |
| 8 | #include <asm/system.h> | 8 | #include <asm/system.h> |
| 9 | #include <asm/cache.h> | 9 | #include <asm/cache.h> |
| 10 | #include <asm/errno.h> | ||
| 10 | #include <asm-generic/uaccess-unaligned.h> | 11 | #include <asm-generic/uaccess-unaligned.h> |
| 11 | 12 | ||
| 12 | #define VERIFY_READ 0 | 13 | #define VERIFY_READ 0 |
| @@ -234,13 +235,35 @@ extern long lstrnlen_user(const char __user *,long); | |||
| 234 | 235 | ||
| 235 | unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len); | 236 | unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len); |
| 236 | #define __copy_to_user copy_to_user | 237 | #define __copy_to_user copy_to_user |
| 237 | unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len); | 238 | unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len); |
| 238 | #define __copy_from_user copy_from_user | ||
| 239 | unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len); | 239 | unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len); |
| 240 | #define __copy_in_user copy_in_user | 240 | #define __copy_in_user copy_in_user |
| 241 | #define __copy_to_user_inatomic __copy_to_user | 241 | #define __copy_to_user_inatomic __copy_to_user |
| 242 | #define __copy_from_user_inatomic __copy_from_user | 242 | #define __copy_from_user_inatomic __copy_from_user |
| 243 | 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 | } | ||
| 266 | |||
| 244 | struct pt_regs; | 267 | struct pt_regs; |
| 245 | int fixup_exception(struct pt_regs *regs); | 268 | int fixup_exception(struct pt_regs *regs); |
| 246 | 269 | ||
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c index abf41f4632a9..1dbca5c31b3c 100644 --- a/arch/parisc/lib/memcpy.c +++ b/arch/parisc/lib/memcpy.c | |||
| @@ -475,7 +475,8 @@ unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len) | |||
| 475 | return pa_memcpy((void __force *)dst, src, len); | 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 | mtsp(get_user_space(), 1); | 481 | mtsp(get_user_space(), 1); |
| 481 | mtsp(get_kernel_space(), 2); | 482 | mtsp(get_kernel_space(), 2); |
