Commit 223b3917 authored by James Morse's avatar James Morse Committed by Sasha Levin

arm64: kernel: Save and restore addr_limit on exception entry

commit e19a6ee2 upstream.

If we take an exception while at EL1, the exception handler inherits
the original context's addr_limit value. 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.
Acked-by: default avatarWill Deacon <will.deacon@arm.com>
Reviewed-by: default avatarMark Rutland <mark.rutland@arm.com>
Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
[ backport to stop perf misusing inherited addr_limit.
  Removed code interacting with UAO and the irqstack ]
Link: https://bugs.chromium.org/p/project-zero/issues/detail?id=822Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Cc: <stable@vger.kernel.org> #4.1
Signed-off-by: default avatarSasha Levin <alexander.levin@verizon.com>
parent 5c576457
...@@ -116,6 +116,8 @@ struct pt_regs { ...@@ -116,6 +116,8 @@ struct pt_regs {
}; };
u64 orig_x0; u64 orig_x0;
u64 syscallno; u64 syscallno;
u64 orig_addr_limit;
u64 unused; // maintain 16 byte alignment
}; };
#define arch_has_single_step() (1) #define arch_has_single_step() (1)
......
...@@ -58,6 +58,7 @@ int main(void) ...@@ -58,6 +58,7 @@ int main(void)
DEFINE(S_PC, offsetof(struct pt_regs, pc)); DEFINE(S_PC, offsetof(struct pt_regs, pc));
DEFINE(S_ORIG_X0, offsetof(struct pt_regs, orig_x0)); DEFINE(S_ORIG_X0, offsetof(struct pt_regs, orig_x0));
DEFINE(S_SYSCALLNO, offsetof(struct pt_regs, syscallno)); DEFINE(S_SYSCALLNO, offsetof(struct pt_regs, syscallno));
DEFINE(S_ORIG_ADDR_LIMIT, offsetof(struct pt_regs, orig_addr_limit));
DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs)); DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));
BLANK(); BLANK();
DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id)); DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id));
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/esr.h> #include <asm/esr.h>
#include <asm/memory.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
#include <asm/unistd.h> #include <asm/unistd.h>
...@@ -93,7 +94,13 @@ ...@@ -93,7 +94,13 @@
disable_step_tsk x19, x20 // exceptions when scheduling. disable_step_tsk x19, x20 // exceptions when scheduling.
.else .else
add x21, sp, #S_FRAME_SIZE add x21, sp, #S_FRAME_SIZE
.endif get_thread_info tsk
/* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */
ldr x20, [tsk, #TI_ADDR_LIMIT]
str x20, [sp, #S_ORIG_ADDR_LIMIT]
mov x20, #TASK_SIZE_64
str x20, [tsk, #TI_ADDR_LIMIT]
.endif /* \el == 0 */
mrs x22, elr_el1 mrs x22, elr_el1
mrs x23, spsr_el1 mrs x23, spsr_el1
stp lr, x21, [sp, #S_LR] stp lr, x21, [sp, #S_LR]
...@@ -117,6 +124,12 @@ ...@@ -117,6 +124,12 @@
.endm .endm
.macro kernel_exit, el, ret = 0 .macro kernel_exit, el, ret = 0
.if \el != 0
/* Restore the task's original addr_limit. */
ldr x20, [sp, #S_ORIG_ADDR_LIMIT]
str x20, [tsk, #TI_ADDR_LIMIT]
.endif
ldp x21, x22, [sp, #S_PC] // load ELR, SPSR ldp x21, x22, [sp, #S_PC] // load ELR, SPSR
.if \el == 0 .if \el == 0
ct_user_enter ct_user_enter
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment