You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
308 lines
12 KiB
308 lines
12 KiB
7 months ago
|
From f6f72373630d901f331df719a0fb55e8f1143c4f Mon Sep 17 00:00:00 2001
|
||
|
From: Jon Maloy <jmaloy@redhat.com>
|
||
|
Date: Wed, 7 Feb 2024 15:43:10 -0500
|
||
|
Subject: [PATCH 10/17] SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4118
|
||
|
- CVE 2022-36764
|
||
|
|
||
|
RH-Author: Jon Maloy <jmaloy@redhat.com>
|
||
|
RH-MergeRequest: 44: edk2: heap buffer overflow in Tcg2MeasureGptTable()
|
||
|
RH-Jira: RHEL-21154 RHEL-21156
|
||
|
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||
|
RH-Commit: [10/13] 5ed702e16f390c79d1abb0ec0b04d886e0094c0b (jmaloy/jons_fork)
|
||
|
|
||
|
JIRA: https://issues.redhat.com/browse/RHEL-21156
|
||
|
CVE: CVE-2022-36764
|
||
|
Upstream: Merged
|
||
|
Conflicts: We get function definiton clash for the following three functions:
|
||
|
- SanitizePeImageEventSize()
|
||
|
This is defined both in
|
||
|
- SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitazion.c
|
||
|
and
|
||
|
- SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitazion.c
|
||
|
Closer investigation reveals that they are identical in functionality (although
|
||
|
not in comment style).
|
||
|
I chose to leave them as is now, meaning that this package will be
|
||
|
unbuildable until I add a commit renaming these symbols later in
|
||
|
this series.
|
||
|
|
||
|
commit 0d341c01eeabe0ab5e76693b36e728b8f538a40e
|
||
|
Author: Douglas Flick [MSFT] <doug.edk2@gmail.com>
|
||
|
Date: Fri Jan 12 02:16:05 2024 +0800
|
||
|
|
||
|
SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764
|
||
|
|
||
|
This commit contains the patch files and tests for DxeTpmMeasureBootLib
|
||
|
CVE 2022-36764.
|
||
|
|
||
|
Cc: Jiewen Yao <jiewen.yao@intel.com>
|
||
|
|
||
|
Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
|
||
|
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
|
||
|
|
||
|
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
|
||
|
---
|
||
|
.../DxeTpmMeasureBootLib.c | 17 ++--
|
||
|
.../DxeTpmMeasureBootLibSanitization.c | 44 +++++++++
|
||
|
.../DxeTpmMeasureBootLibSanitization.h | 23 +++++
|
||
|
.../DxeTpmMeasureBootLibSanitizationTest.c | 98 +++++++++++++++++--
|
||
|
4 files changed, 170 insertions(+), 12 deletions(-)
|
||
|
|
||
|
diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
|
||
|
index d44422dee8..1598015176 100644
|
||
|
--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
|
||
|
+++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
|
||
|
@@ -17,6 +17,7 @@
|
||
|
|
||
|
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
|
||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||
|
+Copyright (c) Microsoft Corporation.<BR>
|
||
|
|
||
|
Copyright (c) Microsoft Corporation.<BR>
|
||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||
|
@@ -338,19 +339,23 @@ TcgMeasurePeImage (
|
||
|
ImageLoad = NULL;
|
||
|
SectionHeader = NULL;
|
||
|
Sha1Ctx = NULL;
|
||
|
- FilePathSize = (UINT32) GetDevicePathSize (FilePath);
|
||
|
+ TcgEvent = NULL;
|
||
|
+ FilePathSize = (UINT32)GetDevicePathSize (FilePath);
|
||
|
|
||
|
- //
|
||
|
// Determine destination PCR by BootPolicy
|
||
|
//
|
||
|
- EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
|
||
|
- TcgEvent = AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT));
|
||
|
+ Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
|
||
|
+ if (EFI_ERROR (Status)) {
|
||
|
+ return EFI_UNSUPPORTED;
|
||
|
+ }
|
||
|
+
|
||
|
+ TcgEvent = AllocateZeroPool (EventSize);
|
||
|
if (TcgEvent == NULL) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
|
||
|
- TcgEvent->EventSize = EventSize;
|
||
|
- ImageLoad = (EFI_IMAGE_LOAD_EVENT *) TcgEvent->Event;
|
||
|
+ TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR);
|
||
|
+ ImageLoad = (EFI_IMAGE_LOAD_EVENT *)TcgEvent->Event;
|
||
|
|
||
|
switch (ImageType) {
|
||
|
case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
|
||
|
diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
|
||
|
index 37cd3ed0ea..bcf8c6de6f 100644
|
||
|
--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
|
||
|
+++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c
|
||
|
@@ -240,3 +240,47 @@ SanitizePrimaryHeaderGptEventSize (
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
+/**
|
||
|
+ This function will validate that the PeImage Event Size from the loaded image is sane
|
||
|
+ It will check the following:
|
||
|
+ - EventSize does not overflow
|
||
|
+
|
||
|
+ @param[in] FilePathSize - Size of the file path.
|
||
|
+ @param[out] EventSize - Pointer to the event size.
|
||
|
+
|
||
|
+ @retval EFI_SUCCESS
|
||
|
+ The event size is valid.
|
||
|
+
|
||
|
+ @retval EFI_OUT_OF_RESOURCES
|
||
|
+ Overflow would have occurred.
|
||
|
+
|
||
|
+ @retval EFI_INVALID_PARAMETER
|
||
|
+ One of the passed parameters was invalid.
|
||
|
+**/
|
||
|
+EFI_STATUS
|
||
|
+SanitizePeImageEventSize (
|
||
|
+ IN UINT32 FilePathSize,
|
||
|
+ OUT UINT32 *EventSize
|
||
|
+ )
|
||
|
+{
|
||
|
+ EFI_STATUS Status;
|
||
|
+
|
||
|
+ // Replacing logic:
|
||
|
+ // sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
|
||
|
+ Status = SafeUint32Add (OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath), FilePathSize, EventSize);
|
||
|
+ if (EFI_ERROR (Status)) {
|
||
|
+ DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n"));
|
||
|
+ return EFI_BAD_BUFFER_SIZE;
|
||
|
+ }
|
||
|
+
|
||
|
+ // Replacing logic:
|
||
|
+ // EventSize + sizeof (TCG_PCR_EVENT_HDR)
|
||
|
+ Status = SafeUint32Add (*EventSize, sizeof (TCG_PCR_EVENT_HDR), EventSize);
|
||
|
+ if (EFI_ERROR (Status)) {
|
||
|
+ DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n"));
|
||
|
+ return EFI_BAD_BUFFER_SIZE;
|
||
|
+ }
|
||
|
+
|
||
|
+ return EFI_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h
|
||
|
index 0d9d00c281..2248495813 100644
|
||
|
--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h
|
||
|
+++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h
|
||
|
@@ -111,4 +111,27 @@ SanitizePrimaryHeaderGptEventSize (
|
||
|
OUT UINT32 *EventSize
|
||
|
);
|
||
|
|
||
|
+/**
|
||
|
+ This function will validate that the PeImage Event Size from the loaded image is sane
|
||
|
+ It will check the following:
|
||
|
+ - EventSize does not overflow
|
||
|
+
|
||
|
+ @param[in] FilePathSize - Size of the file path.
|
||
|
+ @param[out] EventSize - Pointer to the event size.
|
||
|
+
|
||
|
+ @retval EFI_SUCCESS
|
||
|
+ The event size is valid.
|
||
|
+
|
||
|
+ @retval EFI_OUT_OF_RESOURCES
|
||
|
+ Overflow would have occurred.
|
||
|
+
|
||
|
+ @retval EFI_INVALID_PARAMETER
|
||
|
+ One of the passed parameters was invalid.
|
||
|
+**/
|
||
|
+EFI_STATUS
|
||
|
+SanitizePeImageEventSize (
|
||
|
+ IN UINT32 FilePathSize,
|
||
|
+ OUT UINT32 *EventSize
|
||
|
+ );
|
||
|
+
|
||
|
#endif // DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_
|
||
|
diff --git a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c
|
||
|
index eeb928cdb0..c41498be45 100644
|
||
|
--- a/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c
|
||
|
+++ b/SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c
|
||
|
@@ -1,8 +1,8 @@
|
||
|
/** @file
|
||
|
-This file includes the unit test cases for the DxeTpmMeasureBootLibSanitizationTest.c.
|
||
|
+ This file includes the unit test cases for the DxeTpmMeasureBootLibSanitizationTest.c.
|
||
|
|
||
|
-Copyright (c) Microsoft Corporation.<BR>
|
||
|
-SPDX-License-Identifier: BSD-2-Clause-Patent
|
||
|
+ Copyright (c) Microsoft Corporation.<BR>
|
||
|
+ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||
|
**/
|
||
|
|
||
|
#include <Uefi.h>
|
||
|
@@ -186,9 +186,6 @@ TestSanitizePrimaryHeaderGptEventSize (
|
||
|
EFI_STATUS Status;
|
||
|
EFI_PARTITION_TABLE_HEADER PrimaryHeader;
|
||
|
UINTN NumberOfPartition;
|
||
|
- EFI_GPT_DATA *GptData;
|
||
|
-
|
||
|
- GptData = NULL;
|
||
|
|
||
|
// Test that a normal PrimaryHeader passes validation
|
||
|
PrimaryHeader.NumberOfPartitionEntries = 5;
|
||
|
@@ -222,6 +219,94 @@ TestSanitizePrimaryHeaderGptEventSize (
|
||
|
return UNIT_TEST_PASSED;
|
||
|
}
|
||
|
|
||
|
+/**
|
||
|
+ This function tests the SanitizePeImageEventSize function.
|
||
|
+ It's intent is to test that the untrusted input from a file path for an
|
||
|
+ EFI_IMAGE_LOAD_EVENT structure will not cause an overflow when calculating
|
||
|
+ the event size when allocating space.
|
||
|
+
|
||
|
+ @param[in] Context The unit test context.
|
||
|
+
|
||
|
+ @retval UNIT_TEST_PASSED The test passed.
|
||
|
+ @retval UNIT_TEST_ERROR_TEST_FAILED The test failed.
|
||
|
+**/
|
||
|
+UNIT_TEST_STATUS
|
||
|
+EFIAPI
|
||
|
+TestSanitizePeImageEventSize (
|
||
|
+ IN UNIT_TEST_CONTEXT Context
|
||
|
+ )
|
||
|
+{
|
||
|
+ UINT32 EventSize;
|
||
|
+ UINTN ExistingLogicEventSize;
|
||
|
+ UINT32 FilePathSize;
|
||
|
+ EFI_STATUS Status;
|
||
|
+ EFI_DEVICE_PATH_PROTOCOL DevicePath;
|
||
|
+ EFI_IMAGE_LOAD_EVENT *ImageLoadEvent;
|
||
|
+ UNIT_TEST_STATUS TestStatus;
|
||
|
+
|
||
|
+ TestStatus = UNIT_TEST_ERROR_TEST_FAILED;
|
||
|
+
|
||
|
+ // Generate EFI_DEVICE_PATH_PROTOCOL test data
|
||
|
+ DevicePath.Type = 0;
|
||
|
+ DevicePath.SubType = 0;
|
||
|
+ DevicePath.Length[0] = 0;
|
||
|
+ DevicePath.Length[1] = 0;
|
||
|
+
|
||
|
+ // Generate EFI_IMAGE_LOAD_EVENT test data
|
||
|
+ ImageLoadEvent = AllocateZeroPool (sizeof (EFI_IMAGE_LOAD_EVENT) + sizeof (EFI_DEVICE_PATH_PROTOCOL));
|
||
|
+ if (ImageLoadEvent == NULL) {
|
||
|
+ DEBUG ((DEBUG_ERROR, "%a: AllocateZeroPool failed\n", __func__));
|
||
|
+ goto Exit;
|
||
|
+ }
|
||
|
+
|
||
|
+ // Populate EFI_IMAGE_LOAD_EVENT54 test data
|
||
|
+ ImageLoadEvent->ImageLocationInMemory = (EFI_PHYSICAL_ADDRESS)0x12345678;
|
||
|
+ ImageLoadEvent->ImageLengthInMemory = 0x1000;
|
||
|
+ ImageLoadEvent->ImageLinkTimeAddress = (UINTN)ImageLoadEvent;
|
||
|
+ ImageLoadEvent->LengthOfDevicePath = sizeof (EFI_DEVICE_PATH_PROTOCOL);
|
||
|
+ CopyMem (ImageLoadEvent->DevicePath, &DevicePath, sizeof (EFI_DEVICE_PATH_PROTOCOL));
|
||
|
+
|
||
|
+ FilePathSize = 255;
|
||
|
+
|
||
|
+ // Test that a normal PE image passes validation
|
||
|
+ Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
|
||
|
+ if (EFI_ERROR (Status)) {
|
||
|
+ UT_LOG_ERROR ("SanitizePeImageEventSize failed with %r\n", Status);
|
||
|
+ goto Exit;
|
||
|
+ }
|
||
|
+
|
||
|
+ // Test that the event size is correct compared to the existing logic
|
||
|
+ ExistingLogicEventSize = OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath) + FilePathSize;
|
||
|
+ ExistingLogicEventSize += sizeof (TCG_PCR_EVENT_HDR);
|
||
|
+
|
||
|
+ if (EventSize != ExistingLogicEventSize) {
|
||
|
+ UT_LOG_ERROR ("SanitizePeImageEventSize returned an incorrect event size. Expected %u, got %u\n", ExistingLogicEventSize, EventSize);
|
||
|
+ goto Exit;
|
||
|
+ }
|
||
|
+
|
||
|
+ // Test that the event size may not overflow
|
||
|
+ Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize);
|
||
|
+ if (Status != EFI_BAD_BUFFER_SIZE) {
|
||
|
+ UT_LOG_ERROR ("SanitizePeImageEventSize succeded when it was supposed to fail with %r\n", Status);
|
||
|
+ goto Exit;
|
||
|
+ }
|
||
|
+
|
||
|
+ TestStatus = UNIT_TEST_PASSED;
|
||
|
+Exit:
|
||
|
+
|
||
|
+ if (ImageLoadEvent != NULL) {
|
||
|
+ FreePool (ImageLoadEvent);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (TestStatus == UNIT_TEST_ERROR_TEST_FAILED) {
|
||
|
+ DEBUG ((DEBUG_ERROR, "%a: Test failed\n", __func__));
|
||
|
+ } else {
|
||
|
+ DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
|
||
|
+ }
|
||
|
+
|
||
|
+ return TestStatus;
|
||
|
+}
|
||
|
+
|
||
|
// *--------------------------------------------------------------------*
|
||
|
// * Unit Test Code Main Function
|
||
|
// *--------------------------------------------------------------------*
|
||
|
@@ -265,6 +350,7 @@ UefiTestMain (
|
||
|
AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.TcgMeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL);
|
||
|
AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL);
|
||
|
AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL);
|
||
|
+ AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests PE Image and FileSize checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePeImageEventSize, NULL, NULL, NULL);
|
||
|
|
||
|
Status = RunAllTestSuites (Framework);
|
||
|
|
||
|
--
|
||
|
2.41.0
|
||
|
|