!129 漏洞修复CVE-2023-40547 CVE-2023-40548 CVE-2023-40549 CVE-2023-40550 CVE-2023-40551
From: @jinlun123123 Reviewed-by: @HuaxinLuGitee, @huangzq6 Signed-off-by: @HuaxinLuGitee
This commit is contained in:
commit
6ecd956536
@ -0,0 +1,51 @@
|
|||||||
|
From f27182695d88350b48c8b9a6dce54bb513d7aa4e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peter Jones <pjones@redhat.com>
|
||||||
|
Date: Thu, 27 Jul 2023 15:13:08 -0400
|
||||||
|
Subject: [PATCH] Add primitives for overflow-checked arithmetic operations.
|
||||||
|
|
||||||
|
We need to do arithmetic on untrusted values sometimes, so this patch
|
||||||
|
adds the following primitives as macros that wrap the compiler builtins.
|
||||||
|
|
||||||
|
bool checked_add(TYPE addend0, TYPE addend1, TYPE *sum)
|
||||||
|
bool checked_sub(TYPE minuend, TYPE subtrahend, TYPE *difference)
|
||||||
|
bool checked_mul(TYPE factor0, TYPE factor1, TYPE *product)
|
||||||
|
|
||||||
|
And also the following primitive which returns True if divisor is 0 and
|
||||||
|
False otherwise:
|
||||||
|
|
||||||
|
bool checked_div(TYPE dividend, TYPE divisor, TYPE *quotient)
|
||||||
|
|
||||||
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||||
|
---
|
||||||
|
include/compiler.h | 16 ++++++++++++++++
|
||||||
|
1 file changed, 16 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/include/compiler.h b/include/compiler.h
|
||||||
|
index b0d595f..545a72e 100644
|
||||||
|
--- a/include/compiler.h
|
||||||
|
+++ b/include/compiler.h
|
||||||
|
@@ -198,5 +198,21 @@
|
||||||
|
#error shim has no cache_invalidate() implementation for this compiler
|
||||||
|
#endif /* __GNUC__ */
|
||||||
|
|
||||||
|
+#define checked_add(addend0, addend1, sum) \
|
||||||
|
+ __builtin_add_overflow(addend0, addend1, sum)
|
||||||
|
+#define checked_sub(minuend, subtrahend, difference) \
|
||||||
|
+ __builtin_sub_overflow(minuend, subtrahend, difference)
|
||||||
|
+#define checked_mul(factor0, factor1, product) \
|
||||||
|
+ __builtin_mul_overflow(factor0, factor1, product)
|
||||||
|
+#define checked_div(dividend, divisor, quotient) \
|
||||||
|
+ ({ \
|
||||||
|
+ bool _ret = True; \
|
||||||
|
+ if ((divisor) != 0) { \
|
||||||
|
+ _ret = False; \
|
||||||
|
+ (quotient) = (dividend) / (divisor); \
|
||||||
|
+ } \
|
||||||
|
+ _ret; \
|
||||||
|
+ })
|
||||||
|
+
|
||||||
|
#endif /* !COMPILER_H_ */
|
||||||
|
// vim:fenc=utf-8:tw=75:et
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
From 0226b56513b2b8bd5fd281bce77c40c9bf07c66d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peter Jones <pjones@redhat.com>
|
||||||
|
Date: Wed, 2 Aug 2023 14:19:31 -0400
|
||||||
|
Subject: [PATCH] CVE-2023-40547 - avoid incorrectly trusting HTTP headers
|
||||||
|
|
||||||
|
When retrieving files via HTTP or related protocols, shim attempts to
|
||||||
|
allocate a buffer to store the received data. Unfortunately, this means
|
||||||
|
getting the size from an HTTP header, which can be manipulated to
|
||||||
|
specify a size that's smaller than the received data. In this case, the
|
||||||
|
code accidentally uses the header for the allocation but the protocol
|
||||||
|
metadata to copy it from the rx buffer, resulting in an out-of-bounds
|
||||||
|
write.
|
||||||
|
|
||||||
|
This patch adds an additional check to test that the rx buffer is not
|
||||||
|
larger than the allocation.
|
||||||
|
|
||||||
|
Resolves: CVE-2023-40547
|
||||||
|
Reported-by: Bill Demirkapi, Microsoft Security Response Center
|
||||||
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||||
|
---
|
||||||
|
httpboot.c | 8 +++++++-
|
||||||
|
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/httpboot.c b/httpboot.c
|
||||||
|
index dfa493b..b34dd49 100644
|
||||||
|
--- a/httpboot.c
|
||||||
|
+++ b/httpboot.c
|
||||||
|
@@ -578,7 +578,13 @@ receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*buf_size == 0) {
|
||||||
|
- perror(L"Failed to get Content-Lenght\n");
|
||||||
|
+ perror(L"Failed to get Content-Length\n");
|
||||||
|
+ goto error;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (*buf_size < rx_message.BodyLength) {
|
||||||
|
+ efi_status = EFI_BAD_BUFFER_SIZE;
|
||||||
|
+ perror(L"Invalid Content-Length\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
From 96dccc255b16e9465dbee50b3cef6b3db74d11c8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peter Jones <pjones@redhat.com>
|
||||||
|
Date: Thu, 27 Jul 2023 15:21:31 -0400
|
||||||
|
Subject: [PATCH] CVE-2023-40548 Fix integer overflow on SBAT section size on
|
||||||
|
32-bit system
|
||||||
|
|
||||||
|
In verify_sbat_section(), we do some math on data that comes from the
|
||||||
|
binary being verified - in this case, we add 1 to the size of the
|
||||||
|
".sbat" section as reported in the section header, which is then used as
|
||||||
|
the input to the size of an allocation. The original value is then used
|
||||||
|
for a size in a memcpy(), which means there's an out-of-bounds write in
|
||||||
|
the overflow case.
|
||||||
|
|
||||||
|
Due to the type of the variable being size_t, but the type in the
|
||||||
|
section header being uint32_t, this is only plausibly accomplished on
|
||||||
|
32-bit systems.
|
||||||
|
|
||||||
|
This patch makes the arithmetic use a checked add operation to avoid
|
||||||
|
overflow. Additionally, it adds a check in verify_buffer_sbat() to
|
||||||
|
guarantee that the data is within the binary.
|
||||||
|
|
||||||
|
It's not currently known if this is actually exploitable on such
|
||||||
|
systems; the memory layout on a particular machine may further mitigate
|
||||||
|
this scenario.
|
||||||
|
|
||||||
|
Resolves: CVE-2023-40548
|
||||||
|
Reported-by: gkirkpatrick@google.com
|
||||||
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||||
|
---
|
||||||
|
pe.c | 6 +++++-
|
||||||
|
shim.c | 6 ++++++
|
||||||
|
2 files changed, 11 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/pe.c b/pe.c
|
||||||
|
index e15b89f..b3a9d46 100644
|
||||||
|
--- a/pe.c
|
||||||
|
+++ b/pe.c
|
||||||
|
@@ -355,7 +355,11 @@ verify_sbat_section(char *SBATBase, size_t SBATSize)
|
||||||
|
return in_protocol ? EFI_SUCCESS : EFI_SECURITY_VIOLATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
- sbat_size = SBATSize + 1;
|
||||||
|
+ if (checked_add(SBATSize, 1, &sbat_size)) {
|
||||||
|
+ dprint(L"SBATSize + 1 would overflow\n");
|
||||||
|
+ return EFI_SECURITY_VIOLATION;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
sbat_data = AllocatePool(sbat_size);
|
||||||
|
if (!sbat_data) {
|
||||||
|
console_print(L"Failed to allocate .sbat section buffer\n");
|
||||||
|
diff --git a/shim.c b/shim.c
|
||||||
|
index 3fd1e2a..84a98ca 100644
|
||||||
|
--- a/shim.c
|
||||||
|
+++ b/shim.c
|
||||||
|
@@ -743,11 +743,17 @@ verify_buffer_sbat (char *data, int datasize,
|
||||||
|
* and ignore the section if it isn't. */
|
||||||
|
if (Section->SizeOfRawData &&
|
||||||
|
Section->SizeOfRawData >= Section->Misc.VirtualSize) {
|
||||||
|
+ uint64_t boundary;
|
||||||
|
SBATBase = ImageAddress(data, datasize,
|
||||||
|
Section->PointerToRawData);
|
||||||
|
SBATSize = Section->SizeOfRawData;
|
||||||
|
dprint(L"sbat section base:0x%lx size:0x%lx\n",
|
||||||
|
SBATBase, SBATSize);
|
||||||
|
+ if (checked_add((uint64_t)SBATBase, SBATSize, &boundary) ||
|
||||||
|
+ (boundary > (uint64_t)data + datasize)) {
|
||||||
|
+ perror(L"Section exceeds bounds of image\n");
|
||||||
|
+ return EFI_UNSUPPORTED;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
From afdc5039de0a4a3a40162a32daa070f94a883f09 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peter Jones <pjones@redhat.com>
|
||||||
|
Date: Thu, 27 Jul 2023 14:58:55 -0400
|
||||||
|
Subject: [PATCH] CVE-2023-40549 Authenticode: verify that the signature header
|
||||||
|
is in bounds.
|
||||||
|
|
||||||
|
In the validation logic in verify_buffer_authenticode(), there is yet
|
||||||
|
another case where we need to guarantee an object is in the binary but
|
||||||
|
we're only validating the pointer to it. In this case, we're validating
|
||||||
|
that the actual signature data is in the binary, but unfortunately we
|
||||||
|
failed to validate that the header describing it is, so a malformed
|
||||||
|
binary can cause us to take an out-of-bounds read (probably but not
|
||||||
|
necessarily on the same page) past the end of the buffer.
|
||||||
|
|
||||||
|
This patch adds a bounds check to verify that the signature is
|
||||||
|
actually within the bounds.
|
||||||
|
|
||||||
|
It seems unlikely this can be used for more than a denial of service,
|
||||||
|
and if you can get shim to try to verify a malformed binary, you've
|
||||||
|
effectively already accomplished a DoS.
|
||||||
|
|
||||||
|
Resolves: CVE-2023-40549
|
||||||
|
Reported-by: gkirkpatrick@google.com
|
||||||
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||||
|
---
|
||||||
|
shim.c | 9 ++++++++-
|
||||||
|
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/shim.c b/shim.c
|
||||||
|
index 3a97067..3fd1e2a 100644
|
||||||
|
--- a/shim.c
|
||||||
|
+++ b/shim.c
|
||||||
|
@@ -627,11 +627,13 @@ verify_buffer_authenticode (char *data, int datasize,
|
||||||
|
return EFI_SECURITY_VIOLATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (context->SecDir->Size >= size) {
|
||||||
|
+ if (checked_add(context->SecDir->Size, context->SecDir->VirtualAddress, &offset) ||
|
||||||
|
+ offset > size) {
|
||||||
|
perror(L"Certificate Database size is too large\n");
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ offset = 0;
|
||||||
|
ret_efi_status = EFI_NOT_FOUND;
|
||||||
|
do {
|
||||||
|
WIN_CERTIFICATE_EFI_PKCS *sig = NULL;
|
||||||
|
@@ -642,6 +644,11 @@ verify_buffer_authenticode (char *data, int datasize,
|
||||||
|
if (!sig)
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ if ((uint64_t)&sig[1] > (uint64_t)data + datasize) {
|
||||||
|
+ perror(L"Certificate size is too large for secruity database");
|
||||||
|
+ return EFI_INVALID_PARAMETER;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
sz = offset + offsetof(WIN_CERTIFICATE_EFI_PKCS, Hdr.dwLength)
|
||||||
|
+ sizeof(sig->Hdr.dwLength);
|
||||||
|
if (sz > context->SecDir->Size) {
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
From 93ce2552f3e9f71f888a672913bfc0eef255c56d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peter Jones <pjones@redhat.com>
|
||||||
|
Date: Thu, 27 Jul 2023 14:57:32 -0400
|
||||||
|
Subject: [PATCH] CVE-2023-40550 pe: Fix an out-of-bound read in
|
||||||
|
verify_buffer_sbat()
|
||||||
|
|
||||||
|
In verify_buffer_sbat(), we have a goal-seeking loop to find the .sbat
|
||||||
|
section header. Unfortunately, while the actual contents of the section
|
||||||
|
are checked for being inside the binary, no such check exists for the
|
||||||
|
contents of the section table entry.
|
||||||
|
|
||||||
|
As a result, a carefully constructed binary will cause an out-of-bounds
|
||||||
|
read checking if the section name is ".sbat\0\0\0" or not.
|
||||||
|
|
||||||
|
This patch adds a check that each section table entry is within the
|
||||||
|
bounds of the binary.
|
||||||
|
|
||||||
|
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-40550
|
||||||
|
Reported-by: gkirkpatrick@google.com
|
||||||
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||||
|
---
|
||||||
|
shim.c | 5 +++++
|
||||||
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/shim.c b/shim.c
|
||||||
|
index 01e5e56..3a97067 100644
|
||||||
|
--- a/shim.c
|
||||||
|
+++ b/shim.c
|
||||||
|
@@ -709,6 +709,11 @@ verify_buffer_sbat (char *data, int datasize,
|
||||||
|
|
||||||
|
Section = context->FirstSection;
|
||||||
|
for (i = 0; i < context->NumberOfSections; i++, Section++) {
|
||||||
|
+ if ((uint64_t)&Section[1] > (uint64_t)data + datasize) {
|
||||||
|
+ perror(L"Section exceeds bounds of image\n");
|
||||||
|
+ return EFI_UNSUPPORTED;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (CompareMem(Section->Name, ".sbat\0\0\0", 8) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
From f93d9d8c546eed520314ce435c26b184663e1032 Mon Sep 17 00:00:00 2001
|
||||||
|
From: jinlun <jinlun@huawei.com>
|
||||||
|
Date: Thu, 25 Jan 2024 14:50:03 +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>
|
||||||
|
---
|
||||||
|
pe.c | 24 ++++++++++++++++++++++--
|
||||||
|
post-process-pe.c | 2 +-
|
||||||
|
2 files changed, 23 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/pe.c b/pe.c
|
||||||
|
index 96f9c0e..d14f2ff 100644
|
||||||
|
--- a/pe.c
|
||||||
|
+++ b/pe.c
|
||||||
|
@@ -771,14 +771,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");
|
||||||
|
diff --git a/post-process-pe.c b/post-process-pe.c
|
||||||
|
index de8f4a3..86350ce 100644
|
||||||
|
--- a/post-process-pe.c
|
||||||
|
+++ b/post-process-pe.c
|
||||||
|
@@ -110,7 +110,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;
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
From dae82f6bd72cf600e5d48046ec674a441d0f49d7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peter Jones <pjones@redhat.com>
|
||||||
|
Date: Wed, 2 Aug 2023 14:36:09 -0400
|
||||||
|
Subject: [PATCH] Further mitigations against CVE-2023-40546 as a class
|
||||||
|
|
||||||
|
In CVE-2023-40546, an incorrect invocation of LogError()
|
||||||
|
causes a read from the page at address 0, which on newer systems will
|
||||||
|
correctly cause a fault. The immediate fix for this CVE is to fix the
|
||||||
|
invocation so that the error is logged correctly, but there is more that
|
||||||
|
can be done.
|
||||||
|
|
||||||
|
This patch adds additional checks to ensure that the format specifier on
|
||||||
|
any of these invocations can not be NULL, thereby mitigating this entire
|
||||||
|
class of error from creating a fault. Additionally, most of these
|
||||||
|
checks are done using _Static_assert(), so they should normally be
|
||||||
|
triggered at compile time.
|
||||||
|
|
||||||
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||||
|
---
|
||||||
|
errlog.c | 3 +++
|
||||||
|
shim.h | 26 ++++++++++++++++++++------
|
||||||
|
2 files changed, 23 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/errlog.c b/errlog.c
|
||||||
|
index cc6a89f..3c5e0af 100644
|
||||||
|
--- a/errlog.c
|
||||||
|
+++ b/errlog.c
|
||||||
|
@@ -32,6 +32,9 @@ VLogError(const char *file, int line, const char *func, const CHAR16 *fmt,
|
||||||
|
ms_va_list args2;
|
||||||
|
CHAR16 **newerrs;
|
||||||
|
|
||||||
|
+ if (file == NULL || func == NULL || fmt == NULL)
|
||||||
|
+ return EFI_INVALID_PARAMETER;
|
||||||
|
+
|
||||||
|
newerrs = ReallocatePool(errs, (nerrs + 1) * sizeof(*errs),
|
||||||
|
(nerrs + 3) * sizeof(*errs));
|
||||||
|
if (!newerrs)
|
||||||
|
diff --git a/shim.h b/shim.h
|
||||||
|
index 3e221b5..652be45 100644
|
||||||
|
--- a/shim.h
|
||||||
|
+++ b/shim.h
|
||||||
|
@@ -281,18 +281,32 @@ verify_buffer (char *data, int datasize,
|
||||||
|
#ifndef SHIM_UNIT_TEST
|
||||||
|
#define perror_(file, line, func, fmt, ...) ({ \
|
||||||
|
UINTN __perror_ret = 0; \
|
||||||
|
+ _Static_assert((fmt) != NULL, \
|
||||||
|
+ "format specifier cannot be NULL"); \
|
||||||
|
if (!in_protocol) \
|
||||||
|
__perror_ret = console_print((fmt), ##__VA_ARGS__); \
|
||||||
|
LogError_(file, line, func, fmt, ##__VA_ARGS__); \
|
||||||
|
__perror_ret; \
|
||||||
|
})
|
||||||
|
-#define perror(fmt, ...) \
|
||||||
|
- perror_(__FILE__, __LINE__ - 1, __func__, fmt, ##__VA_ARGS__)
|
||||||
|
-#define LogError(fmt, ...) \
|
||||||
|
- LogError_(__FILE__, __LINE__ - 1, __func__, fmt, ##__VA_ARGS__)
|
||||||
|
+#define perror(fmt, ...) ({ \
|
||||||
|
+ _Static_assert((fmt) != NULL, \
|
||||||
|
+ "format specifier cannot be NULL"); \
|
||||||
|
+ perror_(__FILE__, __LINE__ - 1, __func__, fmt, ##__VA_ARGS__); \
|
||||||
|
+ })
|
||||||
|
+#define LogError(fmt, ...) ({ \
|
||||||
|
+ _Static_assert((fmt) != NULL, \
|
||||||
|
+ "format specifier cannot be NULL"); \
|
||||||
|
+ LogError_(__FILE__, __LINE__ - 1, __func__, fmt, ##__VA_ARGS__);\
|
||||||
|
+ })
|
||||||
|
#else
|
||||||
|
-#define perror(fmt, ...)
|
||||||
|
-#define LogError(fmt, ...)
|
||||||
|
+#define perror(fmt, ...) ({ \
|
||||||
|
+ _Static_assert((fmt) != NULL, \
|
||||||
|
+ "format specifier cannot be NULL"); \
|
||||||
|
+ })
|
||||||
|
+#define LogError(fmt, ...) ({ \
|
||||||
|
+ _Static_assert((fmt) != NULL, \
|
||||||
|
+ "format specifier cannot be NULL"); \
|
||||||
|
+ })
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_SHIM_DEVEL
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
From e7f5fdf53ee68025f3ef2688e2f27ccb0082db83 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peter Jones <pjones@redhat.com>
|
||||||
|
Date: Thu, 27 Jul 2023 17:59:22 -0400
|
||||||
|
Subject: [PATCH] pe-relocate: Ensure nothing else implements CVE-2023-40550
|
||||||
|
|
||||||
|
In CVE-2023-40550, we scan the section headers for the section
|
||||||
|
name without having verified that the section header is actually in the
|
||||||
|
binary.
|
||||||
|
|
||||||
|
This patch adds such verification to read_headers()
|
||||||
|
|
||||||
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||||
|
---
|
||||||
|
pe-relocate.c | 7 +++++++
|
||||||
|
1 file changed, 7 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/pe-relocate.c b/pe-relocate.c
|
||||||
|
index 1723642..cb7a02c 100644
|
||||||
|
--- a/pe.c
|
||||||
|
+++ b/pe.c
|
||||||
|
@@ -472,6 +472,13 @@ read_header(void *data, unsigned int datasize,
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (checked_mul((size_t)context->NumberOfSections, sizeof(EFI_IMAGE_SECTION_HEADER), &tmpsz0) ||
|
||||||
|
+ checked_add(tmpsz0, SectionHeaderOffset, &tmpsz0) ||
|
||||||
|
+ (tmpsz0 > datasize)) {
|
||||||
|
+ perror(L"Image sections overflow section headers\n");
|
||||||
|
+ return EFI_UNSUPPORTED;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (checked_sub((size_t)(uintptr_t)PEHdr, (size_t)(uintptr_t)data, &tmpsz0) ||
|
||||||
|
checked_add(tmpsz0, sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION), &tmpsz0) ||
|
||||||
|
(tmpsz0 > datasize)) {
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,112 @@
|
|||||||
|
From e912071b8a6045549c2d1e7b5e1b2150c33ef519 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Peter Jones <pjones@redhat.com>
|
||||||
|
Date: Wed, 26 Jul 2023 16:14:40 -0400
|
||||||
|
Subject: [PATCH] pe-relocate: make read_header() use checked arithmetic
|
||||||
|
operations.
|
||||||
|
|
||||||
|
Since the fuzzer already found one problem here, and none of that data
|
||||||
|
is intended to be trusted to begin with, it makes sense to use checked
|
||||||
|
math for all of the values read from the PE headers.
|
||||||
|
|
||||||
|
This updates all of that math to use checked arithmetic operations.
|
||||||
|
|
||||||
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||||
|
---
|
||||||
|
pe-relocate.c | 49 +++++++++++++++++++++++++++++++++----------------
|
||||||
|
1 file changed, 33 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/pe-relocate.c b/pe-relocate.c
|
||||||
|
index b11fc68..1723642 100644
|
||||||
|
--- a/pe.c
|
||||||
|
+++ b/pe.c
|
||||||
|
@@ -376,6 +376,7 @@ read_header(void *data, unsigned int datasize,
|
||||||
|
unsigned long FileAlignment = 0;
|
||||||
|
UINT16 DllFlags;
|
||||||
|
size_t dos_sz = 0;
|
||||||
|
+ size_t tmpsz0, tmpsz1;
|
||||||
|
|
||||||
|
if (datasize < sizeof (*DosHdr)) {
|
||||||
|
perror(L"Invalid image\n");
|
||||||
|
@@ -443,31 +444,37 @@ read_header(void *data, unsigned int datasize,
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
- HeaderWithoutDataDir = OptHeaderSize
|
||||||
|
- - sizeof (EFI_IMAGE_DATA_DIRECTORY) * EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;
|
||||||
|
- if (((UINT32)PEHdr->Pe32.FileHeader.SizeOfOptionalHeader - HeaderWithoutDataDir) !=
|
||||||
|
- context->NumberOfRvaAndSizes * sizeof (EFI_IMAGE_DATA_DIRECTORY)) {
|
||||||
|
+ if (checked_mul(sizeof(EFI_IMAGE_DATA_DIRECTORY), EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES, &tmpsz0) ||
|
||||||
|
+ checked_sub(OptHeaderSize, tmpsz0, &HeaderWithoutDataDir) ||
|
||||||
|
+ checked_sub((size_t)PEHdr->Pe32.FileHeader.SizeOfOptionalHeader, HeaderWithoutDataDir, &tmpsz0) ||
|
||||||
|
+ checked_mul((size_t)context->NumberOfRvaAndSizes, sizeof (EFI_IMAGE_DATA_DIRECTORY), &tmpsz1) ||
|
||||||
|
+ (tmpsz0 != tmpsz1)) {
|
||||||
|
perror(L"Image header overflows data directory\n");
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
- SectionHeaderOffset = DosHdr->e_lfanew
|
||||||
|
- + sizeof (UINT32)
|
||||||
|
- + sizeof (EFI_IMAGE_FILE_HEADER)
|
||||||
|
- + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader;
|
||||||
|
- if (((UINT32)context->ImageSize - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER
|
||||||
|
- <= context->NumberOfSections) {
|
||||||
|
+ if (checked_add((size_t)DosHdr->e_lfanew, sizeof(UINT32), &tmpsz0) ||
|
||||||
|
+ checked_add(tmpsz0, sizeof(EFI_IMAGE_FILE_HEADER), &tmpsz0) ||
|
||||||
|
+ checked_add(tmpsz0, PEHdr->Pe32.FileHeader.SizeOfOptionalHeader, &SectionHeaderOffset)) {
|
||||||
|
perror(L"Image sections overflow image size\n");
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if ((context->SizeOfHeaders - SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER
|
||||||
|
- < (UINT32)context->NumberOfSections) {
|
||||||
|
+ if (checked_sub((size_t)context->ImageSize, SectionHeaderOffset, &tmpsz0) ||
|
||||||
|
+ (tmpsz0 / EFI_IMAGE_SIZEOF_SECTION_HEADER <= context->NumberOfSections)) {
|
||||||
|
+ perror(L"Image sections overflow image size\n");
|
||||||
|
+ return EFI_UNSUPPORTED;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (checked_sub((size_t)context->SizeOfHeaders, SectionHeaderOffset, &tmpsz0) ||
|
||||||
|
+ (tmpsz0 / EFI_IMAGE_SIZEOF_SECTION_HEADER < (UINT32)context->NumberOfSections)) {
|
||||||
|
perror(L"Image sections overflow section headers\n");
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if ((((UINT8 *)PEHdr - (UINT8 *)data) + sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION)) > datasize) {
|
||||||
|
+ if (checked_sub((size_t)(uintptr_t)PEHdr, (size_t)(uintptr_t)data, &tmpsz0) ||
|
||||||
|
+ checked_add(tmpsz0, sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION), &tmpsz0) ||
|
||||||
|
+ (tmpsz0 > datasize)) {
|
||||||
|
perror(L"Invalid image\n");
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
@@ -504,15 +511,25 @@ read_header(void *data, unsigned int datasize,
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
- context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)((char *)PEHdr + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER));
|
||||||
|
+ if (checked_add((size_t)(uintptr_t)PEHdr, PEHdr->Pe32.FileHeader.SizeOfOptionalHeader, &tmpsz0) ||
|
||||||
|
+ checked_add(tmpsz0, sizeof(UINT32), &tmpsz0) ||
|
||||||
|
+ checked_add(tmpsz0, sizeof(EFI_IMAGE_FILE_HEADER), &tmpsz0)) {
|
||||||
|
+ perror(L"Invalid image\n");
|
||||||
|
+ return EFI_UNSUPPORTED;
|
||||||
|
+ }
|
||||||
|
+ context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)(uintptr_t)tmpsz0;
|
||||||
|
+ if ((uint64_t)(context->FirstSection) > (uint64_t)data + datasize) {
|
||||||
|
+ perror(L"Invalid image\n");
|
||||||
|
+ return EFI_UNSUPPORTED;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (context->ImageSize < context->SizeOfHeaders) {
|
||||||
|
perror(L"Invalid image\n");
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if ((unsigned long)((UINT8 *)context->SecDir - (UINT8 *)data) >
|
||||||
|
- (datasize - sizeof(EFI_IMAGE_DATA_DIRECTORY))) {
|
||||||
|
+ if (checked_sub((size_t)(uintptr_t)context->SecDir, (size_t)(uintptr_t)data, &tmpsz0) ||
|
||||||
|
+ (tmpsz0 > datasize - sizeof(EFI_IMAGE_DATA_DIRECTORY))) {
|
||||||
|
perror(L"Invalid image\n");
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
15
shim.spec
15
shim.spec
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
Name: shim
|
Name: shim
|
||||||
Version: 15.7
|
Version: 15.7
|
||||||
Release: 2
|
Release: 3
|
||||||
Summary: First-stage UEFI bootloader
|
Summary: First-stage UEFI bootloader
|
||||||
ExclusiveArch: x86_64 aarch64
|
ExclusiveArch: x86_64 aarch64
|
||||||
License: BSD
|
License: BSD
|
||||||
@ -35,6 +35,15 @@ Source1: BOOTAA64.CSV
|
|||||||
Source2: BOOTX64.CSV
|
Source2: BOOTX64.CSV
|
||||||
|
|
||||||
Patch1:backport-CVE-2023-40546.patch
|
Patch1:backport-CVE-2023-40546.patch
|
||||||
|
Patch2:backport-CVE-2023-40551-pe-relocate-Fix-bounds-check-for-MZ-b.patch
|
||||||
|
Patch3:backport-pe-relocate-make-read_header-use-checked-arithmetic-.patch
|
||||||
|
Patch4:backport-Add-primitives-for-overflow-checked-arithmetic-opera.patch
|
||||||
|
Patch5:backport-CVE-2023-40550-pe-Fix-an-out-of-bound-read-in-verify.patch
|
||||||
|
Patch6:backport-pe-relocate-Ensure-nothing-else-implements-CVE-2023-40550.patch
|
||||||
|
Patch7:backport-CVE-2023-40548-Fix-integer-overflow-on-SBAT-section-.patch
|
||||||
|
Patch8:backport-CVE-2023-40547-avoid-incorrectly-trusting-HTTP-heade.patch
|
||||||
|
Patch9:backport-Further-mitigations-against-CVE-2023-40546-as-a-clas.patch
|
||||||
|
Patch10:backport-CVE-2023-40549-Authenticode-verify-that-the-signatur.patch
|
||||||
|
|
||||||
# Feature for shim SMx support
|
# Feature for shim SMx support
|
||||||
Patch9000:Feature-shim-openssl-add-ec-support.patch
|
Patch9000:Feature-shim-openssl-add-ec-support.patch
|
||||||
@ -156,6 +165,10 @@ make test
|
|||||||
/usr/src/debug/%{name}-%{version}-%{release}/*
|
/usr/src/debug/%{name}-%{version}-%{release}/*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Jan 25 2024 jinlun <jinlun@huawei.com> - 15.7-3
|
||||||
|
- fix CVE-2023-40547 CVE-2023-40548 CVE-2023-40549 CVE-2023-40550
|
||||||
|
- CVE-2023-40551
|
||||||
|
|
||||||
* Tue Nov 7 2023 jinlun <jinlun@huawei.com> - 15.7-2
|
* Tue Nov 7 2023 jinlun <jinlun@huawei.com> - 15.7-2
|
||||||
- fix CVE-2023-40546
|
- fix CVE-2023-40546
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user