[PATCH] arm64: efi: Make runtime service wrapper more robust

Ard Biesheuvel ardb at kernel.org
Mon Nov 28 01:49:39 PST 2022


Prevent abuse of the runtime service wrapper code by avoiding restoring
the shadow call stack pointer from the ordinary stack, or the stack
pointer itself from a GPR. Also, given that the exception recovery
routine is never called in an ordinary way, it doesn't need BTI landing
pads so it can be SYM_CODE rather than SYM_FUNC.

Cc: Sami Tolvanen <samitolvanen at google.com>
Cc: Kees Cook <keescook at chromium.org>
Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
---
 arch/arm64/kernel/efi-rt-wrapper.S | 16 +++++++++-------
 arch/arm64/kernel/efi.c            |  6 +++++-
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/kernel/efi-rt-wrapper.S b/arch/arm64/kernel/efi-rt-wrapper.S
index 67babd5f04c27c7a..afd3e81e1b627b87 100644
--- a/arch/arm64/kernel/efi-rt-wrapper.S
+++ b/arch/arm64/kernel/efi-rt-wrapper.S
@@ -28,7 +28,7 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
 	stp	x27, x28, [sp, #96]
 
 	adr_this_cpu	x8, __efi_rt_asm_recover_sp, x9
-	str		x29, [x8]
+	stp		x29, x18, [x8]
 
 	/*
 	 * We are lucky enough that no EFI runtime services take more than
@@ -56,15 +56,17 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
 	 * called with preemption disabled and a separate shadow stack is used
 	 * for interrupts.
 	 */
-	mov	x18, x2
+#ifdef CONFIG_SHADOW_CALL_STACK
+	ldr_this_cpu	x18, __efi_rt_asm_recover_sp + 8, x9
+#endif
+
 	b	efi_handle_corrupted_x18	// tail call
 SYM_FUNC_END(__efi_rt_asm_wrapper)
 
-SYM_FUNC_START(__efi_rt_asm_recover)
-	ldr_this_cpu	x8, __efi_rt_asm_recover_sp, x9
-	mov		sp, x8
+SYM_CODE_START(__efi_rt_asm_recover)
+	mov	sp, x30
 
-	ldp	x0,  x18, [sp, #16]
+	ldr	x0, [sp, #16]
 	ldp	x19, x20, [sp, #32]
 	ldp	x21, x22, [sp, #48]
 	ldp	x23, x24, [sp, #64]
@@ -73,4 +75,4 @@ SYM_FUNC_START(__efi_rt_asm_recover)
 	ldp	x29, x30, [sp], #112
 
 	b	efi_handle_runtime_exception
-SYM_FUNC_END(__efi_rt_asm_recover)
+SYM_CODE_END(__efi_rt_asm_recover)
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 8d36e66a6e64cdaa..db7bdce1c7da578b 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -130,7 +130,7 @@ asmlinkage efi_status_t efi_handle_corrupted_x18(efi_status_t s, const char *f)
 	return s;
 }
 
-asmlinkage DEFINE_PER_CPU(u64, __efi_rt_asm_recover_sp);
+asmlinkage DEFINE_PER_CPU(u64[2], __efi_rt_asm_recover_sp);
 
 asmlinkage efi_status_t __efi_rt_asm_recover(void);
 
@@ -151,6 +151,10 @@ bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg)
 	add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
 	dump_stack();
 
+	regs->regs[30] = __this_cpu_read(__efi_rt_asm_recover_sp[0]);
+#ifdef CONFIG_SHADOW_CALL_STACK
+	regs->regs[18] = __this_cpu_read(__efi_rt_asm_recover_sp[1]);
+#endif
 	regs->pc = (u64)__efi_rt_asm_recover;
 	return true;
 }
-- 
2.35.1




More information about the linux-arm-kernel mailing list