rust-hypervisor-firmware
rust-hypervisor-firmware copied to clipboard
unable to load EFI binaries with ImageBase != 0
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
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.