diff options
author | James Morse <james.morse@arm.com> | 2016-06-20 13:28:01 -0400 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2016-07-07 10:55:37 -0400 |
commit | e19a6ee2460bdd0d0055a6029383422773f9999a (patch) | |
tree | f8e7898101568c82617d7afd66e712b9f0538a0e /arch/arm64/kernel/entry.S | |
parent | 4c2e07c6a29e0129e975727b9f57eede813eea85 (diff) |
arm64: kernel: Save and restore UAO and addr_limit on exception entry
If we take an exception while at EL1, the exception handler inherits
the original context's addr_limit and PSTATE.UAO values. To be consistent
always reset addr_limit and PSTATE.UAO on (re-)entry to EL1. This
prevents accidental re-use of the original context's addr_limit.
Based on a similar patch for arm from Russell King.
Cc: <stable@vger.kernel.org> # 4.6-
Acked-by: Will Deacon <will.deacon@arm.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: James Morse <james.morse@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm64/kernel/entry.S')
-rw-r--r-- | arch/arm64/kernel/entry.S | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 12e8d2bcb3f9..6c3b7345a6c4 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/errno.h> | 28 | #include <asm/errno.h> |
29 | #include <asm/esr.h> | 29 | #include <asm/esr.h> |
30 | #include <asm/irq.h> | 30 | #include <asm/irq.h> |
31 | #include <asm/memory.h> | ||
31 | #include <asm/thread_info.h> | 32 | #include <asm/thread_info.h> |
32 | #include <asm/unistd.h> | 33 | #include <asm/unistd.h> |
33 | 34 | ||
@@ -97,7 +98,14 @@ | |||
97 | mov x29, xzr // fp pointed to user-space | 98 | mov x29, xzr // fp pointed to user-space |
98 | .else | 99 | .else |
99 | add x21, sp, #S_FRAME_SIZE | 100 | add x21, sp, #S_FRAME_SIZE |
100 | .endif | 101 | get_thread_info tsk |
102 | /* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */ | ||
103 | ldr x20, [tsk, #TI_ADDR_LIMIT] | ||
104 | str x20, [sp, #S_ORIG_ADDR_LIMIT] | ||
105 | mov x20, #TASK_SIZE_64 | ||
106 | str x20, [tsk, #TI_ADDR_LIMIT] | ||
107 | ALTERNATIVE(nop, SET_PSTATE_UAO(0), ARM64_HAS_UAO, CONFIG_ARM64_UAO) | ||
108 | .endif /* \el == 0 */ | ||
101 | mrs x22, elr_el1 | 109 | mrs x22, elr_el1 |
102 | mrs x23, spsr_el1 | 110 | mrs x23, spsr_el1 |
103 | stp lr, x21, [sp, #S_LR] | 111 | stp lr, x21, [sp, #S_LR] |
@@ -128,6 +136,14 @@ | |||
128 | .endm | 136 | .endm |
129 | 137 | ||
130 | .macro kernel_exit, el | 138 | .macro kernel_exit, el |
139 | .if \el != 0 | ||
140 | /* Restore the task's original addr_limit. */ | ||
141 | ldr x20, [sp, #S_ORIG_ADDR_LIMIT] | ||
142 | str x20, [tsk, #TI_ADDR_LIMIT] | ||
143 | |||
144 | /* No need to restore UAO, it will be restored from SPSR_EL1 */ | ||
145 | .endif | ||
146 | |||
131 | ldp x21, x22, [sp, #S_PC] // load ELR, SPSR | 147 | ldp x21, x22, [sp, #S_PC] // load ELR, SPSR |
132 | .if \el == 0 | 148 | .if \el == 0 |
133 | ct_user_enter | 149 | ct_user_enter |
@@ -406,7 +422,6 @@ el1_irq: | |||
406 | bl trace_hardirqs_off | 422 | bl trace_hardirqs_off |
407 | #endif | 423 | #endif |
408 | 424 | ||
409 | get_thread_info tsk | ||
410 | irq_handler | 425 | irq_handler |
411 | 426 | ||
412 | #ifdef CONFIG_PREEMPT | 427 | #ifdef CONFIG_PREEMPT |