Skip to content

Commit

Permalink
SecurityPkg: DxeTpm2MeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764
Browse files Browse the repository at this point in the history
This commit contains the patch files and tests for DxeTpm2MeasureBootLib
CVE 2022-36764.

Cc: Jiewen Yao <[email protected]>

Signed-off-by: Doug Flick [MSFT] <[email protected]>
Reviewed-by: Jiewen Yao <[email protected]>
  • Loading branch information
Douglas Flick [MSFT] authored and mergify[bot] committed Jan 16, 2024
1 parent 1ddcb9f commit c7b2794
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,6 @@ Tcg2MeasureGptTable (
@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
Expand All @@ -405,6 +404,7 @@ Tcg2MeasurePeImage (
Status = EFI_UNSUPPORTED;
ImageLoad = NULL;
EventPtr = NULL;
Tcg2Event = NULL;

Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol;
CcProtocol = MeasureBootProtocols->CcProtocol;
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ SanitizeEfiPartitionTableHeader (
}

/**
This function will validate that the allocation size from the primary header is sane
This function will validate that the allocation size from the primary header is sane
It will check the following:
- AllocationSize does not overflow
Expand Down Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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_
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
// *--------------------------------------------------------------------*
Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit c7b2794

Please sign in to comment.