cloud-hypervisor / rust-hypervisor-firmware

Apache License 2.0
588 stars 53 forks source link

unable to load EFI binaries with ImageBase != 0 #341

Open nkraetzschmar opened 1 month ago

nkraetzschmar commented 1 month ago

Trying to load EFI binaries with the ImageBase field in the PE binary fails with errors like

cloud-hypervisor: 61.698026ms: <_disk0_q0> ERROR:virtio-devices/src/thread_helper.rs:55 -- Error running worker: HandleEvent(Failed to process queue (submit): RequestExecuting(GetHostAddress(InvalidGuestAddress(GuestAddress(5603131392)))))

An example of such a binary is any UKI using the systemd boot stub compiled from recent versions of systemd, these set the ImageBase field to a pseudo-random value^1. Forcing this to be opt.ImageBase = 0 allows the stub to be loaded by hypervisor-fw.

objdump of working EFI binary:

src/boot/efi/linuxx64.efi.stub:     file format pei-x86-64
src/boot/efi/linuxx64.efi.stub
architecture: i386:x86-64, flags 0x00000103:
HAS_RELOC, EXEC_P, D_PAGED
start address 0x0000000000009135

Characteristics 0x22e
        executable
        line numbers stripped
        symbols stripped
        large address aware
        debugging information removed

Time/Date               Wed Jul 24 21:45:14 2024
Magic                   020b    (PE32+)
MajorLinkerVersion      0
MinorLinkerVersion      0
SizeOfCode              000000000001a8fe
SizeOfInitializedData   000000000000615e
SizeOfUninitializedData 0000000000000000
AddressOfEntryPoint     0000000000009135
BaseOfCode              0000000000001000
ImageBase               0000000000000000
SectionAlignment        00001000
FileAlignment           00000200
MajorOSystemVersion     0
MinorOSystemVersion     0
MajorImageVersion       257
MinorImageVersion       0
MajorSubsystemVersion   1
MinorSubsystemVersion   1
Win32Version            00000000
SizeOfImage             00026000
SizeOfHeaders           00000400
CheckSum                00000000
Subsystem               0000000a        (EFI application)
DllCharacteristics      00000160
                                        HIGH_ENTROPY_VA
                                        DYNAMIC_BASE
                                        NX_COMPAT
SizeOfStackReserve      0000000000100000
SizeOfStackCommit       0000000000001000
SizeOfHeapReserve       0000000000100000
SizeOfHeapCommit        0000000000001000
LoaderFlags             00000000
NumberOfRvaAndSizes     00000010

objdump of broken EFI binary:

src/boot/efi/linuxx64.efi.stub:     file format pei-x86-64
src/boot/efi/linuxx64.efi.stub
architecture: i386:x86-64, flags 0x00000103:
HAS_RELOC, EXEC_P, D_PAGED
start address 0x000000014df99135

Characteristics 0x22e
        executable
        line numbers stripped
        symbols stripped
        large address aware
        debugging information removed

Time/Date               Wed Jul 24 21:37:09 2024
Magic                   020b    (PE32+)
MajorLinkerVersion      0
MinorLinkerVersion      0
SizeOfCode              000000000001a8fe
SizeOfInitializedData   000000000000615e
SizeOfUninitializedData 0000000000000000
AddressOfEntryPoint     0000000000009135
BaseOfCode              0000000000001000
ImageBase               000000014df90000
SectionAlignment        00001000
FileAlignment           00000200
MajorOSystemVersion     0
MinorOSystemVersion     0
MajorImageVersion       257
MinorImageVersion       0
MajorSubsystemVersion   1
MinorSubsystemVersion   1
Win32Version            00000000
SizeOfImage             00026000
SizeOfHeaders           00000400
CheckSum                00000000
Subsystem               0000000a        (EFI application)
DllCharacteristics      00000160
                                        HIGH_ENTROPY_VA
                                        DYNAMIC_BASE
                                        NX_COMPAT
SizeOfStackReserve      0000000000100000
SizeOfStackCommit       0000000000001000
SizeOfHeapReserve       0000000000100000
SizeOfHeapCommit        0000000000001000
LoaderFlags             00000000
NumberOfRvaAndSizes     00000010
retrage commented 1 month ago

Thank you for reporting the issue. The root cause is that the ImageBase points to unmapped memory address.

By PR #85, the firmware tries to load the PE to the address specified by ImageBase if ImageBase is not zero. (This behavior is to boot Windows) RHF/x86_64 maps the memory on the first 4GB (0x100000000) only, but your PE binary ImageBase is 0x14df90000 which is not mapped memory region.