Skip to content

Commit

Permalink
x86/efistub: Clear BSS in EFI handover protocol entrypoint
Browse files Browse the repository at this point in the history
The so-called EFI handover protocol is value-add from the distros that
permits a loader to simply copy a PE kernel image into memory and call
an alternative entrypoint that is described by an embedded boot_params
structure.

Most implementations of this protocol do not bother to check the PE
header for minimum alignment, section placement, etc, and therefore also
don't clear the image's BSS, or even allocate enough memory for it.

Allocating more memory on the fly is rather difficult, but at least
clear the BSS region explicitly when entering in this manner, so that
the EFI stub code does not get confused by global variables that were
not zero-initialized correctly.

When booting in mixed mode, this BSS clearing must occur before any
global state is created, so clear it in the 32-bit asm entry point.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20230807162720.545787-7-ardb@kernel.org
  • Loading branch information
Ard Biesheuvel authored and Borislav Petkov (AMD) committed Aug 7, 2023
1 parent 1279206 commit d7156b9
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
14 changes: 13 additions & 1 deletion arch/x86/boot/compressed/efi_mixed.S
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,18 @@ SYM_FUNC_END(__efi64_thunk)
.code32
#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
SYM_FUNC_START(efi32_stub_entry)
call 1f
1: popl %ecx

/* Clear BSS */
xorl %eax, %eax
leal (_bss - 1b)(%ecx), %edi
leal (_ebss - 1b)(%ecx), %ecx
subl %edi, %ecx
shrl $2, %ecx
cld
rep stosl

add $0x4, %esp /* Discard return address */
popl %ecx
popl %edx
Expand Down Expand Up @@ -334,7 +346,7 @@ SYM_FUNC_END(efi32_pe_entry)
.org efi32_stub_entry + 0x200
.code64
SYM_FUNC_START_NOALIGN(efi64_stub_entry)
jmp efi_stub_entry
jmp efi_handover_entry
SYM_FUNC_END(efi64_stub_entry)
#endif

Expand Down
13 changes: 11 additions & 2 deletions drivers/firmware/efi/libstub/x86-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -970,12 +970,21 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
}

#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
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);
}

#ifndef CONFIG_EFI_MIXED
extern __alias(efi_stub_entry)
extern __alias(efi_handover_entry)
void efi32_stub_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
struct boot_params *boot_params);

extern __alias(efi_stub_entry)
extern __alias(efi_handover_entry)
void efi64_stub_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
struct boot_params *boot_params);
#endif
Expand Down

0 comments on commit d7156b9

Please sign in to comment.