]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 4 Jan 2023 14:52:49 +0000 (15:52 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 4 Jan 2023 14:52:49 +0000 (15:52 +0100)
added patches:
arm64-efi-execute-runtime-services-from-a-dedicated-stack.patch

queue-5.15/arm64-efi-execute-runtime-services-from-a-dedicated-stack.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/arm64-efi-execute-runtime-services-from-a-dedicated-stack.patch b/queue-5.15/arm64-efi-execute-runtime-services-from-a-dedicated-stack.patch
new file mode 100644 (file)
index 0000000..821b67f
--- /dev/null
@@ -0,0 +1,125 @@
+From ff7a167961d1b97e0e205f245f806e564d3505e7 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Mon, 5 Dec 2022 11:31:25 +0100
+Subject: arm64: efi: Execute runtime services from a dedicated stack
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+commit ff7a167961d1b97e0e205f245f806e564d3505e7 upstream.
+
+With the introduction of PRMT in the ACPI subsystem, the EFI rts
+workqueue is no longer the only caller of efi_call_virt_pointer() in the
+kernel. This means the EFI runtime services lock is no longer sufficient
+to manage concurrent calls into firmware, but also that firmware calls
+may occur that are not marshalled via the workqueue mechanism, but
+originate directly from the caller context.
+
+For added robustness, and to ensure that the runtime services have 8 KiB
+of stack space available as per the EFI spec, introduce a spinlock
+protected EFI runtime stack of 8 KiB, where the spinlock also ensures
+serialization between the EFI rts workqueue (which itself serializes EFI
+runtime calls) and other callers of efi_call_virt_pointer().
+
+While at it, use the stack pivot to avoid reloading the shadow call
+stack pointer from the ordinary stack, as doing so could produce a
+gadget to defeat it.
+
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/include/asm/efi.h       |    3 +++
+ arch/arm64/kernel/efi-rt-wrapper.S |   13 ++++++++++++-
+ arch/arm64/kernel/efi.c            |   27 +++++++++++++++++++++++++++
+ 3 files changed, 42 insertions(+), 1 deletion(-)
+
+--- a/arch/arm64/include/asm/efi.h
++++ b/arch/arm64/include/asm/efi.h
+@@ -25,6 +25,7 @@ int efi_set_mapping_permissions(struct m
+ ({                                                                    \
+       efi_virtmap_load();                                             \
+       __efi_fpsimd_begin();                                           \
++      spin_lock(&efi_rt_lock);                                        \
+ })
+ #define arch_efi_call_virt(p, f, args...)                             \
+@@ -36,10 +37,12 @@ int efi_set_mapping_permissions(struct m
+ #define arch_efi_call_virt_teardown()                                 \
+ ({                                                                    \
++      spin_unlock(&efi_rt_lock);                                      \
+       __efi_fpsimd_end();                                             \
+       efi_virtmap_unload();                                           \
+ })
++extern spinlock_t efi_rt_lock;
+ efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...);
+ #define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
+--- a/arch/arm64/kernel/efi-rt-wrapper.S
++++ b/arch/arm64/kernel/efi-rt-wrapper.S
+@@ -16,6 +16,12 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
+        */
+       stp     x1, x18, [sp, #16]
++      ldr_l   x16, efi_rt_stack_top
++      mov     sp, x16
++#ifdef CONFIG_SHADOW_CALL_STACK
++      str     x18, [sp, #-16]!
++#endif
++
+       /*
+        * We are lucky enough that no EFI runtime services take more than
+        * 5 arguments, so all are passed in registers rather than via the
+@@ -29,6 +35,7 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
+       mov     x4, x6
+       blr     x8
++      mov     sp, x29
+       ldp     x1, x2, [sp, #16]
+       cmp     x2, x18
+       ldp     x29, x30, [sp], #32
+@@ -42,6 +49,10 @@ 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_l   x18, efi_rt_stack_top
++      ldr     x18, [x18, #-16]
++#endif
++
+       b       efi_handle_corrupted_x18        // tail call
+ SYM_FUNC_END(__efi_rt_asm_wrapper)
+--- a/arch/arm64/kernel/efi.c
++++ b/arch/arm64/kernel/efi.c
+@@ -144,3 +144,30 @@ asmlinkage efi_status_t efi_handle_corru
+       pr_err_ratelimited(FW_BUG "register x18 corrupted by EFI %s\n", f);
+       return s;
+ }
++
++DEFINE_SPINLOCK(efi_rt_lock);
++
++asmlinkage u64 *efi_rt_stack_top __ro_after_init;
++
++/* EFI requires 8 KiB of stack space for runtime services */
++static_assert(THREAD_SIZE >= SZ_8K);
++
++static int __init arm64_efi_rt_init(void)
++{
++      void *p;
++
++      if (!efi_enabled(EFI_RUNTIME_SERVICES))
++              return 0;
++
++      p = __vmalloc_node(THREAD_SIZE, THREAD_ALIGN, GFP_KERNEL,
++                         NUMA_NO_NODE, &&l);
++l:    if (!p) {
++              pr_warn("Failed to allocate EFI runtime stack\n");
++              clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
++              return -ENOMEM;
++      }
++
++      efi_rt_stack_top = p + THREAD_SIZE;
++      return 0;
++}
++core_initcall(arm64_efi_rt_init);
index 85762eb4af5265fa5497dedd11b023206c7342bb..5b374b2cbd695097546e1133174c1f25852101c5 100644 (file)
@@ -137,3 +137,4 @@ drm-connector-send-hotplug-uevent-on-connector-cleanup.patch
 drm-vmwgfx-validate-the-box-size-for-the-snooped-cursor.patch
 drm-i915-dsi-fix-vbt-send-packet-port-selection-for-dual-link-dsi.patch
 drm-ingenic-fix-missing-platform_driver_unregister-call-in-ingenic_drm_init.patch
+arm64-efi-execute-runtime-services-from-a-dedicated-stack.patch