Skip to content

Commit c7b2794

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

File tree

4 files changed

+131
-15
lines changed

4 files changed

+131
-15
lines changed

SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.c

+8-4
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,6 @@ Tcg2MeasureGptTable (
378378
@retval EFI_OUT_OF_RESOURCES No enough resource to measure image.
379379
@retval EFI_UNSUPPORTED ImageType is unsupported or PE image is mal-format.
380380
@retval other error value
381-
382381
**/
383382
EFI_STATUS
384383
EFIAPI
@@ -405,6 +404,7 @@ Tcg2MeasurePeImage (
405404
Status = EFI_UNSUPPORTED;
406405
ImageLoad = NULL;
407406
EventPtr = NULL;
407+
Tcg2Event = NULL;
408408

409409
Tcg2Protocol = MeasureBootProtocols->Tcg2Protocol;
410410
CcProtocol = MeasureBootProtocols->CcProtocol;
@@ -420,18 +420,22 @@ Tcg2MeasurePeImage (
420420
}
421421

422422
FilePathSize = (UINT32)GetDevicePathSize (FilePath);
423+
Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
424+
if (EFI_ERROR (Status)) {
425+
return EFI_UNSUPPORTED;
426+
}
423427

424428
//
425429
// Determine destination PCR by BootPolicy
426430
//
427-
EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
428-
EventPtr = AllocateZeroPool (EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event));
431+
// from a malicious GPT disk partition
432+
EventPtr = AllocateZeroPool (EventSize);
429433
if (EventPtr == NULL) {
430434
return EFI_OUT_OF_RESOURCES;
431435
}
432436

433437
Tcg2Event = (EFI_TCG2_EVENT *)EventPtr;
434-
Tcg2Event->Size = EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);
438+
Tcg2Event->Size = EventSize;
435439
Tcg2Event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);
436440
Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;
437441
ImageLoad = (EFI_IMAGE_LOAD_EVENT *)Tcg2Event->Event;

SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.c

+45-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ SanitizeEfiPartitionTableHeader (
151151
}
152152

153153
/**
154-
This function will validate that the allocation size from the primary header is sane
154+
This function will validate that the allocation size from the primary header is sane
155155
It will check the following:
156156
- AllocationSize does not overflow
157157
@@ -273,3 +273,47 @@ SanitizePrimaryHeaderGptEventSize (
273273

274274
return EFI_SUCCESS;
275275
}
276+
277+
/**
278+
This function will validate that the PeImage Event Size from the loaded image is sane
279+
It will check the following:
280+
- EventSize does not overflow
281+
282+
@param[in] FilePathSize - Size of the file path.
283+
@param[out] EventSize - Pointer to the event size.
284+
285+
@retval EFI_SUCCESS
286+
The event size is valid.
287+
288+
@retval EFI_OUT_OF_RESOURCES
289+
Overflow would have occurred.
290+
291+
@retval EFI_INVALID_PARAMETER
292+
One of the passed parameters was invalid.
293+
**/
294+
EFI_STATUS
295+
SanitizePeImageEventSize (
296+
IN UINT32 FilePathSize,
297+
OUT UINT32 *EventSize
298+
)
299+
{
300+
EFI_STATUS Status;
301+
302+
// Replacing logic:
303+
// sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize;
304+
Status = SafeUint32Add (OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath), FilePathSize, EventSize);
305+
if (EFI_ERROR (Status)) {
306+
DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n"));
307+
return EFI_BAD_BUFFER_SIZE;
308+
}
309+
310+
// Replacing logic:
311+
// EventSize + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event)
312+
Status = SafeUint32Add (*EventSize, OFFSET_OF (EFI_TCG2_EVENT, Event), EventSize);
313+
if (EFI_ERROR (Status)) {
314+
DEBUG ((DEBUG_ERROR, "EventSize would overflow!\n"));
315+
return EFI_BAD_BUFFER_SIZE;
316+
}
317+
318+
return EFI_SUCCESS;
319+
}

SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLibSanitization.h

+27-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
Tcg2MeasureGptTable() function will receive untrusted GPT partition table, and parse
1010
partition data carefully.
1111
12+
Tcg2MeasurePeImage() function will accept untrusted PE/COFF image and validate its
13+
data structure within this image buffer before use.
14+
1215
Copyright (c) Microsoft Corporation.<BR>
1316
SPDX-License-Identifier: BSD-2-Clause-Patent
1417
@@ -110,4 +113,27 @@ SanitizePrimaryHeaderGptEventSize (
110113
OUT UINT32 *EventSize
111114
);
112115

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

SecurityPkg/Library/DxeTpm2MeasureBootLib/InternalUnitTest/DxeTpm2MeasureBootLibSanitizationTest.c

