Skip to content

Commit cab1f02

Browse files
miki-intel-workmergify[bot]
authored andcommitted
MdeModulePkg/PiSmmCore: SmmEntryPoint underflow (CVE-2021-38578)
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3387 Added use of SafeIntLib to validate values are not causing overflows or underflows in user controlled values when calculating buffer sizes. Signed-off-by: Miki Demeter <[email protected]> Reviewed-by: Michael D Kinney <[email protected]> Cc: Jian J Wang <[email protected]> Cc: Liming Gao <[email protected]> Reviewed-by: Liming Gao <[email protected]>
1 parent c46204e commit cab1f02

File tree

5 files changed

+60
-15
lines changed

5 files changed

+60
-15
lines changed

MdeModulePkg/Core/PiSmmCore/PiSmmCore.c

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ SmmEndOfS3ResumeHandler (
610610
@param[in] Size2 Size of Buff2
611611
612612
@retval TRUE Buffers overlap in memory.
613+
@retval TRUE Math error. Prevents potential math over and underflows.
613614
@retval FALSE Buffer doesn't overlap.
614615
615616
**/
@@ -621,11 +622,24 @@ InternalIsBufferOverlapped (
621622
IN UINTN Size2
622623
)
623624
{
625+
UINTN End1;
626+
UINTN End2;
627+
BOOLEAN IsOverUnderflow1;
628+
BOOLEAN IsOverUnderflow2;
629+
630+
// Check for over or underflow
631+
IsOverUnderflow1 = EFI_ERROR (SafeUintnAdd ((UINTN)Buff1, Size1, &End1));
632+
IsOverUnderflow2 = EFI_ERROR (SafeUintnAdd ((UINTN)Buff2, Size2, &End2));
633+
634+
if (IsOverUnderflow1 || IsOverUnderflow2) {
635+
return TRUE;
636+
}
637+
624638
//
625639
// If buff1's end is less than the start of buff2, then it's ok.
626640
// Also, if buff1's start is beyond buff2's end, then it's ok.
627641
//
628-
if (((Buff1 + Size1) <= Buff2) || (Buff1 >= (Buff2 + Size2))) {
642+
if ((End1 <= (UINTN)Buff2) || ((UINTN)Buff1 >= End2)) {
629643
return FALSE;
630644
}
631645

@@ -651,6 +665,7 @@ SmmEntryPoint (
651665
EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;
652666
BOOLEAN InLegacyBoot;
653667
BOOLEAN IsOverlapped;
668+
BOOLEAN IsOverUnderflow;
654669
VOID *CommunicationBuffer;
655670
UINTN BufferSize;
656671

@@ -699,23 +714,31 @@ SmmEntryPoint (
699714
(UINT8 *)gSmmCorePrivate,
700715
sizeof (*gSmmCorePrivate)
701716
);
702-
if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicationBuffer, BufferSize) || IsOverlapped) {
717+
//
718+
// Check for over or underflows
719+
//
720+
IsOverUnderflow = EFI_ERROR (SafeUintnSub (BufferSize, OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data), &BufferSize));
721+
722+
if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicationBuffer, BufferSize) ||
723+
IsOverlapped || IsOverUnderflow)
724+
{
703725
//
704726
// If CommunicationBuffer is not in valid address scope,
705727
// or there is overlap between gSmmCorePrivate and CommunicationBuffer,
728+
// or there is over or underflow,
706729
// return EFI_INVALID_PARAMETER
707730
//
708731
gSmmCorePrivate->CommunicationBuffer = NULL;
709732
gSmmCorePrivate->ReturnStatus = EFI_ACCESS_DENIED;
710733
} else {
711734
CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommunicationBuffer;
712-
BufferSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
713-
Status = SmiManage (
714-
&CommunicateHeader->HeaderGuid,
715-
NULL,
716-
CommunicateHeader->Data,
717-
&BufferSize
718-
);
735+
// BufferSize was updated by the SafeUintnSub() call above.
736+
Status = SmiManage (
737+
&CommunicateHeader->HeaderGuid,
738+
NULL,
739+
CommunicateHeader->Data,
740+
&BufferSize
741+
);
719742
//
720743
// Update CommunicationBuffer, BufferSize and ReturnStatus
721744
// Communicate service finished, reset the pointer to CommBuffer to NULL

MdeModulePkg/Core/PiSmmCore/PiSmmCore.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include <Library/PerformanceLib.h>
5555
#include <Library/HobLib.h>
5656
#include <Library/SmmMemLib.h>
57+
#include <Library/SafeIntLib.h>
5758

5859
#include "PiSmmCorePrivateData.h"
5960
#include "HeapGuard.h"

MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
PerformanceLib
6161
HobLib
6262
SmmMemLib
63+
SafeIntLib
6364

6465
[Protocols]
6566
gEfiDxeSmmReadyToLockProtocolGuid ## UNDEFINED # SmiHandlerRegister

MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
#include <Library/UefiRuntimeLib.h>
3535
#include <Library/PcdLib.h>
3636
#include <Library/ReportStatusCodeLib.h>
37-
3837
#include "PiSmmCorePrivateData.h"
38+
#include <Library/SafeIntLib.h>
3939

4040
#define SMRAM_CAPABILITIES (EFI_MEMORY_WB | EFI_MEMORY_UC)
4141

@@ -1354,6 +1354,7 @@ SmmSplitSmramEntry (
13541354
@param[in] ReservedRangeToCompare Pointer to EFI_SMM_RESERVED_SMRAM_REGION to compare.
13551355
13561356
@retval TRUE There is overlap.
1357+
@retval TRUE Math error.
13571358
@retval FALSE There is no overlap.
13581359
13591360
**/
@@ -1363,11 +1364,29 @@ SmmIsSmramOverlap (
13631364
IN EFI_SMM_RESERVED_SMRAM_REGION *ReservedRangeToCompare
13641365
)
13651366
{
1366-
UINT64 RangeToCompareEnd;
1367-
UINT64 ReservedRangeToCompareEnd;
1368-
1369-
RangeToCompareEnd = RangeToCompare->CpuStart + RangeToCompare->PhysicalSize;
1370-
ReservedRangeToCompareEnd = ReservedRangeToCompare->SmramReservedStart + ReservedRangeToCompare->SmramReservedSize;
1367+
UINT64 RangeToCompareEnd;
1368+
UINT64 ReservedRangeToCompareEnd;
1369+
BOOLEAN IsOverUnderflow1;
1370+
BOOLEAN IsOverUnderflow2;
1371+
1372+
// Check for over or underflow.
1373+
IsOverUnderflow1 = EFI_ERROR (
1374+
SafeUint64Add (
1375+
(UINT64)RangeToCompare->CpuStart,
1376+
RangeToCompare->PhysicalSize,
1377+
&RangeToCompareEnd
1378+
)
1379+
);
1380+
IsOverUnderflow2 = EFI_ERROR (
1381+
SafeUint64Add (
1382+
(UINT64)ReservedRangeToCompare->SmramReservedStart,
1383+
ReservedRangeToCompare->SmramReservedSize,
1384+
&ReservedRangeToCompareEnd
1385+
)
1386+
);
1387+
if (IsOverUnderflow1 || IsOverUnderflow2) {
1388+
return TRUE;
1389+
}
13711390

13721391
if ((RangeToCompare->CpuStart >= ReservedRangeToCompare->SmramReservedStart) &&
13731392
(RangeToCompare->CpuStart < ReservedRangeToCompareEnd))

MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
DxeServicesLib
4747
PcdLib
4848
ReportStatusCodeLib
49+
SafeIntLib
4950

5051
[Protocols]
5152
gEfiSmmBase2ProtocolGuid ## PRODUCES

0 commit comments

Comments
 (0)