]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
x86/efistub: Use 1:1 file:memory mapping for PE/COFF .compat section
authorArd Biesheuvel <ardb@kernel.org>
Mon, 5 Feb 2024 08:11:07 +0000 (09:11 +0100)
committerArd Biesheuvel <ardb@kernel.org>
Mon, 5 Feb 2024 10:24:51 +0000 (10:24 +0000)
The .compat section is a dummy PE section that contains the address of
the 32-bit entrypoint of the 64-bit kernel image if it is bootable from
32-bit firmware (i.e., CONFIG_EFI_MIXED=y)

This section is only 8 bytes in size and is only referenced from the
loader, and so it is placed at the end of the memory view of the image,
to avoid the need for padding it to 4k, which is required for sections
appearing in the middle of the image.

Unfortunately, this violates the PE/COFF spec, and even if most EFI
loaders will work correctly (including the Tianocore reference
implementation), PE loaders do exist that reject such images, on the
basis that both the file and memory views of the file contents should be
described by the section headers in a monotonically increasing manner
without leaving any gaps.

So reorganize the sections to avoid this issue. This results in a slight
padding overhead (< 4k) which can be avoided if desired by disabling
CONFIG_EFI_MIXED (which is only needed in rare cases these days)

Fixes: 3e3eabe26dc8 ("x86/boot: Increase section and file alignment to 4k/512")
Reported-by: Mike Beaton <mjsbeaton@gmail.com>
Link: https://lkml.kernel.org/r/CAHzAAWQ6srV6LVNdmfbJhOwhBw5ZzxxZZ07aHt9oKkfYAdvuQQ%40mail.gmail.com
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
arch/x86/boot/header.S
arch/x86/boot/setup.ld

index b2771710ed989cc805e6310bd88a1743350a9dc5..a1bbedd989e42ed5f9e433f556613613094ae74d 100644 (file)
@@ -106,8 +106,7 @@ extra_header_fields:
        .word   0                               # MinorSubsystemVersion
        .long   0                               # Win32VersionValue
 
-       .long   setup_size + ZO__end + pecompat_vsize
-                                               # SizeOfImage
+       .long   setup_size + ZO__end            # SizeOfImage
 
        .long   salign                          # SizeOfHeaders
        .long   0                               # CheckSum
@@ -143,7 +142,7 @@ section_table:
        .ascii  ".setup"
        .byte   0
        .byte   0
-       .long   setup_size - salign             # VirtualSize
+       .long   pecompat_fstart - salign        # VirtualSize
        .long   salign                          # VirtualAddress
        .long   pecompat_fstart - salign        # SizeOfRawData
        .long   salign                          # PointerToRawData
@@ -156,8 +155,8 @@ section_table:
 #ifdef CONFIG_EFI_MIXED
        .asciz  ".compat"
 
-       .long   8                               # VirtualSize
-       .long   setup_size + ZO__end            # VirtualAddress
+       .long   pecompat_fsize                  # VirtualSize
+       .long   pecompat_fstart                 # VirtualAddress
        .long   pecompat_fsize                  # SizeOfRawData
        .long   pecompat_fstart                 # PointerToRawData
 
@@ -172,17 +171,16 @@ section_table:
         * modes this image supports.
         */
        .pushsection ".pecompat", "a", @progbits
-       .balign falign
-       .set    pecompat_vsize, salign
+       .balign salign
        .globl  pecompat_fstart
 pecompat_fstart:
        .byte   0x1                             # Version
        .byte   8                               # Size
        .word   IMAGE_FILE_MACHINE_I386         # PE machine type
        .long   setup_size + ZO_efi32_pe_entry  # Entrypoint
+       .byte   0x0                             # Sentinel
        .popsection
 #else
-       .set    pecompat_vsize, 0
        .set    pecompat_fstart, setup_size
 #endif
        .ascii  ".text"
index 83bb7efad8ae7139ca66f850d7bb21b4859bd3e0..3a2d1360abb016902495f5879632335d883b8c03 100644 (file)
@@ -24,6 +24,9 @@ SECTIONS
        .text           : { *(.text .text.*) }
        .text32         : { *(.text32) }
 
+       .pecompat       : { *(.pecompat) }
+       PROVIDE(pecompat_fsize = setup_size - pecompat_fstart);
+
        . = ALIGN(16);
        .rodata         : { *(.rodata*) }
 
@@ -36,9 +39,6 @@ SECTIONS
        . = ALIGN(16);
        .data           : { *(.data*) }
 
-       .pecompat       : { *(.pecompat) }
-       PROVIDE(pecompat_fsize = setup_size - pecompat_fstart);
-
        .signature      : {
                setup_sig = .;
                LONG(0x5a5aaa55)