blob: dd9a0e073d6f3aa0f5a19a5d7d8638efe0e9b331 [file] [log] [blame]
From 5a5147d1e19cf90ec280990c84061ac3f67ea1ab Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Wed, 26 Jul 2023 14:47:45 -0400
Subject: [PATCH] CVE-2023-40551: pe-relocate: Fix bounds check for MZ binaries
In read_header(), we attempt to parse the PE binary headers. In doing
so, if there is an MZ (i.e. MS-DOS) header, we locate the PE header by
finding the offset in that header. Unfortunately that is not correctly
bounds checked, and carefully chosen values can cause an out-of-bounds
ready beyond the end of the loaded binary.
Unfortunately the trivial fix (bounds check that value) also makes it
clear that the way we were determining if an image is loadable on this
platform and distinguishing between PE32 and PE32+ binaries has the
exact same issue going on, and so the fix includes reworking that logic
to correctly bounds check all of those tests as well.
It's not currently known if this is actually exploitable beyond creating
a denial of service, and an attacker who is in a position to use it for
a denial of service attack must already be able to do so.
Resolves: CVE-2023-40551
Reported-by: gkirkpatrick@google.com
Signed-off-by: Peter Jones <pjones@redhat.com>
---
pe.c | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/pe.c b/pe.c
index ba3e2bb..78d6532 100644
--- a/pe.c
+++ b/pe.c
@@ -631,7 +631,7 @@ static int
image_is_64_bit(EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr)
{
/* .Magic is the same offset in all cases */
- if (PEHdr->Pe32Plus.OptionalHeader.Magic
+ if (PEHdr->Pe32.OptionalHeader.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC)
return 1;
return 0;
@@ -697,14 +697,34 @@ read_header(void *data, unsigned int datasize,
unsigned long HeaderWithoutDataDir, SectionHeaderOffset, OptHeaderSize;
unsigned long FileAlignment = 0;
UINT16 DllFlags;
+ size_t dos_sz = 0;
- if (datasize < sizeof (PEHdr->Pe32)) {
+ if (datasize < sizeof (*DosHdr)) {
perror(L"Invalid image\n");
return EFI_UNSUPPORTED;
}
- if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ if (DosHdr->e_lfanew < sizeof (*DosHdr) ||
+ DosHdr->e_lfanew > datasize - 4) {
+ perror(L"Invalid image\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ dos_sz = DosHdr->e_lfanew;
PEHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((char *)data + DosHdr->e_lfanew);
+ }
+
+ if (datasize - dos_sz < sizeof (PEHdr->Pe32)) {
+ perror(L"Invalid image\n");
+ return EFI_UNSUPPORTED;
+ }
+
+ if (image_is_64_bit(PEHdr) &&
+ (datasize - dos_sz < sizeof (PEHdr->Pe32Plus))) {
+ perror(L"Invalid image\n");
+ return EFI_UNSUPPORTED;
+ }
if (!image_is_loadable(PEHdr)) {
perror(L"Platform does not support this image\n");
--
2.43.0.594.gd9cf4e227d-goog