linux-efi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Broken section alignment in 6.7 and 6.8rc EFI stub
@ 2024-02-05  0:08 Mike Beaton
  2024-02-05  2:06 ` Bagas Sanjaya
  0 siblings, 1 reply; 5+ messages in thread
From: Mike Beaton @ 2024-02-05  0:08 UTC (permalink / raw)
  To: linux-efi

Good evening.

Linux kernels from 6.7 upwards (including 6.8rc) appear to have broken
PE section alignment in their EFI stub.

Up to 6.6, we see monotonically increasing and contiguous VMA and LMA,
as  expected for a well-formed PE/COFF file.

In 6.7 and 6.8 these addresses basically jump around all over the place.

At least one loader which is believed to be enforcing strong but
reasonable rules on PE section layout refuses to load these:
https://github.com/acidanthera/bugtracker/issues/2371#issuecomment-1925801292

objdumps of some example kernels (two good, three bad) follow:

$ objdump -h vmlinuz-5.15.0-92-generic

vmlinuz-5.15.0-92-generic:     file format pei-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .setup        00003bc0  0000000001000200  0000000001000200  00000200  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .reloc        00000020  0000000001003dc0  0000000001003dc0  00003dc0  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .compat       00000020  0000000001003de0  0000000001003de0  00003de0  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .text         00b0f4c0  0000000001003e00  0000000001003e00  00003e00  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
$ objdump -h vmlinuz-6.6.11-zabbly+

vmlinuz-6.6.11-zabbly+:     file format pei-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .setup        00003dc0  0000000001000200  0000000001000200  00000200  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .reloc        00000020  0000000001003fc0  0000000001003fc0  00003fc0  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .compat       00000020  0000000001003fe0  0000000001003fe0  00003fe0  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .text         00d6e400  0000000001004000  0000000001004000  00004000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
$ objdump -h vmlinuz-6.7.3-3-liquorix-amd64

vmlinuz-6.7.3-3-liquorix-amd64:     file format pei-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .setup        00003000  0000000000001000  0000000000001000  00001000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .compat       00000008  0000000000c0e000  0000000000c0e000  00004000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .text         00baa000  0000000000005000  0000000000005000  00005000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  3 .data         00001200  0000000000baf000  0000000000baf000  00baf000  2**4
                  CONTENTS, ALLOC, LOAD, DATA
$ objdump -h vmlinuz-6.7.3-zabbly+

vmlinuz-6.7.3-zabbly+:     file format pei-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .setup        00003000  0000000000001000  0000000000001000  00001000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .compat       00000008  0000000000df0000  0000000000df0000  00004000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .text         00d84000  0000000000005000  0000000000005000  00005000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  3 .data         00001200  0000000000d89000  0000000000d89000  00d89000  2**4
                  CONTENTS, ALLOC, LOAD, DATA
$ objdump -h vmlinuz-6.8.0-0.rc3.225.vanilla.fc39.x86_64

vmlinuz-6.8.0-0.rc3.225.vanilla.fc39.x86_64:     file format pei-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .setup        00003000  0000000000001000  0000000000001000  00001000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .compat       00000008  0000000000e8b000  0000000000e8b000  00004000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .text         00e1f000  0000000000005000  0000000000005000  00005000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  3 .data         00001200  0000000000e24000  0000000000e24000  00e24000  2**4
                  CONTENTS, ALLOC, LOAD, DATA
$

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Broken section alignment in 6.7 and 6.8rc EFI stub
  2024-02-05  0:08 Broken section alignment in 6.7 and 6.8rc EFI stub Mike Beaton
@ 2024-02-05  2:06 ` Bagas Sanjaya
  2024-02-05  7:36   ` Mike Beaton
  0 siblings, 1 reply; 5+ messages in thread
From: Bagas Sanjaya @ 2024-02-05  2:06 UTC (permalink / raw)
  To: Mike Beaton, Linux EFI, Linux Kernel Mailing List
  Cc: Ard Biesheuvel, Ivan Hu, Jeremy Kerr, Peter Jones

[-- Attachment #1: Type: text/plain, Size: 4660 bytes --]

On Mon, Feb 05, 2024 at 12:08:00AM +0000, Mike Beaton wrote:
> Good evening.
> 
> Linux kernels from 6.7 upwards (including 6.8rc) appear to have broken
> PE section alignment in their EFI stub.
> 
> Up to 6.6, we see monotonically increasing and contiguous VMA and LMA,
> as  expected for a well-formed PE/COFF file.
> 
> In 6.7 and 6.8 these addresses basically jump around all over the place.
> 
> At least one loader which is believed to be enforcing strong but
> reasonable rules on PE section layout refuses to load these:
> https://github.com/acidanthera/bugtracker/issues/2371#issuecomment-1925801292
> 
> objdumps of some example kernels (two good, three bad) follow:
> 
> $ objdump -h vmlinuz-5.15.0-92-generic
> 
> vmlinuz-5.15.0-92-generic:     file format pei-x86-64
> 
> Sections:
> Idx Name          Size      VMA               LMA               File off  Algn
>   0 .setup        00003bc0  0000000001000200  0000000001000200  00000200  2**4
>                   CONTENTS, ALLOC, LOAD, READONLY, CODE
>   1 .reloc        00000020  0000000001003dc0  0000000001003dc0  00003dc0  2**0
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>   2 .compat       00000020  0000000001003de0  0000000001003de0  00003de0  2**0
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>   3 .text         00b0f4c0  0000000001003e00  0000000001003e00  00003e00  2**4
>                   CONTENTS, ALLOC, LOAD, READONLY, CODE
> $ objdump -h vmlinuz-6.6.11-zabbly+
> 
> vmlinuz-6.6.11-zabbly+:     file format pei-x86-64
> 
> Sections:
> Idx Name          Size      VMA               LMA               File off  Algn
>   0 .setup        00003dc0  0000000001000200  0000000001000200  00000200  2**4
>                   CONTENTS, ALLOC, LOAD, READONLY, CODE
>   1 .reloc        00000020  0000000001003fc0  0000000001003fc0  00003fc0  2**0
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>   2 .compat       00000020  0000000001003fe0  0000000001003fe0  00003fe0  2**0
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>   3 .text         00d6e400  0000000001004000  0000000001004000  00004000  2**4
>                   CONTENTS, ALLOC, LOAD, READONLY, CODE
> $ objdump -h vmlinuz-6.7.3-3-liquorix-amd64
> 
> vmlinuz-6.7.3-3-liquorix-amd64:     file format pei-x86-64
> 
> Sections:
> Idx Name          Size      VMA               LMA               File off  Algn
>   0 .setup        00003000  0000000000001000  0000000000001000  00001000  2**2
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>   1 .compat       00000008  0000000000c0e000  0000000000c0e000  00004000  2**2
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>   2 .text         00baa000  0000000000005000  0000000000005000  00005000  2**4
>                   CONTENTS, ALLOC, LOAD, READONLY, CODE
>   3 .data         00001200  0000000000baf000  0000000000baf000  00baf000  2**4
>                   CONTENTS, ALLOC, LOAD, DATA
> $ objdump -h vmlinuz-6.7.3-zabbly+
> 
> vmlinuz-6.7.3-zabbly+:     file format pei-x86-64
> 
> Sections:
> Idx Name          Size      VMA               LMA               File off  Algn
>   0 .setup        00003000  0000000000001000  0000000000001000  00001000  2**2
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>   1 .compat       00000008  0000000000df0000  0000000000df0000  00004000  2**2
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>   2 .text         00d84000  0000000000005000  0000000000005000  00005000  2**4
>                   CONTENTS, ALLOC, LOAD, READONLY, CODE
>   3 .data         00001200  0000000000d89000  0000000000d89000  00d89000  2**4
>                   CONTENTS, ALLOC, LOAD, DATA
> $ objdump -h vmlinuz-6.8.0-0.rc3.225.vanilla.fc39.x86_64
> 
> vmlinuz-6.8.0-0.rc3.225.vanilla.fc39.x86_64:     file format pei-x86-64
> 
> Sections:
> Idx Name          Size      VMA               LMA               File off  Algn
>   0 .setup        00003000  0000000000001000  0000000000001000  00001000  2**2
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>   1 .compat       00000008  0000000000e8b000  0000000000e8b000  00004000  2**2
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>   2 .text         00e1f000  0000000000005000  0000000000005000  00005000  2**4
>                   CONTENTS, ALLOC, LOAD, READONLY, CODE
>   3 .data         00001200  0000000000e24000  0000000000e24000  00e24000  2**4
>                   CONTENTS, ALLOC, LOAD, DATA
> $

So v6.7 onwards misses .reloc section, right?

Confused...

-- 
An old man doll... just what I always wanted! - Clara

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Broken section alignment in 6.7 and 6.8rc EFI stub
  2024-02-05  2:06 ` Bagas Sanjaya
