On Fri, 30 Oct 2026 at 08:13, Ana Bobillo <[email protected]> wrote:
>
> From: Ana Bobillo <[email protected]>
>
> efi_load_pe() computes the end of each section as the sum of its
> VirtualAddress and its size, both u32, so the sum wraps around before it
> is widened to unsigned long. A section near 4 GiB then yields a small
> virt_size, and the memset() and memcpy() of the section write far past
> the allocated image.
>
> Relative virtual addresses are 32 bit, so reject a section whose end
> does not fit into 32 bits. barebox, whose EFI loader is based on this
> file, fixed the same in b6598389d46d ("efi: loader: fix integer overflow
> in PE virt_size calculation").
>
> This runs before the image is rejected when Secure Boot fails to verify
> it.
>
> Fixes: cb149c66342c ("efi_loader: Add PE image loader")
> Signed-off-by: Ana Bobillo <[email protected]>
> ---

Reviewed-by: Ilias Apalodimas <[email protected]>

>  lib/efi_loader/efi_image_loader.c | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/lib/efi_loader/efi_image_loader.c 
> b/lib/efi_loader/efi_image_loader.c
> index 35cf3cd268f..b15a662e5d6 100644
> --- a/lib/efi_loader/efi_image_loader.c
> +++ b/lib/efi_loader/efi_image_loader.c
> @@ -1062,9 +1062,20 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj 
> *handle,
>         /* Calculate upper virtual address boundary */
>         for (i = num_sections - 1; i >= 0; i--) {
>                 IMAGE_SECTION_HEADER *sec = &sections[i];
> +               u32 end;
>
> -               virt_size = max_t(unsigned long, virt_size,
> -                                 sec->VirtualAddress + section_size(sec));
> +               /*
> +                * Relative virtual addresses are 32 bit. A section whose end
> +                * wraps around would make virt_size too small for the 
> memset()
> +                * and memcpy() below.
> +                */
> +               if (__builtin_add_overflow(sec->VirtualAddress,
> +                                          section_size(sec), &end)) {
> +                       log_err("Section %d virtual address overflow\n", i);
> +                       return EFI_LOAD_ERROR;
> +               }
> +
> +               virt_size = max_t(unsigned long, virt_size, end);
>         }
>
>         /* Read 32/64bit specific header bits */

Reply via email to