+51-9
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ TestSanitizeEfiPartitionTableHeader (
7272
PrimaryHeader.Header.Revision = DEFAULT_PRIMARY_TABLE_HEADER_REVISION;
7373
PrimaryHeader.Header.HeaderSize = sizeof (EFI_PARTITION_TABLE_HEADER);
7474
PrimaryHeader.MyLBA = 1;
75-
PrimaryHeader.AlternateLBA = 2;
76-
PrimaryHeader.FirstUsableLBA = 3;
77-
PrimaryHeader.LastUsableLBA = 4;
78-
PrimaryHeader.PartitionEntryLBA = 5;
75+
PrimaryHeader.PartitionEntryLBA = 2;
76+
PrimaryHeader.AlternateLBA = 3;
77+
PrimaryHeader.FirstUsableLBA = 4;
78+
PrimaryHeader.LastUsableLBA = 5;
7979
PrimaryHeader.NumberOfPartitionEntries = DEFAULT_PRIMARY_TABLE_HEADER_NUMBER_OF_PARTITION_ENTRIES;
8080
PrimaryHeader.SizeOfPartitionEntry = DEFAULT_PRIMARY_TABLE_HEADER_SIZE_OF_PARTITION_ENTRY;
8181
PrimaryHeader.PartitionEntryArrayCRC32 = 0; // Purposely invalid
@@ -187,11 +187,6 @@ TestSanitizePrimaryHeaderGptEventSize (
187187
EFI_STATUS Status;
188188
EFI_PARTITION_TABLE_HEADER PrimaryHeader;
189189
UINTN NumberOfPartition;
190-
EFI_GPT_DATA *GptData;
191-
EFI_TCG2_EVENT *Tcg2Event;
192-
193-
Tcg2Event = NULL;
194-
GptData = NULL;
195190

196191
// Test that a normal PrimaryHeader passes validation
197192
PrimaryHeader.NumberOfPartitionEntries = 5;
@@ -225,6 +220,52 @@ TestSanitizePrimaryHeaderGptEventSize (
225220
return UNIT_TEST_PASSED;
226221
}
227222

223+
/**
224+
This function tests the SanitizePeImageEventSize function.
225+
It's intent is to test that the untrusted input from a file path when generating a
226+
EFI_IMAGE_LOAD_EVENT structure will not cause an overflow when calculating
227+
the event size when allocating space
228+
229+
@param[in] Context The unit test context.
230+
231+
@retval UNIT_TEST_PASSED The test passed.
232+
@retval UNIT_TEST_ERROR_TEST_FAILED The test failed.
233+
**/
234+
UNIT_TEST_STATUS
235+
EFIAPI
236+
TestSanitizePeImageEventSize (
237+
IN UNIT_TEST_CONTEXT Context
238+
)
239+
{
240+
UINT32 EventSize;
241+
UINTN ExistingLogicEventSize;
242+
UINT32 FilePathSize;
243+
EFI_STATUS Status;
244+
245+
FilePathSize = 255;
246+
247+
// Test that a normal PE image passes validation
248+
Status = SanitizePeImageEventSize (FilePathSize, &EventSize);
249+
UT_ASSERT_EQUAL (Status, EFI_SUCCESS);
250+
251+
// Test that the event size is correct compared to the existing logic
252+
ExistingLogicEventSize = OFFSET_OF (EFI_IMAGE_LOAD_EVENT, DevicePath) + FilePathSize;
253+
ExistingLogicEventSize += OFFSET_OF (EFI_TCG2_EVENT, Event);
254+
255+
if (EventSize != ExistingLogicEventSize) {
256+
UT_LOG_ERROR ("SanitizePeImageEventSize returned an incorrect event size. Expected %u, got %u\n", ExistingLogicEventSize, EventSize);
257+
return UNIT_TEST_ERROR_TEST_FAILED;
258+
}
259+
260+
// Test that the event size may not overflow
261+
Status = SanitizePeImageEventSize (MAX_UINT32, &EventSize);
262+
UT_ASSERT_EQUAL (Status, EFI_BAD_BUFFER_SIZE);
263+
264+
DEBUG ((DEBUG_INFO, "%a: Test passed\n", __func__));
265+
266+
return UNIT_TEST_PASSED;
267+
}
268+
228269
// *--------------------------------------------------------------------*
229270
// * Unit Test Code Main Function
230271
// *--------------------------------------------------------------------*
@@ -267,6 +308,7 @@ UefiTestMain (
267308
AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Validating EFI Partition Table", "Common.Tcg2MeasureBootLibValidation", TestSanitizeEfiPartitionTableHeader, NULL, NULL, NULL);
268309
AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header gpt event checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderAllocationSize, NULL, NULL, NULL);
269310
AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests Primary header allocation size checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePrimaryHeaderGptEventSize, NULL, NULL, NULL);
311+
AddTestCase (Tcg2MeasureBootLibValidationTestSuite, "Tests PE Image and FileSize checks for overflow", "Common.Tcg2MeasureBootLibValidation", TestSanitizePeImageEventSize, NULL, NULL, NULL);
270312

271313
Status = RunAllTestSuites (Framework);
272314

0 commit comments

Comments
 (0)