From: Ana Bobillo <[email protected]>

efi_check_pe() is meant to check that the image holds a 64bit NT header,
which is longer than a 32bit one, as its comment says. Since commit
5dad05a0e61d ("efi_loader: carve out efi_check_pe()") it checks for a
32bit one only, so the callers read the optional header fields and data
directories of a PE32+ image past the end of a truncated image. The
addition of e_lfanew can also wrap around on 32bit systems.

Check for the size of the 64bit NT header again, without wrapping, and
declare the header pointer with that type too.

Fixes: 5dad05a0e61d ("efi_loader: carve out efi_check_pe()")
Signed-off-by: Ana Bobillo <[email protected]>
Reviewed-by: Ilias Apalodimas <[email protected]>
Reviewed-by: Heinrich Schuchardt <[email protected]>
---
 lib/efi_loader/efi_image_loader.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/lib/efi_loader/efi_image_loader.c 
b/lib/efi_loader/efi_image_loader.c
index a03866c2907..c2c3109ad1d 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -835,7 +835,7 @@ static bool efi_image_authenticate(void *efi, size_t 
efi_size)
 efi_status_t efi_check_pe(void *buffer, size_t size, void **nt_header)
 {
        IMAGE_DOS_HEADER *dos = buffer;
-       IMAGE_NT_HEADERS32 *nt;
+       IMAGE_NT_HEADERS64 *nt;
 
        if (size < sizeof(*dos))
                return EFI_INVALID_PARAMETER;
@@ -849,9 +849,10 @@ efi_status_t efi_check_pe(void *buffer, size_t size, void 
**nt_header)
         * least one section header follows we only need to check for the length
         * of the 64bit header which is longer than the 32bit header.
         */
-       if (size < dos->e_lfanew + sizeof(IMAGE_NT_HEADERS32))
+       if (dos->e_lfanew > size ||
+           size - dos->e_lfanew < sizeof(*nt))
                return EFI_INVALID_PARAMETER;
-       nt = (IMAGE_NT_HEADERS32 *)((u8 *)buffer + dos->e_lfanew);
+       nt = (IMAGE_NT_HEADERS64 *)((u8 *)buffer + dos->e_lfanew);
 
        /* Check for PE-COFF magic */
        if (nt->Signature != IMAGE_NT_SIGNATURE)

Reply via email to