* [PATCH] efi/libstub: Allocate the INITRD table in ACPI reclaim memory
@ 2026-10-12 13:37 Sebastien WENSKE
2026-10-22 15:39 ` [PATCH] x86/efi: Drop stale INITRD table entry on kexec boot Jaehee Park
0 siblings, 1 reply; 2+ messages in thread
From: Sebastien WENSKE @ 2026-10-12 13:37 UTC (permalink / raw)
To: Ard Biesheuvel, linux-efi
Cc: swenske, Ilias Apalodimas, James Le Cuirot, linux-kernel, stable
Commit 6e62d1c6f2c7 ("efi: Wipe INITRD config table from memory after
consumption") makes the kernel clear the base and size of the
LINUX_EFI_INITRD_MEDIA_GUID configuration table once it has read them,
so that a kexec'd kernel no longer picks up a stale initrd.
However, the stub allocates that table from EFI_LOADER_DATA, which the
kernel that consumes it treats as ordinary RAM, while the configuration
table entry pointing at it survives kexec. A kexec'd kernel therefore
finds the same address in the configuration table, and clears 16 bytes
there again, in memory that may by then hold anything - including the
kexec'd kernel's own image, which kexec_file_load() is free to place
there.
Seen on x86_64 v7.2.10 under QEMU with Debian's OVMF 2025.02 Secure
Boot capable build (OVMF_CODE_4M.secboot.fd, no keys enrolled), the
initrd handed to the stub through the LINUX_EFI_INITRD_MEDIA_GUID
device path (systemd-stub UKI). A kexec reboot (kexec_file_load(),
bzImage64, with an initrd) loads the new kernel at 0x1ca00000; the
stale table is at 0x1d4bcf98, in the middle of tcp_parse_options() in
that image. The kexec'd kernel boots, then oopses on the first incoming
SYN, 16 bytes of its text zeroed:
BUG: kernel NULL pointer dereference, address: 0000000000000002
RIP: 0010:tcp_parse_options+0xe7/0x2f0
Code: a5 4c 29 e1 89 c8 0f b6 4d 12 83 e0 3f 83 e1 c0 09 c1 88 4d 12 eb de 41 83 fe 04 75 d8 41 f6 44 24 0d 02 74 d0 45 85 d2 75 cb <0f> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 66 39 d0 89 d1
Call Trace:
<IRQ>
tcp_conn_request+0x270/0x9d0
tcp_rcv_state_process+0x147/0x1560
tcp_v4_do_rcv+0xc1/0x260
tcp_v4_rcv+0x110e/0x1190
A debug print added before the wipe shows what the kexec'd kernel reads
at the table's address - its own text:
efi: INITRD table at 0x1d4bcf98:
base 0xc274c085660241b7 size 0x8c0c1661455b70f
Whether a given kernel crashes depends on what happens to land at that
address: v7.2.9 clears 16 bytes elsewhere in its image without any
visible failure, and bisecting v7.2.9..v7.2.10 ends on an unrelated
commit that only shifts the image's layout.
Allocate the table from EFI_ACPI_RECLAIM_MEMORY instead, as the stub
already does for the RNG seed table so that it survives a kexec reboot.
The table then stays where it is across kexec, and the wipe always
lands on the table itself.
Fixes: 6e62d1c6f2c7 ("efi: Wipe INITRD config table from memory after consumption")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Sebastien WENSKE <sebastien@wenske.fr>
---
Tested on x86_64 under QEMU (q35, KVM) with Debian's OVMF 2025.02
(OVMF_CODE_4M.secboot.fd and OVMF_CODE_4M.fd), booting a systemd-stub
UKI, then rebooting with kexec_file_load() and an initrd:
- v7.2.10: the oops above in 6 out of 6 kexec reboots under the
secboot build (none under the plain one). With this patch: 2 out of
2 come up, and two chained kexec'd kernels read the cleared table
back (base 0x0 size 0x0), now in ACPI data memory.
- v7.3-rc7 without this patch: no visible failure, but the same debug
print shows the kexec'd kernel reading its own image at the table's
address - and so clearing 16 bytes of it:
efi: INITRD table at 0x1d4bcf98:
base 0xf413863894c40c4 size 0x415c74063c1246b6 - inside this
kernel's image
With this patch: kexec reboots (chained too) come up under both OVMF
builds. It builds without warnings, W=1 included for libstub.
Not tested: other architectures, real hardware.
Reserving the table with efi_mem_reserve() in efi_config_parse_tables()
instead doesn't help on x86: efi_arch_mem_reserve() only handles
EFI_BOOT_SERVICES_DATA ("Failed to lookup EFI memory descriptor"), so
kexec still places the next kernel over the table. Note that a kernel
kexec'd from one without this patch still finds the table in loader
data memory.
drivers/firmware/efi/libstub/efi-stub-helper.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index f27f2e1f0..9293b8b31 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -641,8 +641,14 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
EFISTUB_EVT_INITRD) == EFI_SUCCESS)
efi_info("Measured initrd data into PCR 9\n");
- status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(initrd),
- (void **)&tbl);
+ /*
+ * Use EFI_ACPI_RECLAIM_MEMORY so the table survives a kexec reboot:
+ * configuration tables do, and the kernel wipes this one once it has
+ * consumed it - a kexec'd kernel wipes it again, at the same address,
+ * which in EFI_LOADER_DATA memory may hold anything by then.
+ */
+ status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
+ sizeof(initrd), (void **)&tbl);
if (status != EFI_SUCCESS)
goto free_initrd;
base-commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907
--
2.47.3
^ permalink raw reply [flat|nested] 2+ messages in thread* [PATCH] x86/efi: Drop stale INITRD table entry on kexec boot
2026-10-12 13:37 [PATCH] efi/libstub: Allocate the INITRD table in ACPI reclaim memory Sebastien WENSKE
@ 2026-10-22 15:39 ` Jaehee Park
0 siblings, 0 replies; 2+ messages in thread
From: Jaehee Park @ 2026-10-22 15:39 UTC (permalink / raw)
To: ardb
Cc: sebastien, ilias.apalodimas, tglx, mingo, bp, dave.hansen, x86,
hpa, linux-efi, linux-kernel
From: Jaehee Park <jpark@coreweave.com>
The EFI stub allocates the INITRD configuration table in EFI_LOADER_DATA
memory. That memory can be reused after boot, but the configuration table
entry pointing to it survives kexec.
When a kexec'd kernel consumes the stale entry, efi_config_parse_tables()
clears the base and size fields at the old table address. If the new
initramfs occupies that memory, this overwrites 16 bytes of compressed
data and prevents the capture kernel from unpacking its initramfs.
Invalidate the INITRD entry when reusing the EFI configuration tables on
x86. Kexec supplies the new initrd through boot_params, so the capture
kernel does not need the old table.
Fixes: 6e62d1c6f2c7 ("efi: Wipe INITRD config table from memory after consumption")
Cc: stable@vger.kernel.org
Signed-off-by: Jaehee Park <jpark@coreweave.com>
---
Hi Ard, Sebastien,
I independently diagnosed and locally fixed this issue on October 6
while debugging kdump on an x86_64 L40S system. I was preparing to submit
my fix after internal review and found your October 12 proposal.
In my case, the stale INITRD table address overlapped the capture
initramfs. The capture kernel reported:
Initramfs unpacking failed: ZSTD-compressed data is corrupt
Failed to execute /init (error -2)
Kernel panic - not syncing: No working init found.
My local fix invalidates the inherited INITRD entry in efi_reuse_config()
instead of changing the stub allocation. With that fix, the capture
initramfs checksum remained unchanged through successful unpacking and
kdump saved a crash dump.
The tested version also removed the data->smbios early return. I have
left that change out of this submission to keep the initial patch small.
This reduced version has not been boot-tested separately. It retains
the existing SMBIOS guard, so it does not cover SMBIOS3-only systems.
Would you prefer handling that guard as part of this fix?
Would invalidating the inherited entry also be useful when kexec boots
from a kernel whose stub allocated the table in EFI_LOADER_DATA? The
allocation change appears to address the lifetime at its source, while
this change prevents the incoming x86 kernel from consuming a stale
entry created by an older kernel.
I have not tested the ACPI reclaim patch, so I am not offering a
Tested-by for that patch.
Thanks,
Jaehee
arch/x86/platform/efi/quirks.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -615,6 +615,13 @@
if (!efi_guidcmp(guid, EFI_MEMORY_ATTRIBUTES_TABLE_GUID))
((efi_config_table_64_t *)p)->table = EFI_INVALID_TABLE_ADDR;
+ /*
+ * The EFI stub allocated this table in loader data, which may
+ * have been reused. Kexec passes its initrd in boot_params.
+ */
+ if (!efi_guidcmp(guid, LINUX_EFI_INITRD_MEDIA_GUID))
+ ((efi_config_table_64_t *)p)->table = EFI_INVALID_TABLE_ADDR;
+
p += sz;
}
early_memunmap(tablep, nr_tables * sz);
base-commit: 7be4bc52fd9e0e55dc9a2e0232b89427d2c4b614
--
2.54.0
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-22 15:39 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-12 13:37 [PATCH] efi/libstub: Allocate the INITRD table in ACPI reclaim memory Sebastien WENSKE
2026-10-22 15:39 ` [PATCH] x86/efi: Drop stale INITRD table entry on kexec boot Jaehee Park
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®