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)