parisc: Add hardened usercopy feature
authorHelge Deller <deller@gmx.de>
Thu, 6 Oct 2016 07:07:30 +0000 (09:07 +0200)
committerHelge Deller <deller@gmx.de>
Thu, 6 Oct 2016 20:10:19 +0000 (22:10 +0200)
Add hardened usercopy checks to parisc architecture and clean up
indenting.

Signed-off-by: Helge Deller <deller@gmx.de>
arch/parisc/Kconfig
arch/parisc/include/asm/uaccess.h
arch/parisc/lib/memcpy.c

index f8dc10dcf2925a86ed1222140278a737fca5a424..689eb74b34b56eebe28e53868f05274d9c53c53c 100644 (file)
@@ -23,6 +23,7 @@ config PARISC
        select SYSCTL_ARCH_UNALIGN_ALLOW
        select SYSCTL_EXCEPTION_TRACE
        select HAVE_MOD_ARCH_SPECIFIC
+       select HAVE_ARCH_HARDENED_USERCOPY
        select VIRT_TO_BUS
        select MODULES_USE_ELF_RELA
        select CLONE_BACKWARDS
index 482847865dac26ffd890ca529be741cddea4e747..9a2aee1b90fcca4c90ba11b70c58da4e3f3e6129 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/bug.h>
 #include <linux/string.h>
+#include <linux/thread_info.h>
 
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
@@ -201,10 +202,12 @@ extern long lstrnlen_user(const char __user *, long);
 #define clear_user lclear_user
 #define __clear_user lclear_user
 
-unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len);
-#define __copy_to_user copy_to_user
-unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len);
-unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len);
+unsigned long __must_check __copy_to_user(void __user *dst, const void *src,
+                                         unsigned long len);
+unsigned long __must_check __copy_from_user(void *dst, const void __user *src,
+                                         unsigned long len);
+unsigned long copy_in_user(void __user *dst, const void __user *src,
+                          unsigned long len);
 #define __copy_in_user copy_in_user
 #define __copy_to_user_inatomic __copy_to_user
 #define __copy_from_user_inatomic __copy_from_user
@@ -217,23 +220,40 @@ static inline void copy_user_overflow(int size, unsigned long count)
        WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count);
 }
 
-static inline unsigned long __must_check copy_from_user(void *to,
-                                          const void __user *from,
-                                          unsigned long n)
+static __always_inline unsigned long __must_check
+copy_from_user(void *to, const void __user *from, unsigned long n)
 {
-        int sz = __compiletime_object_size(to);
-        unsigned long ret = n;
+       int sz = __compiletime_object_size(to);
+       unsigned long ret = n;
 
-        if (likely(sz == -1 || sz >= n))
-                ret = __copy_from_user(to, from, n);
-        else if (!__builtin_constant_p(n))
+       if (likely(sz < 0 || sz >= n)) {
+               check_object_size(to, n, false);
+               ret = __copy_from_user(to, from, n);
+       } else if (!__builtin_constant_p(n))
                copy_user_overflow(sz, n);
        else
-                __bad_copy_user();
+               __bad_copy_user();
 
        if (unlikely(ret))
                memset(to + (n - ret), 0, ret);
-        return ret;
+
+       return ret;
+}
+
+static __always_inline unsigned long __must_check
+copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+       int sz = __compiletime_object_size(from);
+
+       if (likely(sz < 0 || sz >= n)) {
+               check_object_size(from, n, true);
+               n = __copy_to_user(to, from, n);
+       } else if (!__builtin_constant_p(n))
+               copy_user_overflow(sz, n);
+       else
+               __bad_copy_user();
+
+       return n;
 }
 
 struct pt_regs;
index b2b441b32341acbc473533ecbd24057b8c564eda..f82ff10ed974117a59f8713eba4281350feb44aa 100644 (file)
@@ -489,20 +489,23 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
 }
 
 #ifdef __KERNEL__
-unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len)
+unsigned long __copy_to_user(void __user *dst, const void *src,
+                            unsigned long len)
 {
        mtsp(get_kernel_space(), 1);
        mtsp(get_user_space(), 2);
        return pa_memcpy((void __force *)dst, src, len);
 }
+EXPORT_SYMBOL(__copy_to_user);
 
-EXPORT_SYMBOL(__copy_from_user);
-unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len)
+unsigned long __copy_from_user(void *dst, const void __user *src,
+                              unsigned long len)
 {
        mtsp(get_user_space(), 1);
        mtsp(get_kernel_space(), 2);
        return pa_memcpy(dst, (void __force *)src, len);
 }
+EXPORT_SYMBOL(__copy_from_user);
 
 unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len)
 {
@@ -520,8 +523,6 @@ void * memcpy(void * dst,const void *src, size_t count)
        return dst;
 }
 
-EXPORT_SYMBOL(copy_to_user);
-EXPORT_SYMBOL(copy_from_user);
 EXPORT_SYMBOL(copy_in_user);
 EXPORT_SYMBOL(memcpy);