:p
atchew
Login
These patches improve support for Secure boot. UEFI CA memory mitigation requires memory pages to be not executable and writable at the same time. So changing permissions and splitting some section is required. Remove multiboot pieces from EFI executable. Changes since v1: - improved some comments; - merged 2 pacthes removing multiboot support in x86 PE; - removed a patch dealing with SBAT; - other minor changes (see single patches). Frediano Ziglio (2): Align some sections to 4KB x86: Split .init section to satisfy UEFI CA memory mitigation Roger Pau Monné (2): x86/efi: discard multiboot support for PE binary x86/efi: avoid a relocation in efi_arch_post_exit_boot() docs/hypervisor-guide/x86/how-xen-boots.rst | 6 ------ xen/arch/x86/boot/head.S | 3 ++- xen/arch/x86/efi/efi-boot.h | 7 +++++-- xen/arch/x86/xen.lds.S | 22 +++++++++++---------- 4 files changed, 19 insertions(+), 19 deletions(-) -- 2.43.0
Required by UEFI CA memory mitigation. It is a requirement for NX_COMPAT so the PE can be loaded with W^X perms in the pagetables. NX_COMPAT is a requirement from shim-review, https://github.com/rhboot/shim-review#do-you-have-the-nx-bit-set-in-your-shim-if-so-is-your-entire-boot-stack-nx-compatible-and-what-testing-have-you-done-to-ensure-such-compatibility Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com> -- Changes since v2: - Change subject. --- xen/arch/x86/xen.lds.S | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -XXX,XX +XXX,XX @@ SECTIONS __note_gnu_build_id_end = .; } PHDR(note) PHDR(text) #elif defined(BUILD_ID_EFI) - /* Workaround bug in binutils < 2.36 */ - . = ALIGN(32); + /* Align to satisfy UEFI CA memory mitigation. */ + . = ALIGN(PAGE_SIZE); DECL_SECTION(.buildid) { __note_gnu_build_id_start = .; *(.buildid) @@ -XXX,XX +XXX,XX @@ SECTIONS __2M_rwdata_end = ALIGN(SECTION_ALIGN); #ifdef EFI + . = ALIGN(PAGE_SIZE); .reloc ALIGN(4) : { __base_relocs_start = .; *(.reloc) -- 2.43.0
From: Roger Pau Monné <roger.pau@citrix.com> The multiboot headers (.text.header section) are not consumed in the PE binary, hence discard them in the linker script when doing a PE build. The multiboot and PVH entry points are not used in the PE binary, hence discard them in the linker script when doing a PE build. That removes some relocations that otherwise appear due to the usage of the start and __efi64_mb2_start symbols in the multiboot2 header. Section discarding is not done updating DISCARD_SECTIONS definition as the change is specific for x86. No functional change intended. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com> -- Changes since v1: - improve commit message; - change section orders to avoid changing code order in final executable; - merge 2 commits; - removed deprecated documentation section. --- docs/hypervisor-guide/x86/how-xen-boots.rst | 6 ------ xen/arch/x86/boot/head.S | 3 ++- xen/arch/x86/xen.lds.S | 5 +++++ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/hypervisor-guide/x86/how-xen-boots.rst b/docs/hypervisor-guide/x86/how-xen-boots.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/hypervisor-guide/x86/how-xen-boots.rst +++ b/docs/hypervisor-guide/x86/how-xen-boots.rst @@ -XXX,XX +XXX,XX @@ When a PEI-capable toolchain is found, the objects are linked together and a PE32+ binary is created. It can be run directly from the EFI shell, and has ``efi_start`` as its entry symbol. -.. note:: - - xen.efi does contain all MB1/MB2/PVH tags included in the rest of the - build. However, entry via anything other than the EFI64 protocol is - unsupported, and won't work. - Boot ---- diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -XXX,XX +XXX,XX @@ vga_text_buffer: efi_platform: .byte 0 - .section .init.text, "ax", @progbits + .section .init.multiboot, "ax", @progbits early_error: /* Here to improve the disassembly. */ @@ -XXX,XX +XXX,XX @@ trampoline_setup: /* Jump into the relocated trampoline. */ lret + .section .init.text, "ax", @progbits ENTRY(trampoline_start) #include "trampoline.S" ENTRY(trampoline_end) diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -XXX,XX +XXX,XX @@ SECTIONS __image_base__ = .; #else . = __image_base__; + /DISCARD/ : { + *(.text.header) + *(.init.multiboot) + } #endif #if 0 @@ -XXX,XX +XXX,XX @@ SECTIONS DECL_SECTION(.init.text) { #endif _sinittext = .; + *(.init.multiboot) *(.init.text) *(.text.startup) _einittext = .; -- 2.43.0
From: Roger Pau Monné <roger.pau@citrix.com> Instead of using the absolute __start_xen address, calculate it as an offset from the current instruction pointer. The relocation would be problematic if the generated PE binary had .init.text as a standalone section with just read and execute permissions." Removing this relocation is necessary to make it safe to split .init. No functional change intended. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com> -- Changes since v2: - Improve commit message. --- xen/arch/x86/efi/efi-boot.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/efi/efi-boot.h +++ b/xen/arch/x86/efi/efi-boot.h @@ -XXX,XX +XXX,XX @@ static void __init noreturn efi_arch_post_exit_boot(void) /* Jump to higher mappings. */ "mov stack_start(%%rip), %%rsp\n\t" - "movabs $__start_xen, %[rip]\n\t" + "lea __start_xen(%%rip), %[rip]\n\t" + "add %[offset], %[rip]\n\t" + "push %[cs]\n\t" "push %[rip]\n\t" "lretq" @@ -XXX,XX +XXX,XX @@ static void __init noreturn efi_arch_post_exit_boot(void) [cr4] "+&r" (cr4) : [cr3] "r" (idle_pg_table), [cs] "i" (__HYPERVISOR_CS), - [ds] "r" (__HYPERVISOR_DS) + [ds] "r" (__HYPERVISOR_DS), + [offset] "r" (__XEN_VIRT_START - xen_phys_start) : "memory" ); unreachable(); } -- 2.43.0
Currently .init section is both writeable and executable, split data and code to have 2 sections satisfying W^X rule. It is a requirement for NX_COMPAT so the PE can be loaded with W^X perms in the pagetables. NX_COMPAT is a requirement from shim-review, https://github.com/rhboot/shim-review#do-you-have-the-nx-bit-set-in-your-shim-if-so-is-your-entire-boot-stack-nx-compatible-and-what-testing-have-you-done-to-ensure-such-compatibility Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com> -- Change since v2: - update comment style. --- xen/arch/x86/xen.lds.S | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -XXX,XX +XXX,XX @@ SECTIONS __2M_init_start = .; /* Start of 2M superpages, mapped RWX (boot only). */ . = ALIGN(PAGE_SIZE); /* Init code and data */ __init_begin = .; -#ifdef EFI /* EFI wants to merge all of .init.* ELF doesn't. */ - DECL_SECTION(.init) { -#else DECL_SECTION(.init.text) { -#endif _sinittext = .; *(.init.multiboot) *(.init.text) @@ -XXX,XX +XXX,XX @@ SECTIONS */ *(.altinstr_replacement) -#ifdef EFI /* EFI wants to merge all of .init.* ELF doesn't. */ - . = ALIGN(SMP_CACHE_BYTES); -#else } PHDR(text) - DECL_SECTION(.init.data) { +#ifdef EFI + /* Align to satisfy UEFI CA memory mitigation. */ + . = ALIGN(SECTION_ALIGN); #endif + DECL_SECTION(.init.data) { *(.init.bss.stack_aligned) *(.init.data.page_aligned) -- 2.43.0
These patches improve support for Secure boot. UEFI CA memory mitigation requires memory pages to be not executable and writable at the same time. So changing permissions and splitting some section is required. Remove multiboot pieces from EFI executable. Changes since v1: - improved some comments; - merged 2 pacthes removing multiboot support in x86 PE; - removed a patch dealing with SBAT; - other minor changes (see single patches). Changes since v2: - improved some comments. Changes since v3: - Added Acked-by; - Improve commit message. Changes since v4: - Messages updates; - Clean some dependencies cause by code removal; - Add small commit to remove a possibly unused string. Changes since v5: - removed merged commit; - remove more code/data from xen.efi output. Frediano Ziglio (2): Align relevant sections to 4KB x86: Split .init section to satisfy UEFI CA memory mitigation Roger Pau Monné (2): x86/efi: discard multiboot and PVH support for PE binary x86/efi: avoid a relocation in efi_arch_post_exit_boot() docs/hypervisor-guide/x86/how-xen-boots.rst | 6 ----- xen/arch/x86/boot/head.S | 8 +++---- xen/arch/x86/efi/efi-boot.h | 7 ++++-- xen/arch/x86/xen.lds.S | 25 ++++++++++++--------- xen/tools/combine_two_binaries.py | 2 +- 5 files changed, 25 insertions(+), 23 deletions(-) -- 2.43.0
From: Frediano Ziglio <frediano.ziglio@cloud.com> Required by UEFI CA memory mitigation. It is a requirement for NX_COMPAT so the PE can be loaded with W^X perms in the pagetables. NX_COMPAT is a requirement from shim-review, https://github.com/rhboot/shim-review#do-you-have-the-nx-bit-set-in-your-shim-if-so-is-your-entire-boot-stack-nx-compatible-and-what-testing-have-you-done-to-ensure-such-compatibility Sections with different permissions must be in separate pages. In the case of debug sections they are contiguous and have the same permissions, including the immediately preceding .reloc section, so it's not an issue if they are not aligned to the page. Before the .debug sections you could have the .reloc or the SBAT section, either are permission-compatible. Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com> Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> Acked-by: Jan Beulich <jbeulich@suse.com> --- Changes since v1: - Change subject. Changes since v2: - Improved commit message and subject. Changes since v3: - Added Acked-by; - Improved commit message. Changes since v4: - Added missing comment; - Added Acked-by. --- xen/arch/x86/xen.lds.S | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -XXX,XX +XXX,XX @@ SECTIONS __note_gnu_build_id_end = .; } PHDR(note) PHDR(text) #elif defined(BUILD_ID_EFI) - /* Workaround bug in binutils < 2.36 */ - . = ALIGN(32); + /* Align to satisfy UEFI CA memory mitigation. */ + . = ALIGN(PAGE_SIZE); DECL_SECTION(.buildid) { __note_gnu_build_id_start = .; *(.buildid) @@ -XXX,XX +XXX,XX @@ SECTIONS __2M_rwdata_end = ALIGN(SECTION_ALIGN); #ifdef EFI + /* Align to satisfy UEFI CA memory mitigation. */ + . = ALIGN(PAGE_SIZE); .reloc ALIGN(4) : { __base_relocs_start = .; *(.reloc) -- 2.43.0
From: Roger Pau Monné <roger.pau@citrix.com> Multiboot and PVH booting are not supported for PE, hence discards them in the linker script when doing a PE build. That removes some relocations that otherwise appear due to the usage of the start and __efi64_mb2_start symbols in the multiboot2 header. Section discarding is not done updating DISCARD_SECTIONS definition as the change is specific for x86. No functional change intended. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com> --- Changes since v1: - improve commit message; - change section orders to avoid changing code order in final executable; - merge 2 commits; - removed deprecated documentation section. Changes since v2: - Update commit message, join 2 sentences together. Changes since v3: - Added Acked-by. Changes since v4: - more clear subject; - removed more code/data from EFI output; - removed Acked-by. Changes since v5: - simplify section exclusion using more wildcard; - exclude more multiboot functions. --- docs/hypervisor-guide/x86/how-xen-boots.rst | 6 ------ xen/arch/x86/boot/head.S | 8 ++++---- xen/arch/x86/xen.lds.S | 7 +++++++ xen/tools/combine_two_binaries.py | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/hypervisor-guide/x86/how-xen-boots.rst b/docs/hypervisor-guide/x86/how-xen-boots.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/hypervisor-guide/x86/how-xen-boots.rst +++ b/docs/hypervisor-guide/x86/how-xen-boots.rst @@ -XXX,XX +XXX,XX @@ When a PEI-capable toolchain is found, the objects are linked together and a PE32+ binary is created. It can be run directly from the EFI shell, and has ``efi_start`` as its entry symbol. -.. note:: - - xen.efi does contain all MB1/MB2/PVH tags included in the rest of the - build. However, entry via anything other than the EFI64 protocol is - unsupported, and won't work. - Boot ---- diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -XXX,XX +XXX,XX @@ multiboot2_header: .size multiboot2_header, . - multiboot2_header .type multiboot2_header, @object - .section .init.rodata, "a", @progbits + .section .init.rodata.multiboot, "a", @progbits .Lbad_cpu_msg: .asciz "ERR: Not a 64-bit CPU!" .Lbad_ldr_msg: .asciz "ERR: Not a Multiboot bootloader!" @@ -XXX,XX +XXX,XX @@ multiboot2_header: .Lno_nx_msg: .asciz "ERR: Not an NX-capable CPU!" #endif - .section .init.data, "aw", @progbits - .subsection 1 /* Put data here after the page tables (in x86_64.S). */ + .section .init.data.multiboot, "aw", @progbits .align 4 .word 0 @@ -XXX,XX +XXX,XX @@ vga_text_buffer: efi_platform: .byte 0 - .section .init.text, "ax", @progbits + .section .init.multiboot, "ax", @progbits early_error: /* Here to improve the disassembly. */ @@ -XXX,XX +XXX,XX @@ trampoline_setup: /* Jump into the relocated trampoline. */ lret + .section .init.text, "ax", @progbits ENTRY(trampoline_start) #include "trampoline.S" ENTRY(trampoline_end) diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -XXX,XX +XXX,XX @@ SECTIONS __image_base__ = .; #else . = __image_base__; + /DISCARD/ : { + *(.text.header) + *(.init.*multiboot) + } #endif #if 0 @@ -XXX,XX +XXX,XX @@ SECTIONS DECL_SECTION(.init.text) { #endif _sinittext = .; + *(.init.multiboot) *(.init.text) *(.text.startup) _einittext = .; @@ -XXX,XX +XXX,XX @@ SECTIONS *(.init.rodata.cf_clobber) __initdata_cf_clobber_end = .; + *(.init.rodata.multiboot) *(.init.rodata) *(.init.rodata.*) @@ -XXX,XX +XXX,XX @@ SECTIONS *(.initcall1.init) __initcall_end = .; + *(.init.data.multiboot) *(.init.data) *(.init.data.rel) *(.init.data.rel.*) diff --git a/xen/tools/combine_two_binaries.py b/xen/tools/combine_two_binaries.py index XXXXXXX..XXXXXXX 100755 --- a/xen/tools/combine_two_binaries.py +++ b/xen/tools/combine_two_binaries.py @@ -XXX,XX +XXX,XX @@ parser.add_argument('--map', dest='mapfile', parser.add_argument('--exports', dest='exports', help='Symbols to export') parser.add_argument('--section-header', dest='section_header', - default='.section .init.text, "ax", @progbits', + default='.section .init.multiboot, "ax", @progbits', help='Section header declaration') parser.add_argument('-v', '--verbose', action='store_true') -- 2.43.0
From: Roger Pau Monné <roger.pau@citrix.com> Instead of using the absolute __start_xen address, calculate it as an offset from the current instruction pointer. The relocation would be problematic if the generated PE binary had .init.text as a standalone section with just read and execute permissions." Removing this relocation is necessary to make it safe to split .init. No functional change intended. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com> Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> --- Changes since v1: - Improve commit message. Changes since v3: - Added Acked-by. --- xen/arch/x86/efi/efi-boot.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/efi/efi-boot.h +++ b/xen/arch/x86/efi/efi-boot.h @@ -XXX,XX +XXX,XX @@ static void __init noreturn efi_arch_post_exit_boot(void) /* Jump to higher mappings. */ "mov stack_start(%%rip), %%rsp\n\t" - "movabs $__start_xen, %[rip]\n\t" + "lea __start_xen(%%rip), %[rip]\n\t" + "add %[offset], %[rip]\n\t" + "push %[cs]\n\t" "push %[rip]\n\t" "lretq" @@ -XXX,XX +XXX,XX @@ static void __init noreturn efi_arch_post_exit_boot(void) [cr4] "+&r" (cr4) : [cr3] "r" (idle_pg_table), [cs] "i" (__HYPERVISOR_CS), - [ds] "r" (__HYPERVISOR_DS) + [ds] "r" (__HYPERVISOR_DS), + [offset] "r" (__XEN_VIRT_START - xen_phys_start) : "memory" ); unreachable(); } -- 2.43.0
From: Frediano Ziglio <frediano.ziglio@cloud.com> Currently .init section is both writeable and executable, split data and code to have 2 sections satisfying W^X rule. It is a requirement for NX_COMPAT so the PE can be loaded with W^X perms in the pagetables. NX_COMPAT is a requirement from shim-review, https://github.com/rhboot/shim-review#do-you-have-the-nx-bit-set-in-your-shim-if-so-is-your-entire-boot-stack-nx-compatible-and-what-testing-have-you-done-to-ensure-such-compatibility Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com> Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com> Acked-by: Jan Beulich <jbeulich@suse.com> --- Change since v1: - update comment style. Changes since v3: - Added Acked-by. Changes since v4: - Added Acked-by. --- xen/arch/x86/xen.lds.S | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -XXX,XX +XXX,XX @@ SECTIONS __2M_init_start = .; /* Start of 2M superpages, mapped RWX (boot only). */ . = ALIGN(PAGE_SIZE); /* Init code and data */ __init_begin = .; -#ifdef EFI /* EFI wants to merge all of .init.* ELF doesn't. */ - DECL_SECTION(.init) { -#else DECL_SECTION(.init.text) { -#endif _sinittext = .; *(.init.multiboot) *(.init.text) @@ -XXX,XX +XXX,XX @@ SECTIONS */ *(.altinstr_replacement) -#ifdef EFI /* EFI wants to merge all of .init.* ELF doesn't. */ - . = ALIGN(SMP_CACHE_BYTES); -#else } PHDR(text) - DECL_SECTION(.init.data) { +#ifdef EFI + /* Align to satisfy UEFI CA memory mitigation. */ + . = ALIGN(SECTION_ALIGN); #endif + DECL_SECTION(.init.data) { *(.init.bss.stack_aligned) *(.init.data.page_aligned) -- 2.43.0