Skip to content

Commit 0d341c0

Browse files
Douglas Flick [MSFT]mergify[bot]
Douglas Flick [MSFT]
authored andcommitted
SecurityPkg: DxeTpmMeasureBootLib: SECURITY PATCH 4118 - CVE 2022-36764
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]>
1 parent c7b2794 commit 0d341c0

File tree

4 files changed

+168
-10
lines changed

4 files changed

+168
-10
lines changed

SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.c

+9-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
1818
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
1919
SPDX-License-Identifier: BSD-2-Clause-Patent
20+
Copyright (c) Microsoft Corporation.<BR>
2021
2122
Copyright (c) Microsoft Corporation.<BR>
2223
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -345,18 +346,22 @@ TcgMeasurePeImage (
345346
ImageLoad = NULL;
346347
SectionHeader = NULL;
347348
Sha1Ctx = NULL;
349+
TcgEvent = NULL;
348350
FilePathSize = (UINT32)GetDevicePathSize (FilePath);
349351

350-
//
351352
// Determine destination PCR by BootPolicy
352353
//
353-
EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
354-
TcgEvent = AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT));
354+
Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
355+
if (EFI_ERROR (Status)) {
356+
return EFI_UNSUPPORTED;
357+
}
358+
359+
TcgEvent = AllocateZeroPool (EventSize);
355360
if (TcgEvent == NULL) {
356361
return EFI_OUT_OF_RESOURCES;
357362
}
358363

359-
TcgEvent->EventSize = EventSize;
364+
TcgEvent->EventSize = EventSize - sizeof (TCG_PCR_EVENT_HDR);
360365
ImageLoad = (EFI_IMAGE_LOAD_EVENT *)TcgEvent->Event;
361366

362367
switch (ImageType) {

SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.c

+44
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,47 @@ SanitizePrimaryHeaderGptEventSize (
239239

240240
return EFI_SUCCESS;
241241
}
242+
243+
/**
244+
This function will validate that the PeImage Event Size from the loaded image is sane
245+
It will check the following:
246+
- EventSize does not overflow
247+
248+
@param[in] FilePathSize - Size of the file path.
249+
@param[out] EventSize - Pointer to the event size.
250+
251+
@retval EFI_SUCCESS
252+
The event size is valid.
253+
254+
@retval EFI_OUT_OF_RESOURCES
255+
Overflow would have occurred.
256+
257+
@retval EFI_INVALID_PARAMETER
258+
One of the passed parameters was invalid.
259+
**/
260+
EFI_STATUS
261+
SanitizePeImageEventSize (
262+
IN UINT32 FilePathSize,
263+
OUT UINT32 *EventSize
264+
)
265+
{
266+
EFI_STATUS Status;
267+
268+
// Replacing logic:
269+
// sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
270+
Status = SafeUint32Add (OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath), FilePathSize, EventSize);
271+
if (EFI_ERROR (Status)) {
272+
DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n"));
273+
return EFI_BAD_BUFFER_SIZE;
274+
}
275+
276+
// Replacing logic:
277+
// EventSize + sizeof (TCG_PCR_EVENT_HDR)
278+
Status = SafeUint32Add (*EventSize, sizeof (TCG_PCR_EVENT_HDR), EventSize);
279+
if (EFI_ERROR (Status)) {
280+
DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n"));
281+
return EFI_BAD_BUFFER_SIZE;
282+
}
283+
284+
return EFI_SUCCESS;
285+
}

SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLibSanitization.h

+23
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,27 @@ SanitizePrimaryHeaderGptEventSize (
111111
OUT UINT32 *EventSize
112112
);
113113

114+
/**
115+
This function will validate that the PeImage Event Size from the loaded image is sane
116+
It will check the following:
117+
- EventSize does not overflow
118+
119+
@param[in] FilePathSize - Size of the file path.
120+
@param[out] EventSize - Pointer to the event size.
121+
122+
@retval EFI_SUCCESS
123+
The event size is valid.
124+
125+
@retval EFI_OUT_OF_RESOURCES
126+
Overflow would have occurred.
127+
128+
@retval EFI_INVALID_PARAMETER
129+
One of the passed parameters was invalid.
130+
**/
131+
EFI_STATUS
132+
SanitizePeImageEventSize (
133+
IN UINT32 FilePathSize,
134+
OUT UINT32 *EventSize
135+
);
136+
114137
#endif // DXE_TPM_MEASURE_BOOT_LIB_VALIDATION_

SecurityPkg/Library/DxeTpmMeasureBootLib/InternalUnitTest/DxeTpmMeasureBootLibSanitizationTest.c

+92-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/** @file
2-
This file includes the unit test cases for the DxeTpmMeasureBootLibSanitizationTest.c.
2+
This file includes the unit test cases for the DxeTpmMeasureBootLibSanitizationTest.c.
33
4-
Copyright (c) Microsoft Corporation.<BR>
5-
SPDX-License-Identifier: BSD-2-Clause-Patent
4+
Copyright (c) Microsoft Corporation.<BR>
5+
SPDX-License-Identifier: BSD-2-Clause-Patent
66
**/
77

