SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764

This commit contains the patch files and tests for DxeTpm2MeasureBootLib
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>
This commit is contained in:
Douglas Flick [MSFT] 2024-01-12 02:16:04 +08:00 committed by mergify[bot]
parent 1ddcb9fc6b
commit c7b2794421
4 changed files with 131 additions and 15 deletions

View File

@ -378,7 +378,6 @@ Exit:
@retval EFI_OUT_OF_RESOURCES No enough resource to measure image.
@retval EFI_UNSUPPORTED ImageType is unsupported or PE image is mal-format.
@retval other error value
**/
EFI_STATUS
EFIAPI
@ -405,6 +404,7 @@ Tcg2MeasurePeImage (
Status = EFI_UNSUPPORTED;
ImageLoad = NULL;
EventPtr = NULL;
Tcg2Event = NULL;
Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol;
CcProtocol = MeasureBootProtocols->CcProtocol;
@ -420,18 +420,22 @@ Tcg2MeasurePeImage (
}
FilePathSize = (UINT32)GetDevicePathSize (FilePath);
Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
//
// Determine destination PCR by BootPolicy
//
EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
EventPtr = AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));
// from a malicious GPT disk partition
EventPtr = AllocateZeroPool (EventSize);
if (EventPtr == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Tcg2Event = (EFI_TCG2_EVENT *)EventPtr;
Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);
Tcg2Event->Size = EventSize;
Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);
Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;
ImageLoad = (EFI_IMAGE_LOAD_EVENT *)Tcg2Event->Event;

View File

@ -273,3 +273,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 (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)
Status = SafeUint32Add (*EventSize, OFFSET_OF (EFI_TCG2_EVENT, Event), EventSize);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n"));
return EFI_BAD_BUFFER_SIZE;
}
return EFI_SUCCESS;
}

View File

@ -9,6 +9,9 @@
Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse
partition data carefully.
Tcg2MeasurePeImage() function will accept untrusted PE/COFF image and validate its
data structure within this image buffer before use.
Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@ -110,4 +113,27 @@ SanitizePrimaryHeaderGptEventSize (
OUT UINT32 *EventSize
);
#endif // DXE_TPM2_MEASURE_BOOT_LIB_SANITATION_
/**
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_TPM2_MEASURE_BOOT_LIB_VALIDATION_

View File

@ -72,10 +72,10 @@ TestSanitizeEfiPartitionTableHeader (
PrimaryHeader.Header.Revision = DEFAULT_PRIMARY_TABLE_HEADER_REVISION;
PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER);
PrimaryHeader.MyLBA = 1;
PrimaryHeader.AlternateLBA = 2;
PrimaryHeader.FirstUsableLBA = 3;
PrimaryHeader.LastUsableLBA = 4;
PrimaryHeader.PartitionEntryLBA = 5;
PrimaryHeader.PartitionEntryLBA = 2;
PrimaryHeader.AlternateLBA = 3;
PrimaryHeader.FirstUsableLBA = 4;
PrimaryHeader.LastUsableLBA = 5;
PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES;
PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid
@ -187,11 +187,6 @@ TestSanitizePrimaryHeaderGptEventSize (
EFI_STATUS Status;
EFI_PARTITION_TABLE_HEADER PrimaryHeader;
UINTN NumberOfPartition;
EFI_GPT_DATA *GptData;
EFI_TCG2_EVENT *Tcg2Event;
Tcg2Event = NULL;
GptData = NULL;
// Test that a normal PrimaryHeader passes validation
PrimaryHeader.NumberOfPartitionEntries = 5;
@ -225,6 +220,52 @@ 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 when generating a
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;
FilePathSize = 255;
// Test that a normal PE image passes validation
Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
UT_ASSERT_EQUAL (Status, EFI_SUCCESS);
// Test that the event size is correct compared to the existing logic
ExistingLogicEventSize = OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath) + FilePathSize;
ExistingLogicEventSize += OFFSET_OF (EFI_TCG2_EVENT, Event);
if (EventSize != ExistingLogicEventSize) {
UT_LOG_ERROR ("SanitizePeImageEventSize returned an incorrect event size. Expected %u, got %u\n", ExistingLogicEventSize, EventSize);
return UNIT_TEST_ERROR_TEST_FAILED;
}
// Test that the event size may not overflow
Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize);
UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
return UNIT_TEST_PASSED;
}
// *--------------------------------------------------------------------*
// * Unit Test Code Main Function
// *--------------------------------------------------------------------*
@ -267,6 +308,7 @@ UefiTestMain (
AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.Tcg2MeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL);
AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL);
AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL);
AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests PE Image and FileSize checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePeImageEventSize, NULL, NULL, NULL);
Status = RunAllTestSuites (Framework);