82 lines
2.8 KiB
Diff
82 lines
2.8 KiB
Diff
From 945f88af2301bb4deec66eb16cd47136970ab2f2 Mon Sep 17 00:00:00 2001
|
|
From: jinlun <jinlun@huawei.com>
|
|
Date: Tue, 30 Jan 2024 10:20:28 +0800
|
|
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.
|
|
h
|
|
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>
|
|
---
|
|
shim.c | 26 +++++++++++++++++++++++---
|
|
1 file changed, 23 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/shim.c b/shim.c
|
|
index 2c3dbf3..8bfa652 100644
|
|
--- a/shim.c
|
|
+++ b/shim.c
|
|
@@ -161,7 +161,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;
|
|
@@ -1095,14 +1095,34 @@ static EFI_STATUS read_header(void *data, unsigned int datasize,
|
|
EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = data;
|
|
unsigned long HeaderWithoutDataDir, SectionHeaderOffset, OptHeaderSize;
|
|
unsigned long FileAlignment = 0;
|
|
+ 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.33.0
|
|
|