linux-hardening.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ardb@kernel.org>
To: Evgeniy Baskov <baskov@ispras.ru>
Cc: Borislav Petkov <bp@alien8.de>, Andy Lutomirski <luto@kernel.org>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Ingo Molnar <mingo@redhat.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Alexey Khoroshilov <khoroshilov@ispras.ru>,
	lvc-project@linuxtesting.org, x86@kernel.org,
	linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-hardening@vger.kernel.org
Subject: Re: [PATCH 09/16] efi/libstub: Move helper function to related file
Date: Wed, 19 Oct 2022 09:21:15 +0200	[thread overview]
Message-ID: <CAMj1kXFE1cZK5U-Q++_uG5hF4DwoSCxrsiaU2inbZ6-nW_hVxA@mail.gmail.com> (raw)
In-Reply-To: <a1c01892bad6e4f05da96380b63ff14a82842d27.1662459668.git.baskov@ispras.ru>

On Tue, 6 Sept 2022 at 12:42, Evgeniy Baskov <baskov@ispras.ru> wrote:
>
> efi_adjust_memory_range_protection() can be useful outside x86-stub.c.
>
> Move it to mem.c, where memory related code resides and make it
> non-static.
>
> Change its behavior to setup exact attibutes and disallow making memory
> regions readable and writable simultaniosly for supported
> configurations.
>
> Signed-off-by: Evgeniy Baskov <baskov@ispras.ru>

Acked-by: Ard Biesheuvel <ardb@kernel.org>

