Commit 21cb9b41 authored by Arvind Sankar's avatar Arvind Sankar Committed by Ingo Molnar

efi/x86: Always relocate the kernel for EFI handover entry

Commit

  d5cdf4cf ("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: d5cdf4cf ("efi/x86: Don't relocate the kernel unless necessary")
Reported-by: default avatarSergey Shatunov <me@prok.pw>
Signed-off-by: default avatarArvind Sankar <nivedita@alum.mit.edu>
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
Link: https://lore.kernel.org/r/20200406180614.429454-2-nivedita@alum.mit.edu
Link: https://lore.kernel.org/r/20200409130434.6736-5-ardb@kernel.org
parent 105cb954
...@@ -740,8 +740,15 @@ unsigned long efi_main(efi_handle_t handle, ...@@ -740,8 +740,15 @@ unsigned long efi_main(efi_handle_t handle,
* now use KERNEL_IMAGE_SIZE, which will be 512MiB, the same as what * now use KERNEL_IMAGE_SIZE, which will be 512MiB, the same as what
* KASLR uses. * KASLR uses.
* *
* Also relocate it if image_offset is zero, i.e. we weren't loaded by * Also relocate it if image_offset is zero, i.e. the kernel wasn't
* LoadImage, but we are not aligned correctly. * loaded by LoadImage, but rather by a bootloader that called the
* handover entry. The reason we must always relocate in this case is
* to handle the case of systemd-boot booting a unified kernel image,
* which is a PE executable that contains the bzImage and an initrd as
* COFF sections. The initrd section is placed after the bzImage
* without ensuring that there are at least init_size bytes available
* for the bzImage, and thus the compressed kernel's startup code may
* overwrite the initrd unless it is moved out of the way.
*/ */
buffer_start = ALIGN(bzimage_addr - image_offset, buffer_start = ALIGN(bzimage_addr - image_offset,
...@@ -751,8 +758,7 @@ unsigned long efi_main(efi_handle_t handle, ...@@ -751,8 +758,7 @@ unsigned long efi_main(efi_handle_t handle,
if ((buffer_start < LOAD_PHYSICAL_ADDR) || if ((buffer_start < LOAD_PHYSICAL_ADDR) ||
(IS_ENABLED(CONFIG_X86_32) && buffer_end > KERNEL_IMAGE_SIZE) || (IS_ENABLED(CONFIG_X86_32) && buffer_end > KERNEL_IMAGE_SIZE) ||
(IS_ENABLED(CONFIG_X86_64) && buffer_end > MAXMEM_X86_64_4LEVEL) || (IS_ENABLED(CONFIG_X86_64) && buffer_end > MAXMEM_X86_64_4LEVEL) ||
(image_offset == 0 && !IS_ALIGNED(bzimage_addr, (image_offset == 0)) {
hdr->kernel_alignment))) {
status = efi_relocate_kernel(&bzimage_addr, status = efi_relocate_kernel(&bzimage_addr,
hdr->init_size, hdr->init_size, hdr->init_size, hdr->init_size,
hdr->pref_address, hdr->pref_address,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment