From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754648AbcEXWuX (ORCPT ); Tue, 24 May 2016 18:50:23 -0400 Received: from mail.kernel.org ([198.145.29.136]:36643 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932098AbcEXWsy (ORCPT ); Tue, 24 May 2016 18:48:54 -0400 From: Andy Lutomirski To: x86@kernel.org Cc: linux-kernel@vger.kernel.org, Borislav Petkov , Kees Cook , Brian Gerst , Andy Lutomirski Subject: [PATCH 3/7] x86/uaccess: Give uaccess faults their own handler Date: Tue, 24 May 2016 15:48:40 -0700 Message-Id: <9f880e410d704e8fbde7a294439815343af0a242.1464129798.git.luto@kernel.org> X-Mailer: git-send-email 2.5.5 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This will give us a single piece of code to edit to harden our uaccess fault handling. Signed-off-by: Andy Lutomirski --- 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 -#include +#include #include 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