Skip to content

Commit 21cb9b4

Browse files
nivedita76Ingo Molnar
authored andcommitted
efi/x86: Always relocate the kernel for EFI handover entry
Commit d5cdf4c ("efi/x86: Don't relocate the kernel unless necessary") tries to avoid relocating the kernel in the EFI stub as far as possible. However, when systemd-boot is used to boot a unified kernel image [1], the image is constructed by embedding the bzImage as a .linux section in a PE executable that contains a small stub loader from systemd that will call the EFI stub handover entry, together with additional sections and potentially an initrd. When this image is constructed, by for example dracut, the initrd is placed after the bzImage without ensuring that at least init_size bytes are available for the bzImage. If the kernel is not relocated by the EFI stub, this could result in the compressed kernel's startup code in head_{32,64}.S overwriting the initrd. To prevent this, unconditionally relocate the kernel if the EFI stub was entered via the handover entry point. [1] https://systemd.io/BOOT_LOADER_SPECIFICATION/#type-2-efi-unified-kernel-images Fixes: d5cdf4c ("efi/x86: Don't relocate the kernel unless necessary") Reported-by: Sergey Shatunov <[email protected]> Signed-off-by: Arvind Sankar <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Link: https://lore.kernel.org/r/[email protected] Link: https://lore.kernel.org/r/[email protected]
1 parent 105cb95 commit 21cb9b4

File tree

1 file changed

+10
-4
lines changed

1 file changed

+10
-4
lines changed

drivers/firmware/efi/libstub/x86-stub.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -740,8 +740,15 @@ unsigned long efi_main(efi_handle_t handle,
740740
* now use KERNEL_IMAGE_SIZE, which will be 512MiB, the same as what
741741
* KASLR uses.
742742
*
743-
* Also relocate it if image_offset is zero, i.e. we weren't loaded by
744-
* LoadImage, but we are not aligned correctly.
743+
* Also relocate it if image_offset is zero, i.e. the kernel wasn't
744+
* loaded by LoadImage, but rather by a bootloader that called the
745+
* handover entry. The reason we must always relocate in this case is
746+
* to handle the case of systemd-boot booting a unified kernel image,
747+
* which is a PE executable that contains the bzImage and an initrd as
748+
* COFF sections. The initrd section is placed after the bzImage
749+
* without ensuring that there are at least init_size bytes available
750+
* for the bzImage, and thus the compressed kernel's startup code may
751+
* overwrite the initrd unless it is moved out of the way.
745752
*/
746753

747754
buffer_start = ALIGN(bzimage_addr - image_offset,
@@ -751,8 +758,7 @@ unsigned long efi_main(efi_handle_t handle,
751758
if ((buffer_start < LOAD_PHYSICAL_ADDR) ||
752759
(IS_ENABLED(CONFIG_X86_32) && buffer_end > KERNEL_IMAGE_SIZE) ||
753760
(IS_ENABLED(CONFIG_X86_64) && buffer_end > MAXMEM_X86_64_4LEVEL) ||
754-
(image_offset == 0 && !IS_ALIGNED(bzimage_addr,
755-
hdr->kernel_alignment))) {
761+
(image_offset == 0)) {
756762
status = efi_relocate_kernel(&bzimage_addr,
757763
hdr->init_size, hdr->init_size,
758764
hdr->pref_address,

0 commit comments

Comments
 (0)