Re: [PATCH v4 21/26] efi/x86: Explicitly set sections memory attributes
From: Ard Biesheuvel
Date: Fri Mar 10 2023 - 10:33:44 EST
On Thu, 15 Dec 2022 at 13:42, Evgeniy Baskov <baskov@xxxxxxxxx> wrote:
>
> Explicitly change sections memory attributes in efi_pe_entry in case
> of incorrect EFI implementations and to reduce access rights to
> compressed kernel blob. By default it is set executable due to
> restriction in maximum number of sections that can fit before zero
> page.
>
> Tested-by: Peter Jones <pjones@xxxxxxxxxx>
> Signed-off-by: Evgeniy Baskov <baskov@xxxxxxxxx>
I don't think we need this patch. Firmware that cares about W^X will
map the PE image with R-X for text/rodata and RW- for data/bss, which
is sufficient, and firmware that doesn't is a lost cause anyway.
> ---
> drivers/firmware/efi/libstub/x86-stub.c | 54 +++++++++++++++++++++++++
> 1 file changed, 54 insertions(+)
>
> diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
> index 1f0a2e7075c3..60697fcd8950 100644
> --- a/drivers/firmware/efi/libstub/x86-stub.c
> +++ b/drivers/firmware/efi/libstub/x86-stub.c
> @@ -27,6 +27,12 @@ const efi_dxe_services_table_t *efi_dxe_table;
> u32 image_offset __section(".data");
> static efi_loaded_image_t *image __section(".data");
>
> +extern char _head[], _ehead[];
> +extern char _compressed[], _ecompressed[];
> +extern char _text[], _etext[];
> +extern char _rodata[], _erodata[];
> +extern char _data[];
> +
> static efi_status_t
> preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
> {
> @@ -343,6 +349,52 @@ void __noreturn efi_exit(efi_handle_t handle, efi_status_t status)
> asm("hlt");
> }
>
> +
> +/*
> + * Manually setup memory protection attributes for each ELF section
> + * since we cannot do it properly by using PE sections.
> + */
> +static void setup_sections_memory_protection(unsigned long image_base)
> +{
> +#ifdef CONFIG_EFI_DXE_MEM_ATTRIBUTES
> + efi_dxe_table = get_efi_config_table(EFI_DXE_SERVICES_TABLE_GUID);
> +
> + if (!efi_dxe_table ||
> + efi_dxe_table->hdr.signature != EFI_DXE_SERVICES_TABLE_SIGNATURE) {
> + efi_warn("Unable to locate EFI DXE services table\n");
> + efi_dxe_table = NULL;
> + return;
> + }
> +
> + /* .setup [image_base, _head] */
> + efi_adjust_memory_range_protection(image_base,
> + (unsigned long)_head - image_base,
> + EFI_MEMORY_RO | EFI_MEMORY_XP);
> + /* .head.text [_head, _ehead] */
> + efi_adjust_memory_range_protection((unsigned long)_head,
> + (unsigned long)_ehead - (unsigned long)_head,
> + EFI_MEMORY_RO);
> + /* .rodata..compressed [_compressed, _ecompressed] */
> + efi_adjust_memory_range_protection((unsigned long)_compressed,
> + (unsigned long)_ecompressed - (unsigned long)_compressed,
> + EFI_MEMORY_RO | EFI_MEMORY_XP);
> + /* .text [_text, _etext] */
> + efi_adjust_memory_range_protection((unsigned long)_text,
> + (unsigned long)_etext - (unsigned long)_text,
> + EFI_MEMORY_RO);
> + /* .rodata [_rodata, _erodata] */
> + efi_adjust_memory_range_protection((unsigned long)_rodata,
> + (unsigned long)_erodata - (unsigned long)_rodata,
> + EFI_MEMORY_RO | EFI_MEMORY_XP);
> + /* .data, .bss [_data, _end] */
> + efi_adjust_memory_range_protection((unsigned long)_data,
> + (unsigned long)_end - (unsigned long)_data,
> + EFI_MEMORY_XP);
> +#else
> + (void)image_base;
> +#endif
> +}
> +
> void __noreturn efi_stub_entry(efi_handle_t handle,
> efi_system_table_t *sys_table_arg,
> struct boot_params *boot_params);
> @@ -687,6 +739,8 @@ asmlinkage unsigned long efi_main(efi_handle_t handle,
> efi_dxe_table = NULL;
> }
>
> + setup_sections_memory_protection(bzimage_addr - image_offset);
> +
> #ifdef CONFIG_CMDLINE_BOOL
> status = efi_parse_options(CONFIG_CMDLINE);
> if (status != EFI_SUCCESS) {
> --
> 2.37.4
>