> ---
>  drivers/firmware/efi/libstub/efistub.h  |   4 +
>  drivers/firmware/efi/libstub/mem.c      | 101 ++++++++++++++++++++++++
>  drivers/firmware/efi/libstub/x86-stub.c |  67 ++--------------
>  3 files changed, 111 insertions(+), 61 deletions(-)
>
> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> index b0ae0a454404..22fe28385db7 100644
> --- a/drivers/firmware/efi/libstub/efistub.h
> +++ b/drivers/firmware/efi/libstub/efistub.h
> @@ -907,6 +907,10 @@ efi_status_t efi_relocate_kernel(unsigned long *image_addr,
>                                  unsigned long alignment,
>                                  unsigned long min_addr);
>
> +efi_status_t efi_adjust_memory_range_protection(unsigned long start,
> +                                               unsigned long size,
> +                                               unsigned long attributes);
> +
>  efi_status_t efi_parse_options(char const *cmdline);
>
>  void efi_parse_option_graphics(char *option);
> diff --git a/drivers/firmware/efi/libstub/mem.c b/drivers/firmware/efi/libstub/mem.c
> index feef8d4be113..89ebc8ad2c22 100644
> --- a/drivers/firmware/efi/libstub/mem.c
> +++ b/drivers/firmware/efi/libstub/mem.c
> @@ -130,3 +130,104 @@ void efi_free(unsigned long size, unsigned long addr)
>         nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
>         efi_bs_call(free_pages, addr, nr_pages);
>  }
> +
> +/**
> + * efi_adjust_memory_range_protection() - change memory range protection attributes
> + * @start:     memory range start address
> + * @size:      memory range size
> + *
> + * Actual memory range for which memory attributes are modified is
> + * the smallest ranged with start address and size aligned to EFI_PAGE_SIZE
> + * that includes [start, start + size].
> + *
> + * @return: status code
> + */
> +efi_status_t efi_adjust_memory_range_protection(unsigned long start,
> +                                               unsigned long size,
> +                                               unsigned long attributes)
> +{
> +       efi_status_t status;
> +       efi_gcd_memory_space_desc_t desc;
> +       efi_physical_addr_t end, next;
> +       efi_physical_addr_t rounded_start, rounded_end;
> +       efi_physical_addr_t unprotect_start, unprotect_size;
> +       int has_system_memory = 0;
> +
> +       if (efi_dxe_table == NULL)
> +               return EFI_UNSUPPORTED;
> +
> +       /*
> +        * This function should not be used to modify attributes
> +        * other than writable/executable.
> +        */
> +
> +       if ((attributes & ~(EFI_MEMORY_RO | EFI_MEMORY_XP)) != 0)
> +               return EFI_INVALID_PARAMETER;
> +
> +       /*
> +        * Disallow simultaniously executable and writable memory
> +        * to inforce W^X policy if direct extraction code is enabled.
> +        */
> +
> +       if ((attributes & (EFI_MEMORY_RO | EFI_MEMORY_XP)) == 0 &&
> +           IS_ENABLED(CONFIG_EFI_STUB_EXTRACT_DIRECT))
> +               return EFI_INVALID_PARAMETER;
> +
> +       rounded_start = rounddown(start, EFI_PAGE_SIZE);
> +       rounded_end = roundup(start + size, EFI_PAGE_SIZE);
> +
> +       /*
> +        * Don't modify memory region attributes, they are
> +        * already suitable, to lower the possibility to
> +        * encounter firmware bugs.
> +        */
> +
> +       for (end = start + size; start < end; start = next) {
> +
> +               status = efi_dxe_call(get_memory_space_descriptor,
> +                                     start, &desc);
> +
> +               if (status != EFI_SUCCESS) {
> +                       efi_warn("Unable to get memory descriptor at %lx\n",
> +                                start);
> +                       return status;
> +               }
> +
> +               next = desc.base_address + desc.length;
> +
> +               /*
> +                * Only system memory is suitable for trampoline/kernel image
> +                * placement, so only this type of memory needs its attributes
> +                * to be modified.
> +                */
> +
> +               if (desc.gcd_memory_type != EfiGcdMemoryTypeSystemMemory) {
> +                       efi_warn("Attempted to change protection of special memory range\n");
> +                       return EFI_UNSUPPORTED;
> +               }
> +
> +               if (((desc.attributes ^ attributes) &
> +                    (EFI_MEMORY_RO | EFI_MEMORY_XP)) == 0)
> +                       continue;
> +
> +               desc.attributes &= ~(EFI_MEMORY_RO | EFI_MEMORY_XP);
> +               desc.attributes |= attributes;
> +
> +               unprotect_start = max(rounded_start, desc.base_address);
> +               unprotect_size = min(rounded_end, next) - unprotect_start;
> +
> +               status = efi_dxe_call(set_memory_space_attributes,
> +                                     unprotect_start, unprotect_size,
> +                                     desc.attributes);
> +
> +               if (status != EFI_SUCCESS) {
> +                       efi_warn("Unable to unprotect memory range [%08lx,%08lx]: %lx\n",
> +                                (unsigned long)unprotect_start,
> +                                (unsigned long)(unprotect_start + unprotect_size),
> +                                status);
> +                       return status;
> +               }
> +       }
> +
> +       return EFI_SUCCESS;
> +}
> diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
> index 05ae8bcc9d67..678f9c2ccafc 100644
> --- a/drivers/firmware/efi/libstub/x86-stub.c
> +++ b/drivers/firmware/efi/libstub/x86-stub.c
> @@ -212,62 +212,6 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
>         }
>  }
>
> -static void
> -adjust_memory_range_protection(unsigned long start, unsigned long size)
> -{
> -       efi_status_t status;
> -       efi_gcd_memory_space_desc_t desc;
> -       unsigned long end, next;
> -       unsigned long rounded_start, rounded_end;
> -       unsigned long unprotect_start, unprotect_size;
> -       int has_system_memory = 0;
> -
> -       if (efi_dxe_table == NULL)
> -               return;
> -
> -       rounded_start = rounddown(start, EFI_PAGE_SIZE);
> -       rounded_end = roundup(start + size, EFI_PAGE_SIZE);
> -
> -       /*
> -        * Don't modify memory region attributes, they are
> -        * already suitable, to lower the possibility to
> -        * encounter firmware bugs.
> -        */
> -
> -       for (end = start + size; start < end; start = next) {
> -
> -               status = efi_dxe_call(get_memory_space_descriptor, start, &desc);
> -
> -               if (status != EFI_SUCCESS)
> -                       return;
> -
> -               next = desc.base_address + desc.length;
> -
> -               /*
> -                * Only system memory is suitable for trampoline/kernel image placement,
> -                * so only this type of memory needs its attributes to be modified.
> -                */
> -
> -               if (desc.gcd_memory_type != EfiGcdMemoryTypeSystemMemory ||
> -                   (desc.attributes & (EFI_MEMORY_RO | EFI_MEMORY_XP)) == 0)
> -                       continue;
> -
> -               unprotect_start = max(rounded_start, (unsigned long)desc.base_address);
> -               unprotect_size = min(rounded_end, next) - unprotect_start;
> -
> -               status = efi_dxe_call(set_memory_space_attributes,
> -                                     unprotect_start, unprotect_size,
> -                                     EFI_MEMORY_WB);
> -
> -               if (status != EFI_SUCCESS) {
> -                       efi_warn("Unable to unprotect memory range [%08lx,%08lx]: %lx\n",
> -                                unprotect_start,
> -                                unprotect_start + unprotect_size,
> -                                status);
> -               }
> -       }
> -}
> -
>  /*
>   * Trampoline takes 2 pages and can be loaded in first megabyte of memory
>   * with its end placed between 128k and 640k where BIOS might start.
> @@ -291,12 +235,12 @@ setup_memory_protection(unsigned long image_base, unsigned long image_size)
>          * and relocated kernel image.
>          */
>
> -       adjust_memory_range_protection(TRAMPOLINE_PLACEMENT_BASE,
> -                                      TRAMPOLINE_PLACEMENT_SIZE);
> +       efi_adjust_memory_range_protection(TRAMPOLINE_PLACEMENT_BASE,
> +                                          TRAMPOLINE_PLACEMENT_SIZE, 0);
>
>  #ifdef CONFIG_64BIT
>         if (image_base != (unsigned long)startup_32)
> -               adjust_memory_range_protection(image_base, image_size);
> +               efi_adjust_memory_range_protection(image_base, image_size, 0);
>  #else
>         /*
>          * Clear protection flags on a whole range of possible
> @@ -306,8 +250,9 @@ setup_memory_protection(unsigned long image_base, unsigned long image_size)
>          * need to remove possible protection on relocated image
>          * itself disregarding further relocations.
>          */
> -       adjust_memory_range_protection(LOAD_PHYSICAL_ADDR,
> -                                      KERNEL_IMAGE_SIZE - LOAD_PHYSICAL_ADDR);
> +       efi_adjust_memory_range_protection(LOAD_PHYSICAL_ADDR,
> +                                          KERNEL_IMAGE_SIZE - LOAD_PHYSICAL_ADDR,
> +                                          0);
>  #endif
>  }
>
> --
> 2.35.1
>

  reply	other threads:[~2022-10-19  7:21 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-06 10:41 [PATCH 00/16] x86_64: Improvements at compressed kernel stage Evgeniy Baskov
2022-09-06 10:41 ` [PATCH 01/16] x86/boot: Align vmlinuz sections on page size Evgeniy Baskov
2022-10-19  7:01   ` Ard Biesheuvel
2022-10-20 11:13     ` Evgeniy Baskov
2022-09-06 10:41 ` [PATCH 02/16] x86/build: Remove RWX sections and align on 4KB Evgeniy Baskov
2022-10-19  7:04   ` Ard Biesheuvel
2022-10-20 11:15     ` Evgeniy Baskov
2022-09-06 10:41 ` [PATCH 03/16] x86/boot: Set cr0 to known state in trampoline Evgeniy Baskov
2022-10-19  7:06   ` Ard Biesheuvel
2022-10-20 11:23     ` Evgeniy Baskov
2022-10-19  7:44   ` Andrew Cooper
2022-10-20 13:25     ` Evgeniy Baskov
2022-09-06 10:41 ` [PATCH 04/16] x86/boot: Increase boot page table size Evgeniy Baskov
2022-10-19  7:08   ` Ard Biesheuvel
2022-10-20 11:29     ` Evgeniy Baskov
2022-09-06 10:41 ` [PATCH 05/16] x86/boot: Support 4KB pages for identity mapping Evgeniy Baskov
2022-10-19  7:11   ` Ard Biesheuvel
2022-10-20 11:30     ` Evgeniy Baskov
2022-09-06 10:41 ` [PATCH 06/16] x86/boot: Setup memory protection for bzImage code Evgeniy Baskov
2022-10-19  7:17   ` Ard Biesheuvel
2022-10-20 12:07     ` Evgeniy Baskov
2022-10-19  7:57   ` Andrew Cooper
2022-10-20 13:30     ` Evgeniy Baskov
2022-10-20 16:51       ` Andrew Cooper
2022-09-06 10:41 ` [PATCH 07/16] x86/boot: Map memory explicitly Evgeniy Baskov
2022-09-06 10:41 ` [PATCH 08/16] x86/boot: Remove mapping from page fault handler Evgeniy Baskov
2022-10-19  7:20   ` Ard Biesheuvel
2022-09-06 10:41 ` [PATCH 09/16] efi/libstub: Move helper function to related file Evgeniy Baskov
2022-10-19  7:21   ` Ard Biesheuvel [this message]
2022-09-06 10:41 ` [PATCH 10/16] x86/boot: Make console interface more abstract Evgeniy Baskov
2022-10-19  7:23   ` Ard Biesheuvel
2022-10-20 12:10     ` Evgeniy Baskov
2022-09-06 10:41 ` [PATCH 11/16] x86/boot: Split trampoline and pt init code Evgeniy Baskov
2022-09-06 10:41 ` [PATCH 12/16] x86/boot: Add EFI kernel extraction interface Evgeniy Baskov
2022-10-19  7:27   ` Ard Biesheuvel
2022-10-20 12:14     ` Evgeniy Baskov
2022-09-06 10:41 ` [PATCH 13/16] efi/x86: Support extracting kernel from libstub Evgeniy Baskov
2022-10-19  7:35   ` Ard Biesheuvel
2022-10-20 12:36     ` Evgeniy Baskov
2022-09-06 10:41 ` [PATCH 14/16] x86/build: Make generated PE more spec compliant Evgeniy Baskov
2022-10-19  7:39   ` Ard Biesheuvel
2022-10-20 13:07     ` Evgeniy Baskov
2022-09-06 10:41 ` [PATCH 15/16] efi/libstub: Add memory attribute protocol definitions Evgeniy Baskov
2022-10-19  7:39   ` Ard Biesheuvel
2022-09-06 10:41 ` [PATCH 16/16] efi/libstub: Use memory attribute protocol Evgeniy Baskov
2022-10-18 20:51   ` [PATCH] efi/libstub: make memory protection warnings include newlines Peter Jones
2022-10-19  7:44     ` Ard Biesheuvel
2022-10-19  7:42   ` [PATCH 16/16] efi/libstub: Use memory attribute protocol Ard Biesheuvel
2022-10-20 13:13     ` Evgeniy Baskov
2022-10-18 21:04 ` [PATCH 00/16] x86_64: Improvements at compressed kernel stage Peter Jones
2022-10-20 11:05   ` Evgeniy Baskov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAMj1kXFE1cZK5U-Q++_uG5hF4DwoSCxrsiaU2inbZ6-nW_hVxA@mail.gmail.com \
    --to=ardb@kernel.org \
    --cc=baskov@ispras.ru \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=khoroshilov@ispras.ru \
    --cc=linux-efi@vger.kernel.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=lvc-project@linuxtesting.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).