Skip to content

Commit

Permalink
SecurityPkg: DxeTpmMeasureBootLib: 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 DxeTpmMeasureBootLib
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 c7b2794 commit 0d341c0
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 10 deletions.
13 changes: 9 additions & 4 deletions SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -345,18 +346,22 @@ TcgMeasurePeImage (
ImageLoad = NULL;
SectionHeader = NULL;
Sha1Ctx = NULL;
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;
TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR);
ImageLoad = (EFI_IMAGE_LOAD_EVENT *)TcgEvent->Event;

switch (ImageType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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_
Original file line number Diff line number Diff line change
@@ -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>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
// *--------------------------------------------------------------------*
Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit 0d341c0

Please sign in to comment.