Booting Xen via multiboot2 on x86_64 EFI is currently broken in two
independent ways introduced by recent hardening work in the relocator
path. This series fixes both issues.

The first regression comes from commit d72208423dca ("kern/dl: Use
correct segment in grub_dl_set_mem_attrs()"), which now correctly
applies read-only attributes according to ELF section flags to .text
sections of loaded modules. The x86 relocator stubs are, however,
patched in place at runtime. With the new attributes in effect the
runtime patch faults with #PF due to a write to a read-only page.
Patch 1 moves those stubs to a dedicated .text.relocator section flagged
"awx" (writable, executable) so the assembler emits expected ELF section
flags for that usage.

Fail log:
kern/dl.c:grub_dl_set_mem_attrs:684:modules: setting memory attributes for
section 1 at 0x7b3b7000, segement flags 0x6
kern/dl.c:grub_dl_set_mem_attrs:699:modules: set_attrs 0x5, clear_attrs 0x2
kern/dl.c:grub_dl_set_mem_attrs:684:modules: setting memory attributes for
section 3 at 0x7b3be000, segement flags 0x2
kern/dl.c:grub_dl_set_mem_attrs:699:modules: set_attrs 0x4, clear_attrs 0x3
kern/dl.c:grub_dl_set_mem_attrs:684:modules: setting memory attributes for
section 4 at 0x7b3bf000, segement flags 0x3
kern/dl.c:grub_dl_set_mem_attrs:699:modules: set_attrs 0x6, clear_attrs 0x1
kern/dl.c:grub_dl_set_mem_attrs:684:modules: setting memory attributes for
section 5 at 0x7b3c0000, segement flags 0x3
kern/dl.c:grub_dl_set_mem_attrs:699:modules: set_attrs 0x6, clear_attrs 0x1
kern/dl.c:grub_dl_set_mem_attrs:684:modules: setting memory attributes for
section 6 at 0x7b3c1000, segement flags 0x2
kern/dl.c:grub_dl_set_mem_attrs:699:modules: set_attrs 0x4, clear_attrs 0x3
kern/dl.c:grub_dl_flush_cache:606:modules: flushing 0xb000 bytes at 0x7b3b7000
kern/dl.c:grub_dl_load_core_noinit:798:modules: module name: relocator
kern/dl.c:grub_dl_load_core_noinit:799:modules: init function: 0x0

!!!! X64 Exception Type - 0E(#PF - Page-Fault)  CPU Apic ID - 00000000 !!!!
ExceptionData - 0000000000000003  I:0 R:0 U:0 W:1 P:1 PK:0 SS:0 SGX:0
RIP  - 000000007B3BD1C4, CS  - 0000000000000038, RFLAGS - 0000000000210246
RAX  - 0000000036D76289, RCX - 000000007FEC7ED8, RDX - 000000007B3B7BCA
RBX  - 0000000000000000, RSP - 000000007FEC8290, RBP - 000000007FEC82D0
RSI  - 0000000000000048, RDI - 0000000000003000
R8   - 0000000000000000, R9  - 0000000000000020, R10 - 000000007DFC5CB0
R11  - 00000000003E8000, R12 - 000000007E126F98, R13 - 000000007DF0AF20
R14  - 000000007DF0AF28, R15 - 000000007DF0AF30
DS   - 0000000000000030, ES  - 0000000000000030, FS  - 0000000000000030
GS   - 0000000000000030, SS  - 0000000000000030
CR0  - 0000000080010033, CR2 - 000000007B3B7BCA, CR3 - 000000007FC01000
CR4  - 0000000000000668, CR8 - 0000000000000000
DR0  - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
DR3  - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
GDTR - 000000007F9D4000 0000000000000057, LDTR - 0000000000000000
IDTR - 000000007F520018 0000000000000FFF,   TR - 0000000000000048
FXSAVE_STATE - 000000007F9D3460
!!!! Find image based on IP(0x7B3BD1C4) (No PDB)  (ImageBase=0000000078E59000, 
EntryPoint=0000000079EC3A48) !!!!

The second regression comes from commit 6898fcf74d13 ("relocator: Switch
to own page table while moving chunks"), which builds a GRUB-owned page
table covering [0, max_ram_size) and switches CR3 to it before moving
chunks, to avoid clobbering firmware-owned page tables. Unfortunately,
payloads such as Xen continue to access memory above max_ram_size after
the switch, particularly for EFI runtime services and MMIO regions
mapped high by the firmware, and those mappings are absent from GRUB's
preamble page table,which again ends in #PF. Patch 2 generates the
preamble PML4 based on the firmware's PML4 before overwriting entries
for [0, max_ram_size), so high mappings remain reachable across the CR3
switch.

Fail log:
lib/relocator.c:grub_relocator_prepare_relocs:1553:relocator: Relocs allocated
at 0x100000
lib/relocator.c:grub_relocator_prepare_relocs:1566:relocator: chunk
0x3000->0x3000, 0x48
lib/relocator.c:grub_relocator_prepare_relocs:1566:relocator: chunk
0x2000->0x2000, 0x7a2
lib/relocator.c:grub_relocator_prepare_relocs:1566:relocator: chunk
0x27fa000->0x27fa000, 0x26c2226
lib/relocator.c:grub_relocator_prepare_relocs:1566:relocator: chunk
0x1780000->0x1780000, 0x1079988
lib/relocator.c:grub_relocator_prepare_relocs:1566:relocator: chunk
0x1000->0x1000, 0x18
lib/relocator.c:grub_relocator_prepare_relocs:1566:relocator: chunk
0x7da00000->0x7da00000, 0x400000
lib/relocator.c:grub_relocator_prepare_relocs:1613:relocator: sorted chunk
0x1000->0x1000, 0x18
lib/relocator.c:grub_relocator_prepare_relocs:1613:relocator: sorted chunk
0x2000->0x2000, 0x7a2
lib/relocator.c:grub_relocator_prepare_relocs:1613:relocator: sorted chunk
0x3000->0x3000, 0x48
lib/relocator.c:grub_relocator_prepare_relocs:1613:relocator: sorted chunk
0x1780000->0x1780000, 0x1079988
lib/relocator.c:grub_relocator_prepare_relocs:1613:relocator: sorted chunk
0x27fa000->0x27fa000, 0x26c2226
lib/relocator.c:grub_relocator_prepare_relocs:1613:relocator: sorted chunk
0x7da00000->0x7da00000, 0x400000
!!!! X64 Exception Type - 0E(#PF - Page-Fault)  CPU Apic ID - 00000000 !!!!
ExceptionData - 0000000000000002  I:0 R:0 U:0 W:1 P:0 PK:0 SS:0 SGX:0
RIP  - 000000007F517A02, CS  - 0000000000000038, RFLAGS - 0000000000210246
RAX  - 0000000000000000, RCX - 0000000000000001, RDX - 000000007F5186E0
RBX  - 0000387000000402, RSP - 000000007FEC7F90, RBP - 000000007FEC8010
RSI  - 0000000000000000, RDI - 0000000000000001
R8   - 000000007FEC80CC, R9  - 0000387000000402, R10 - 0000000000000000
R11  - 0000000000000000, R12 - 000000007FEC80CC, R13 - 0000000000000001
R14  - 0000000000000000, R15 - 0000000000000001
DS   - 0000000000000030, ES  - 0000000000000030, FS  - 0000000000000030
GS   - 0000000000000030, SS  - 0000000000000030
CR0  - 0000000080010033, CR2 - 0000387000000402, CR3 - 0000000000101000
CR4  - 0000000000000668, CR8 - 0000000000000000
DR0  - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
DR3  - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
GDTR - 000000007F9D4000 0000000000000057, LDTR - 0000000000000000
IDTR - 000000007F520018 0000000000000FFF,   TR - 0000000000000048
FXSAVE_STATE - 000000007F9D3460
!!!! Find image based on IP(0x7F517A02) 
edk2/Build/OvmfX64/DEBUG_GCC/X64/UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe/DEBUG/CpuIo2Dxe.dll
 (ImageBase=000000007F516000, EntryPoint=000000007F517BE3) !!!!

With both patches applied, multiboot2 Xen boot on x86_64 EFI works
again, and the existing low-memory chunk-move protection is preserved.

Jiaqing Zhao (2):
  relocator/x86: place runtime-patched stubs in writable section
  relocator/x86: inherit firmware PML4 in preamble page table

 grub-core/lib/i386/relocator16.S        | 5 ++++-
 grub-core/lib/i386/relocator32.S        | 3 +++
 grub-core/lib/i386/relocator64.S        | 3 +++
 grub-core/lib/i386/relocator_asm.S      | 3 +++
 grub-core/lib/i386/relocator_common_c.c | 8 ++++++++
 grub-core/lib/x86_64/relocator_asm.S    | 3 +++
 6 files changed, 24 insertions(+), 1 deletion(-)

-- 
2.53.0


_______________________________________________
Grub-devel mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to