Merge tag 'usercopy-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 8 Aug 2016 21:48:14 +0000 (14:48 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 8 Aug 2016 21:48:14 +0000 (14:48 -0700)
Pull usercopy protection from Kees Cook:
 "Tbhis implements HARDENED_USERCOPY verification of copy_to_user and
  copy_from_user bounds checking for most architectures on SLAB and
  SLUB"

* tag 'usercopy-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  mm: SLUB hardened usercopy support
  mm: SLAB hardened usercopy support
  s390/uaccess: Enable hardened usercopy
  sparc/uaccess: Enable hardened usercopy
  powerpc/uaccess: Enable hardened usercopy
  ia64/uaccess: Enable hardened usercopy
  arm64/uaccess: Enable hardened usercopy
  ARM: uaccess: Enable hardened usercopy
  x86/uaccess: Enable hardened usercopy
  mm: Hardened usercopy
  mm: Implement stack frame object validation
  mm: Add is_migrate_cma_page

19 files changed:
1  2 
arch/Kconfig
arch/arm/Kconfig
arch/arm/include/asm/uaccess.h
arch/arm64/Kconfig
arch/arm64/include/asm/uaccess.h
arch/ia64/Kconfig
arch/powerpc/Kconfig
arch/s390/Kconfig
arch/s390/lib/uaccess.c
arch/x86/Kconfig
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/uaccess.h
include/linux/mmzone.h
include/linux/slab.h
include/linux/thread_info.h
init/Kconfig
mm/Makefile
mm/slab.c
mm/slub.c

diff --cc arch/Kconfig
Simple merge
Simple merge
Simple merge
Simple merge
index 5e834d10b2913d91bf3620c0e5930cdb5e14035e,92848b00e3cd3969654d32541fe8973457fc5c5e..c47257c91b77e3d6516000c0c8bec5705b97b6dc
@@@ -264,33 -263,32 +264,38 @@@ extern unsigned long __must_check __cle
  
  static inline unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n)
  {
-       return  __arch_copy_from_user(to, from, n);
 +      kasan_check_write(to, n);
+       check_object_size(to, n, false);
+       return __arch_copy_from_user(to, from, n);
  }
  
  static inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n)
  {
-       return  __arch_copy_to_user(to, from, n);
 +      kasan_check_read(from, n);
+       check_object_size(from, n, true);
+       return __arch_copy_to_user(to, from, n);
  }
  
  static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
  {
-       if (access_ok(VERIFY_READ, from, n))
 +      kasan_check_write(to, n);
 +
+       if (access_ok(VERIFY_READ, from, n)) {
+               check_object_size(to, n, false);
                n = __arch_copy_from_user(to, from, n);
-       else /* security hole - plug it */
+       else /* security hole - plug it */
                memset(to, 0, n);
        return n;
  }
  
  static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
  {
-       if (access_ok(VERIFY_WRITE, to, n))
 +      kasan_check_read(from, n);
 +
+       if (access_ok(VERIFY_WRITE, to, n)) {
+               check_object_size(from, n, true);
                n = __arch_copy_to_user(to, from, n);
+       }
        return n;
  }
  
Simple merge
index ec4047e170a0e6dc5267509f36974f8cbaa1fa84,0ac48a81632dbcadf8c75e3d71cfd335a770a90d..927d2ab2ce08a68c2574c41e6d1b732ecf597d9b
@@@ -164,8 -164,7 +164,9 @@@ config PP
        select ARCH_HAS_UBSAN_SANITIZE_ALL
        select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT
        select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS
 +      select GENERIC_CPU_AUTOPROBE
 +      select HAVE_VIRT_CPU_ACCOUNTING
+       select HAVE_ARCH_HARDENED_USERCOPY
  
  config GENERIC_CSUM
        def_bool CPU_LITTLE_ENDIAN
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 352b1542f5cc21953c037f499d9b48f03ee98314,f24b99eac9696616de150c7c018a772812fb2ad3..cbd8990e2e77e6ffa49f45611eb6710980fddd23
@@@ -105,6 -105,71 +105,30 @@@ static inline int test_ti_thread_flag(s
  
  #define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)
  
 -#if defined TIF_RESTORE_SIGMASK && !defined HAVE_SET_RESTORE_SIGMASK
 -/*
 - * An arch can define its own version of set_restore_sigmask() to get the
 - * job done however works, with or without TIF_RESTORE_SIGMASK.
 - */
 -#define HAVE_SET_RESTORE_SIGMASK      1
 -
 -/**
 - * set_restore_sigmask() - make sure saved_sigmask processing gets done
 - *
 - * This sets TIF_RESTORE_SIGMASK and ensures that the arch signal code
 - * will run before returning to user mode, to process the flag.  For
 - * all callers, TIF_SIGPENDING is already set or it's no harm to set
 - * it.  TIF_RESTORE_SIGMASK need not be in the set of bits that the
 - * arch code will notice on return to user mode, in case those bits
 - * are scarce.  We set TIF_SIGPENDING here to ensure that the arch
 - * signal code always gets run when TIF_RESTORE_SIGMASK is set.
 - */
 -static inline void set_restore_sigmask(void)
 -{
 -      set_thread_flag(TIF_RESTORE_SIGMASK);
 -      WARN_ON(!test_thread_flag(TIF_SIGPENDING));
 -}
 -static inline void clear_restore_sigmask(void)
 -{
 -      clear_thread_flag(TIF_RESTORE_SIGMASK);
 -}
 -static inline bool test_restore_sigmask(void)
 -{
 -      return test_thread_flag(TIF_RESTORE_SIGMASK);
 -}
 -static inline bool test_and_clear_restore_sigmask(void)
 -{
 -      return test_and_clear_thread_flag(TIF_RESTORE_SIGMASK);
 -}
 -#endif        /* TIF_RESTORE_SIGMASK && !HAVE_SET_RESTORE_SIGMASK */
 -
 -#ifndef HAVE_SET_RESTORE_SIGMASK
 -#error "no set_restore_sigmask() provided and default one won't work"
 -#endif
 -
+ #ifndef CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES
+ static inline int arch_within_stack_frames(const void * const stack,
+                                          const void * const stackend,
+                                          const void *obj, unsigned long len)
+ {
+       return 0;
+ }
+ #endif
+ #ifdef CONFIG_HARDENED_USERCOPY
+ extern void __check_object_size(const void *ptr, unsigned long n,
+                                       bool to_user);
+ static inline void check_object_size(const void *ptr, unsigned long n,
+                                    bool to_user)
+ {
+       __check_object_size(ptr, n, to_user);
+ }
+ #else
+ static inline void check_object_size(const void *ptr, unsigned long n,
+                                    bool to_user)
+ { }
+ #endif /* CONFIG_HARDENED_USERCOPY */
  #endif        /* __KERNEL__ */
  
  #endif /* _LINUX_THREAD_INFO_H */
diff --cc init/Kconfig
Simple merge
diff --cc mm/Makefile
Simple merge
diff --cc mm/slab.c
Simple merge
diff --cc mm/slub.c
Simple merge