@ 2024-02-05  7:36   ` Mike Beaton
  2024-02-05  7:47     ` Ard Biesheuvel
  0 siblings, 1 reply; 5+ messages in thread
From: Mike Beaton @ 2024-02-05  7:36 UTC (permalink / raw)
  To: Bagas Sanjaya
  Cc: Linux EFI, Linux Kernel Mailing List, Ard Biesheuvel, Ivan Hu,
	Jeremy Kerr, Peter Jones

On Mon, 5 Feb 2024 at 02:06, Bagas Sanjaya <bagasdotme@gmail.com> wrote:
>
> So v6.7 onwards misses .reloc section, right?
>
> Confused...

Reloc info is still present as normal in data directories, e.g.
`llvm-objdump -p` shows NumberOfRvaAndSizes = 6. Reloc info is taken
from index 5 https://github.com/tianocore/edk2/blob/master/MdePkg/Include/IndustryStandard/PeImage.h#L128
. (I've been told a dummy .reloc section was dumped recently?)

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Broken section alignment in 6.7 and 6.8rc EFI stub
  2024-02-05  7:36   ` Mike Beaton
@ 2024-02-05  7:47     ` Ard Biesheuvel
  2024-02-05  7:59       ` Ard Biesheuvel
  0 siblings, 1 reply; 5+ messages in thread
From: Ard Biesheuvel @ 2024-02-05  7:47 UTC (permalink / raw)
  To: Mike Beaton
  Cc: Bagas Sanjaya, Linux EFI, Linux Kernel Mailing List, Ivan Hu,
	Jeremy Kerr, Peter Jones

On Mon, 5 Feb 2024 at 08:37, Mike Beaton <mjsbeaton@gmail.com> wrote:
>
> On Mon, 5 Feb 2024 at 02:06, Bagas Sanjaya <bagasdotme@gmail.com> wrote:
> >
> > So v6.7 onwards misses .reloc section, right?
> >
> > Confused...
>
> Reloc info is still present as normal in data directories, e.g.
> `llvm-objdump -p` shows NumberOfRvaAndSizes = 6. Reloc info is taken
> from index 5 https://github.com/tianocore/edk2/blob/master/MdePkg/Include/IndustryStandard/PeImage.h#L128
> . (I've been told a dummy .reloc section was dumped recently?)
>

So there are a couple of things going on here:
- the .reloc section was indeed dropped because we could not find any
evidence anywhere that the reason it was added is still valid;
- the .compat section uses a non-1:1 RVA mapping, to avoid padding,
but reading the PE/COFF spec again, I suppose this is not compliant.

Note that objdump looks broken too, on an image I have locally, I get

(llvm-readelf -a)

  Section {
    Number: 2
    Name: .compat (2E 63 6F 6D 70 61 74 00)
    VirtualSize: 0x8
    VirtualAddress: 0xB82000
    RawDataSize: 4096
    PointerToRawData: 0x4000

(objdump -h)

  1 .compat       00000008  0000000000b82000  0000000000b82000  00004000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

So the .compat section is in the correct spot in the file view but not
in the memory view.

Given that the .setup section is not relevant to EFI boot anyway, we
could try to use the same file mapping as the virtual mapping, and
just split the content preceding .text across the .setup and .compat
sections arbitrarily.

Could you try the below?


diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index b2771710ed98..f8b48ff86dd9 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -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
@@ -157,7 +156,7 @@ section_table:
        .asciz  ".compat"

        .long   8                               # VirtualSize
-       .long   setup_size + ZO__end            # VirtualAddress
+       .long   pecompat_fstart                 # VirtualAddress
        .long   pecompat_fsize                  # SizeOfRawData
        .long   pecompat_fstart                 # PointerToRawData

@@ -173,7 +172,6 @@ section_table:
         */
        .pushsection ".pecompat", "a", @progbits
        .balign falign
-       .set    pecompat_vsize, salign
        .globl  pecompat_fstart
 pecompat_fstart:
        .byte   0x1                             # Version
@@ -182,7 +180,6 @@ pecompat_fstart:
        .long   setup_size + ZO_efi32_pe_entry  # Entrypoint
        .popsection
 #else
-       .set    pecompat_vsize, 0
        .set    pecompat_fstart, setup_size
 #endif
        .ascii  ".text"

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: Broken section alignment in 6.7 and 6.8rc EFI stub
  2024-02-05  7:47     ` Ard Biesheuvel
@ 2024-02-05  7:59       ` Ard Biesheuvel
  0 siblings, 0 replies; 5+ messages in thread
From: Ard Biesheuvel @ 2024-02-05  7:59 UTC (permalink / raw)
  To: Mike Beaton
  Cc: Bagas Sanjaya, Linux EFI, Linux Kernel Mailing List, Ivan Hu,
	Jeremy Kerr, Peter Jones

On Mon, 5 Feb 2024 at 08:47, Ard Biesheuvel <ardb@kernel.org> wrote:
>
> On Mon, 5 Feb 2024 at 08:37, Mike Beaton <mjsbeaton@gmail.com> wrote:
> >
> > On Mon, 5 Feb 2024 at 02:06, Bagas Sanjaya <bagasdotme@gmail.com> wrote:
> > >
> > > So v6.7 onwards misses .reloc section, right?
> > >
> > > Confused...
> >
> > Reloc info is still present as normal in data directories, e.g.
> > `llvm-objdump -p` shows NumberOfRvaAndSizes = 6. Reloc info is taken
> > from index 5 https://github.com/tianocore/edk2/blob/master/MdePkg/Include/IndustryStandard/PeImage.h#L128
> > . (I've been told a dummy .reloc section was dumped recently?)
> >
>
> So there are a couple of things going on here:
> - the .reloc section was indeed dropped because we could not find any
> evidence anywhere that the reason it was added is still valid;
> - the .compat section uses a non-1:1 RVA mapping, to avoid padding,
> but reading the PE/COFF spec again, I suppose this is not compliant.
>
> Note that objdump looks broken too, on an image I have locally, I get
>
> (llvm-readelf -a)
>
>   Section {
>     Number: 2
>     Name: .compat (2E 63 6F 6D 70 61 74 00)
>     VirtualSize: 0x8
>     VirtualAddress: 0xB82000
>     RawDataSize: 4096
>     PointerToRawData: 0x4000
>
> (objdump -h)
>
>   1 .compat       00000008  0000000000b82000  0000000000b82000  00004000  2**2
>                   CONTENTS, ALLOC, LOAD, READONLY, DATA
>
> So the .compat section is in the correct spot in the file view but not
> in the memory view.
>
> Given that the .setup section is not relevant to EFI boot anyway, we
> could try to use the same file mapping as the virtual mapping, and
> just split the content preceding .text across the .setup and .compat
> sections arbitrarily.
>
> Could you try the below?
>

OK, never mind - that violates the section alignment.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-02-05  7:59 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-05  0:08 Broken section alignment in 6.7 and 6.8rc EFI stub Mike Beaton
2024-02-05  2:06 ` Bagas Sanjaya
2024-02-05  7:36   ` Mike Beaton
2024-02-05  7:47     ` Ard Biesheuvel
2024-02-05  7:59       ` Ard Biesheuvel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).