88
#include <Uefi.h>
@@ -186,9 +186,6 @@ TestSanitizePrimaryHeaderGptEventSize (
186186
EFI_STATUS Status;
187187
EFI_PARTITION_TABLE_HEADER PrimaryHeader;
188188
UINTN NumberOfPartition;
189-
EFI_GPT_DATA *GptData;
190-
191-
GptData = NULL;
192189

193190
// Test that a normal PrimaryHeader passes validation
194191
PrimaryHeader.NumberOfPartitionEntries = 5;
@@ -222,6 +219,94 @@ TestSanitizePrimaryHeaderGptEventSize (
222219
return UNIT_TEST_PASSED;
223220
}
224221

222+
/**
223+
This function tests the SanitizePeImageEventSize function.
224+
It's intent is to test that the untrusted input from a file path for an
225+
EFI_IMAGE_LOAD_EVENT structure will not cause an overflow when calculating
226+
the event size when allocating space.
227+
228+
@param[in] Context The unit test context.
229+
230+
@retval UNIT_TEST_PASSED The test passed.
231+
@retval UNIT_TEST_ERROR_TEST_FAILED The test failed.
232+
**/
233+
UNIT_TEST_STATUS
234+
EFIAPI
235+
TestSanitizePeImageEventSize (
236+
IN UNIT_TEST_CONTEXT Context
237+
)
238+
{
239+
UINT32 EventSize;
240+
UINTN ExistingLogicEventSize;
241+
UINT32 FilePathSize;
242+
EFI_STATUS Status;
243+
EFI_DEVICE_PATH_PROTOCOL DevicePath;
244+
EFI_IMAGE_LOAD_EVENT *ImageLoadEvent;
245+
UNIT_TEST_STATUS TestStatus;
246+
247+
TestStatus = UNIT_TEST_ERROR_TEST_FAILED;
248+
249+
// Generate EFI_DEVICE_PATH_PROTOCOL test data
250+
DevicePath.Type = 0;
251+
DevicePath.SubType = 0;
252+
DevicePath.Length[0] = 0;
253+
DevicePath.Length[1] = 0;
254+
255+
// Generate EFI_IMAGE_LOAD_EVENT test data
256+
ImageLoadEvent = AllocateZeroPool (sizeof (EFI_IMAGE_LOAD_EVENT) + sizeof (EFI_DEVICE_PATH_PROTOCOL));
257+
if (ImageLoadEvent == NULL) {
258+
DEBUG ((DEBUG_ERROR, "%a: AllocateZeroPool failed\n", __func__));
259+
goto Exit;
260+
}
261+
262+
// Populate EFI_IMAGE_LOAD_EVENT54 test data
263+
ImageLoadEvent->ImageLocationInMemory = (EFI_PHYSICAL_ADDRESS)0x12345678;
264+
ImageLoadEvent->ImageLengthInMemory = 0x1000;
265+
ImageLoadEvent->ImageLinkTimeAddress = (UINTN)ImageLoadEvent;
266+
ImageLoadEvent->LengthOfDevicePath = sizeof (EFI_DEVICE_PATH_PROTOCOL);
267+
CopyMem (ImageLoadEvent->DevicePath, &DevicePath, sizeof (EFI_DEVICE_PATH_PROTOCOL));
268+
269+
FilePathSize = 255;
270+
271+
// Test that a normal PE image passes validation
272+
Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
273+
if (EFI_ERROR (Status)) {
274+
UT_LOG_ERROR ("SanitizePeImageEventSize failed with %r\n", Status);
275+
goto Exit;
276+
}
277+
278+
// Test that the event size is correct compared to the existing logic
279+
ExistingLogicEventSize = OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath) + FilePathSize;
280+
ExistingLogicEventSize += sizeof (TCG_PCR_EVENT_HDR);
281+
282+
if (EventSize != ExistingLogicEventSize) {
283+
UT_LOG_ERROR ("SanitizePeImageEventSize returned an incorrect event size. Expected %u, got %u\n", ExistingLogicEventSize, EventSize);
284+
goto Exit;
285+
}
286+
287+
// Test that the event size may not overflow
288+
Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize);
289+
if (Status != EFI_BAD_BUFFER_SIZE) {
290+
UT_LOG_ERROR ("SanitizePeImageEventSize succeded when it was supposed to fail with %r\n", Status);
291+
goto Exit;
292+
}
293+
294+
TestStatus = UNIT_TEST_PASSED;
295+
Exit:
296+
297+
if (ImageLoadEvent != NULL) {
298+
FreePool (ImageLoadEvent);
299+
}
300+
301+
if (TestStatus == UNIT_TEST_ERROR_TEST_FAILED) {
302+
DEBUG ((DEBUG_ERROR, "%a: Test failed\n", __func__));
303+
} else {
304+
DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
305+
}
306+
307+
return TestStatus;
308+
}
309+
225310
// *--------------------------------------------------------------------*
226311
// * Unit Test Code Main Function
227312
// *--------------------------------------------------------------------*
@@ -265,6 +350,7 @@ UefiTestMain (
265350
AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.TcgMeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL);
266351
AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL);
267352
AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL);
353+
AddTestCase (TcgMeasureBootLibValidationTestSuite, "Tests PE Image and FileSize checks for overflow", "Common.TcgMeasureBootLibValidation", TestSanitizePeImageEventSize, NULL, NULL, NULL);
268354

269355
Status = RunAllTestSuites (Framework);
270356

0 commit comments

Comments
 (0)