This will give us a single piece of code to edit to harden our
uaccess fault handling.

Signed-off-by: Andy Lutomirski <l...@kernel.org>
---
 arch/x86/include/asm/uaccess.h | 16 ++++++++--------
 arch/x86/lib/getuser.S         | 12 ++++++------
 arch/x86/lib/putuser.S         | 10 +++++-----
 arch/x86/mm/extable.c          | 27 +++++++++++++++++++++++----
 4 files changed, 42 insertions(+), 23 deletions(-)

diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 5b65b2110167..1bc0d18446d7 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -205,8 +205,8 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 
0ULL, 0UL))
                     "4:        movl %3,%0\n"                           \
                     "  jmp 3b\n"                                       \
                     ".previous\n"                                      \
-                    _ASM_EXTABLE(1b, 4b)                               \
-                    _ASM_EXTABLE(2b, 4b)                               \
+                    _ASM_EXTABLE_HANDLE(1b, 4b, ex_handler_uaccess)    \
+                    _ASM_EXTABLE_HANDLE(2b, 4b, ex_handler_uaccess)    \
                     : "=r" (err)                                       \
                     : "A" (x), "r" (addr), "i" (errret), "0" (err))
 
@@ -374,7 +374,7 @@ do {                                                        
                \
                     "  xor"itype" %"rtype"1,%"rtype"1\n"               \
                     "  jmp 2b\n"                                       \
                     ".previous\n"                                      \
-                    _ASM_EXTABLE(1b, 3b)                               \
+                    _ASM_EXTABLE_HANDLE(1b, 3b, ex_handler_uaccess)    \
                     : "=r" (err), ltype(x)                             \
                     : "m" (__m(addr)), "i" (errret), "0" (err))
 
@@ -446,7 +446,7 @@ struct __large_struct { unsigned long buf[100]; };
                     "3:        mov %3,%0\n"                            \
                     "  jmp 2b\n"                                       \
                     ".previous\n"                                      \
-                    _ASM_EXTABLE(1b, 3b)                               \
+                    _ASM_EXTABLE_HANDLE(1b, 3b, ex_handler_uaccess)    \
                     : "=r"(err)                                        \
                     : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err))
 
@@ -574,7 +574,7 @@ extern void __cmpxchg_wrong_size(void)
                        "3:\tmov     %3, %0\n"                          \
                        "\tjmp     2b\n"                                \
                        "\t.previous\n"                                 \
-                       _ASM_EXTABLE(1b, 3b)                            \
+                       _ASM_EXTABLE_HANDLE(1b, 3b, ex_handler_uaccess) \
                        : "+r" (__ret), "=a" (__old), "+m" (*(ptr))     \
                        : "i" (-EFAULT), "q" (__new), "1" (__old)       \
                        : "memory"                                      \
@@ -590,7 +590,7 @@ extern void __cmpxchg_wrong_size(void)
                        "3:\tmov     %3, %0\n"                          \
                        "\tjmp     2b\n"                                \
                        "\t.previous\n"                                 \
-                       _ASM_EXTABLE(1b, 3b)                            \
+                       _ASM_EXTABLE_HANDLE(1b, 3b, ex_handler_uaccess) \
                        : "+r" (__ret), "=a" (__old), "+m" (*(ptr))     \
                        : "i" (-EFAULT), "r" (__new), "1" (__old)       \
                        : "memory"                                      \
@@ -606,7 +606,7 @@ extern void __cmpxchg_wrong_size(void)
                        "3:\tmov     %3, %0\n"                          \
                        "\tjmp     2b\n"                                \
                        "\t.previous\n"                                 \
-                       _ASM_EXTABLE(1b, 3b)                            \
+                       _ASM_EXTABLE_HANDLE(1b, 3b, ex_handler_uaccess) \
                        : "+r" (__ret), "=a" (__old), "+m" (*(ptr))     \
                        : "i" (-EFAULT), "r" (__new), "1" (__old)       \
                        : "memory"                                      \
@@ -625,7 +625,7 @@ extern void __cmpxchg_wrong_size(void)
                        "3:\tmov     %3, %0\n"                          \
                        "\tjmp     2b\n"                                \
                        "\t.previous\n"                                 \
-                       _ASM_EXTABLE(1b, 3b)                            \
+                       _ASM_EXTABLE_HANDLE(1b, 3b, ex_handler_uaccess) \
                        : "+r" (__ret), "=a" (__old), "+m" (*(ptr))     \
                        : "i" (-EFAULT), "r" (__new), "1" (__old)       \
                        : "memory"                                      \
diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
index 46668cda4ffd..953b7be58300 100644
--- a/arch/x86/lib/getuser.S
+++ b/arch/x86/lib/getuser.S
@@ -116,12 +116,12 @@ bad_get_user_8:
 END(bad_get_user_8)
 #endif
 
-       _ASM_EXTABLE(1b,bad_get_user)
-       _ASM_EXTABLE(2b,bad_get_user)
-       _ASM_EXTABLE(3b,bad_get_user)
+       _ASM_EXTABLE_HANDLE(1b,bad_get_user, ex_handler_uaccess)
+       _ASM_EXTABLE_HANDLE(2b,bad_get_user, ex_handler_uaccess)
+       _ASM_EXTABLE_HANDLE(3b,bad_get_user, ex_handler_uaccess)
 #ifdef CONFIG_X86_64
-       _ASM_EXTABLE(4b,bad_get_user)
+       _ASM_EXTABLE_HANDLE(4b,bad_get_user, ex_handler_uaccess)
 #else
-       _ASM_EXTABLE(4b,bad_get_user_8)
-       _ASM_EXTABLE(5b,bad_get_user_8)
+       _ASM_EXTABLE_HANDLE(4b,bad_get_user_8, ex_handler_uaccess)
+       _ASM_EXTABLE_HANDLE(5b,bad_get_user_8, ex_handler_uaccess)
 #endif
diff --git a/arch/x86/lib/putuser.S b/arch/x86/lib/putuser.S
index e0817a12d323..16d21d630cc7 100644
--- a/arch/x86/lib/putuser.S
+++ b/arch/x86/lib/putuser.S
@@ -88,10 +88,10 @@ bad_put_user:
        EXIT
 END(bad_put_user)
 
-       _ASM_EXTABLE(1b,bad_put_user)
-       _ASM_EXTABLE(2b,bad_put_user)
-       _ASM_EXTABLE(3b,bad_put_user)
-       _ASM_EXTABLE(4b,bad_put_user)
+       _ASM_EXTABLE_HANDLE(1b,bad_put_user, ex_handler_uaccess)
+       _ASM_EXTABLE_HANDLE(2b,bad_put_user, ex_handler_uaccess)
+       _ASM_EXTABLE_HANDLE(3b,bad_put_user, ex_handler_uaccess)
+       _ASM_EXTABLE_HANDLE(4b,bad_put_user, ex_handler_uaccess)
 #ifdef CONFIG_X86_32
-       _ASM_EXTABLE(5b,bad_put_user)
+       _ASM_EXTABLE_HANDLE(5b,bad_put_user, ex_handler_uaccess)
 #endif
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index c1a25aca0365..658292fdee5e 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -1,5 +1,5 @@
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/traps.h>
 
 typedef bool (*ex_handler_t)(const struct exception_table_entry *,
@@ -26,6 +26,23 @@ bool ex_handler_default(const struct exception_table_entry 
*fixup,
 }
 EXPORT_SYMBOL(ex_handler_default);
 
+static bool uaccess_fault_okay(int trapnr, unsigned long error_code,
+                              unsigned long extra)
+{
+       return true;
+}
+
+bool ex_handler_uaccess(const struct exception_table_entry *fixup,
+                       struct pt_regs *regs, int trapnr,
+                       unsigned long error_code, unsigned long extra)
+{
+       if (!uaccess_fault_okay(trapnr, error_code, extra))
+               return false;
+
+       return ex_handler_default(fixup, regs, trapnr, error_code, extra);
+}
+EXPORT_SYMBOL(ex_handler_uaccess);
+
 bool ex_handler_fault(const struct exception_table_entry *fixup,
                      struct pt_regs *regs, int trapnr,
                      unsigned long error_code, unsigned long extra)
@@ -41,9 +58,11 @@ bool ex_handler_ext(const struct exception_table_entry 
*fixup,
                    unsigned long error_code, unsigned long extra)
 {
        /* Special hack for uaccess_err */
-       current_thread_info()->uaccess_err = 1;
-       regs->ip = ex_fixup_addr(fixup);
-       return true;
+       bool ret = ex_handler_uaccess(fixup, regs, trapnr, error_code, extra);
+
+       if (ret)
+               current_thread_info()->uaccess_err = 1;
+       return ret;
 }
 EXPORT_SYMBOL(ex_handler_ext);
 
-- 
2.5.5

Reply via email to