aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Garnier <thgarnie@google.com>2017-09-07 11:30:46 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-09-17 13:45:33 -0400
commite33f8d32677fa4f4f8996ef46748f86aac81ccff (patch)
tree152d8320692675e6c04e141d61557114839baf71
parent2404269bc4e77a67875c8db6667be34c9913c96e (diff)
arm/syscalls: Optimize address limit check
Disable the generic address limit check in favor of an architecture specific optimized implementation. The generic implementation using pending work flags did not work well with ARM and alignment faults. The address limit is checked on each syscall return path to user-mode path as well as the irq user-mode return function. If the address limit was changed, a function is called to report data corruption (stopping the kernel or process based on configuration). The address limit check has to be done before any pending work because they can reset the address limit and the process is killed using a SIGKILL signal. For example the lkdtm address limit check does not work because the signal to kill the process will reset the user-mode address limit. Signed-off-by: Thomas Garnier <thgarnie@google.com> Signed-off-by: Kees Cook <keescook@chromium.org> Tested-by: Kees Cook <keescook@chromium.org> Tested-by: Leonard Crestez <leonard.crestez@nxp.com> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Pratyush Anand <panand@redhat.com> Cc: Dave Martin <Dave.Martin@arm.com> Cc: Will Drewry <wad@chromium.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will.deacon@arm.com> Cc: Russell King <linux@armlinux.org.uk> Cc: Andy Lutomirski <luto@amacapital.net> Cc: David Howells <dhowells@redhat.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: linux-api@vger.kernel.org Cc: Yonghong Song <yhs@fb.com> Cc: linux-arm-kernel@lists.infradead.org Link: http://lkml.kernel.org/r/1504798247-48833-4-git-send-email-keescook@chromium.org
-rw-r--r--arch/arm/kernel/entry-common.S11
-rw-r--r--arch/arm/kernel/signal.c7
2 files changed, 18 insertions, 0 deletions
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 0b60adf4a5d9..99c908226065 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -12,6 +12,7 @@
12#include <asm/unistd.h> 12#include <asm/unistd.h>
13#include <asm/ftrace.h> 13#include <asm/ftrace.h>
14#include <asm/unwind.h> 14#include <asm/unwind.h>
15#include <asm/memory.h>
15#ifdef CONFIG_AEABI 16#ifdef CONFIG_AEABI
16#include <asm/unistd-oabi.h> 17#include <asm/unistd-oabi.h>
17#endif 18#endif
@@ -48,10 +49,14 @@ ret_fast_syscall:
48 UNWIND(.fnstart ) 49 UNWIND(.fnstart )
49 UNWIND(.cantunwind ) 50 UNWIND(.cantunwind )
50 disable_irq_notrace @ disable interrupts 51 disable_irq_notrace @ disable interrupts
52 ldr r2, [tsk, #TI_ADDR_LIMIT]
53 cmp r2, #TASK_SIZE
54 blne addr_limit_check_failed
51 ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing 55 ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
52 tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK 56 tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
53 bne fast_work_pending 57 bne fast_work_pending
54 58
59
55 /* perform architecture specific actions before user return */ 60 /* perform architecture specific actions before user return */
56 arch_ret_to_user r1, lr 61 arch_ret_to_user r1, lr
57 62
@@ -74,6 +79,9 @@ ret_fast_syscall:
74 UNWIND(.cantunwind ) 79 UNWIND(.cantunwind )
75 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 80 str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
76 disable_irq_notrace @ disable interrupts 81 disable_irq_notrace @ disable interrupts
82 ldr r2, [tsk, #TI_ADDR_LIMIT]
83 cmp r2, #TASK_SIZE
84 blne addr_limit_check_failed
77 ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing 85 ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
78 tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK 86 tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
79 beq no_work_pending 87 beq no_work_pending
@@ -106,6 +114,9 @@ ENTRY(ret_to_user)
106ret_slow_syscall: 114ret_slow_syscall:
107 disable_irq_notrace @ disable interrupts 115 disable_irq_notrace @ disable interrupts
108ENTRY(ret_to_user_from_irq) 116ENTRY(ret_to_user_from_irq)
117 ldr r2, [tsk, #TI_ADDR_LIMIT]
118 cmp r2, #TASK_SIZE
119 blne addr_limit_check_failed
109 ldr r1, [tsk, #TI_FLAGS] 120 ldr r1, [tsk, #TI_FLAGS]
110 tst r1, #_TIF_WORK_MASK 121 tst r1, #_TIF_WORK_MASK
111 bne slow_work_pending 122 bne slow_work_pending
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 5814298ef0b7..b67ae12503f3 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -14,6 +14,7 @@
14#include <linux/uaccess.h> 14#include <linux/uaccess.h>
15#include <linux/tracehook.h> 15#include <linux/tracehook.h>
16#include <linux/uprobes.h> 16#include <linux/uprobes.h>
17#include <linux/syscalls.h>
17 18
18#include <asm/elf.h> 19#include <asm/elf.h>
19#include <asm/cacheflush.h> 20#include <asm/cacheflush.h>
@@ -673,3 +674,9 @@ struct page *get_signal_page(void)
673 674
674 return page; 675 return page;
675} 676}
677
678/* Defer to generic check */
679asmlinkage void addr_limit_check_failed(void)
680{
681 addr_limit_user_check();
682}