diff options
author | David S. Miller <davem@davemloft.net> | 2009-12-11 10:05:23 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-12-11 10:05:23 +0300 |
commit | fb34035e7b4bb3edc7c2dc0683cfe21f57a9574d (patch) | |
tree | ddde17e5690d77f4f61c6271fc8b6f520c746851 /arch/sparc/include/asm/uaccess_64.h | |
parent | 4ed5d5e4299f42438dd5ac6dcb1f2168ea4fb02a (diff) | |
download | linux-fb34035e7b4bb3edc7c2dc0683cfe21f57a9574d.tar.xz |
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>
Diffstat (limited to 'arch/sparc/include/asm/uaccess_64.h')
-rw-r--r-- | arch/sparc/include/asm/uaccess_64.h | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h index 9ea271e19c70..dbc141660994 100644 --- a/arch/sparc/include/asm/uaccess_64.h +++ b/arch/sparc/include/asm/uaccess_64.h @@ -6,6 +6,7 @@ */ #ifdef __KERNEL__ +#include <linux/errno.h> #include <linux/compiler.h> #include <linux/string.h> #include <linux/thread_info.h> @@ -204,6 +205,14 @@ __asm__ __volatile__( \ extern int __get_user_bad(void); +extern void copy_from_user_overflow(void) +#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS + __compiletime_error("copy_from_user() buffer size is not provably correct") +#else + __compiletime_warning("copy_from_user() buffer size is not provably correct") +#endif +; + extern unsigned long __must_check ___copy_from_user(void *to, const void __user *from, unsigned long size); @@ -212,10 +221,16 @@ extern unsigned long copy_from_user_fixup(void *to, const void __user *from, static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long size) { - unsigned long ret = ___copy_from_user(to, from, size); - - if (unlikely(ret)) - ret = copy_from_user_fixup(to, from, size); + unsigned long ret = (unsigned long) -EFAULT; + int sz = __compiletime_object_size(to); + + if (likely(sz == -1 || sz >= size)) { + ret = ___copy_from_user(to, from, size); + if (unlikely(ret)) + ret = copy_from_user_fixup(to, from, size); + } else { + copy_from_user_overflow(); + } return ret; } #define __copy_from_user copy_from_user |