From 76e9e5bbd9122e10e028585c6fac95a5e09cf9e6 Mon Sep 17 00:00:00 2001 From: James Morse Date: Mon, 20 Jun 2016 18:28:01 +0100 Subject: [PATCH] arm64: kernel: Save and restore UAO and addr_limit on exception entry commit e19a6ee2460bdd0d0055a6029383422773f9999a upstream. 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. Change-Id: Iaef0dfaa335bd665b15718a2f1bba775ffc18a11 Acked-by: Will Deacon Reviewed-by: Mark Rutland Signed-off-by: James Morse Signed-off-by: Will Deacon Signed-off-by: Greg Kroah-Hartman Git-commit: e19a6ee2460bdd0d0055a6029383422773f9999a Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [psodagud@codeaurora.org bring in changes missed in commit a5a095803c2469cd3d1fc5a11acc1a8150b7c9f4] Signed-off-by: Prasad Sodagudi --- arch/arm64/kernel/entry.S | 3 +++ arch/arm64/mm/fault.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 9bcc0ad84917..cab1821db191 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -104,6 +104,7 @@ str x20, [sp, #S_ORIG_ADDR_LIMIT] mov x20, #TASK_SIZE_64 str x20, [tsk, #TI_ADDR_LIMIT] + ALTERNATIVE(nop, SET_PSTATE_UAO(0), ARM64_HAS_UAO, CONFIG_ARM64_UAO) .endif /* \el == 0 */ mrs x22, elr_el1 mrs x23, spsr_el1 @@ -139,6 +140,8 @@ /* Restore the task's original addr_limit. */ ldr x20, [sp, #S_ORIG_ADDR_LIMIT] str x20, [tsk, #TI_ADDR_LIMIT] + + /* No need to restore UAO, it will be restored from SPSR_EL1 */ .endif ldp x21, x22, [sp, #S_PC] // load ELR, SPSR diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 68cd3bb8eb89..eacaee18645b 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -291,7 +291,8 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, } if (permission_fault(esr) && (addr < USER_DS)) { - if (get_fs() == KERNEL_DS) + /* regs->orig_addr_limit may be 0 if we entered from EL0 */ + if (regs->orig_addr_limit == KERNEL_DS) die("Accessing user space memory with fs=KERNEL_DS", regs, esr); if (!search_exception_tables(regs->pc))