[PATCH] x86/efistub: Clear decompressor BSS in native EFI entrypoint

From: Ard Biesheuvel
Date: Fri Mar 15 2024 - 14:45:07 EST


From: Ard Biesheuvel <ardb@xxxxxxxxxx>

The EFI decompressor no longer invokes the decompressor as a subsequent
boot stage, but calls into the decompression code directly.

This means that when using the native EFI entrypoint (as opposed to the
EFI handover protocol, which clears BSS explicitly), we are relying on
the firmware PE image loader to ensure that BSS is zeroed before the EFI
stub is called by the firmware.

As Radek's report proves, this is a bad idea. Not all loaders do this
correctly, which means some global variables that should default to 0x0
may have junk in them.

So clear BSS explicitly when entering via efi_pe_entry(). Note that
zeroing BSS from C code is not generally safe, but in this case, the
following assignment and dereference of a global pointer variable
ensures that the memset() cannot be reordered.

Cc: <stable@xxxxxxxxxx> # v6.1+
Reported-by: Radek Podgorny <radek@xxxxxxxxxxx>
Signed-off-by: Ard Biesheuvel <ardb@xxxxxxxxxx>
---
drivers/firmware/efi/libstub/x86-stub.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index 35413c8dfc25..2096ae09438e 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -21,6 +21,8 @@
#include "efistub.h"
#include "x86-stub.h"

+extern char _bss[], _ebss[];
+
const efi_system_table_t *efi_system_table;
const efi_dxe_services_table_t *efi_dxe_table;
static efi_loaded_image_t *image = NULL;
@@ -474,6 +476,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_status_t status;
char *cmdline_ptr;

+ memset(_bss, 0, _ebss - _bss);
+
efi_system_table = sys_table_arg;

/* Check if we were booted by the EFI firmware */
@@ -967,8 +971,6 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
void efi_handover_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
struct boot_params *boot_params)
{
- extern char _bss[], _ebss[];
-
memset(_bss, 0, _ebss - _bss);
efi_stub_entry(handle, sys_table_arg, boot_params);
}
--
2.44.0.291.gc1ea87d7ee-goog