From 3720ee6d32219fd67d391f53f2cb812dc197a86b Mon Sep 17 00:00:00 2001 From: Jeff Fan Date: Tue, 9 Dec 2014 02:20:16 +0000 Subject: [PATCH] Checking if gSmmCorePrivate->CommunicationBuffer is in supported physical address scope. If CommunicationBuffer is not in valid address scope, return EFI_INVALID_PARAMETER. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan Reviewed-by: Michael D Kinney Reviewed-by: Jiewen Yao git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16486 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Core/PiSmmCore/PiSmmCore.c | 119 +++++++++++++++++++--- MdeModulePkg/Core/PiSmmCore/PiSmmCore.h | 1 + MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf | 1 + 3 files changed, 105 insertions(+), 16 deletions(-) diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c index 3222a92a79..d8790241e3 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c @@ -85,6 +85,11 @@ SMM_CORE_SMI_HANDLERS mSmmCoreSmiHandlers[] = { UINTN mFullSmramRangeCount; EFI_SMRAM_DESCRIPTOR *mFullSmramRanges; +// +// Maximum support address used to check input CommunicationBuffer +// +UINTN mMaximumSupportAddress = 0; + /** Place holder function until all the SMM System Table Service are available. @@ -274,6 +279,76 @@ SmmEndOfDxeHandler ( return Status; } +/** + Caculate and save the maximum support address. + +**/ +VOID +CaculateMaximumSupportAddress ( + VOID + ) +{ + VOID *Hob; + UINT32 RegEax; + UINT8 PhysicalAddressBits; + + // + // Get physical address bits supported. + // + Hob = GetFirstHob (EFI_HOB_TYPE_CPU); + if (Hob != NULL) { + PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace; + } else { + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000008) { + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); + PhysicalAddressBits = (UINT8) RegEax; + } else { + PhysicalAddressBits = 36; + } + } + // + // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses. + // + ASSERT (PhysicalAddressBits <= 52); + if (PhysicalAddressBits > 48) { + PhysicalAddressBits = 48; + } + + // + // Save the maximum support address in one global variable + // + mMaximumSupportAddress = (UINTN) (LShiftU64 (1, PhysicalAddressBits) - 1); + DEBUG ((EFI_D_INFO, "mMaximumSupportAddress = 0x%lx\n", mMaximumSupportAddress)); +} + +/** + Check if input buffer is in valid address scope or not. + + @param[in] Pointer Pointer to the input buffer. + @param[in] BufferSize Input buffer size in bytes. + + @retval TRUE The input buffer is in valid address scope. + @retval FALSE The input buffer is not in valid address scope. + +**/ +BOOLEAN +IsValidPointer ( + IN VOID *Pointer, + IN UINTN BufferSize + ) +{ + if ((UINTN) Pointer > mMaximumSupportAddress) { + return FALSE; + } + + if (BufferSize > (mMaximumSupportAddress - (UINTN) Pointer)) { + return FALSE; + } + + return TRUE; +} + /** The main entry point to SMM Foundation. @@ -323,22 +398,29 @@ SmmEntryPoint ( // // Synchronous SMI for SMM Core or request from Communicate protocol // - CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)gSmmCorePrivate->CommunicationBuffer; - gSmmCorePrivate->BufferSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data); - Status = SmiManage ( - &CommunicateHeader->HeaderGuid, - NULL, - CommunicateHeader->Data, - &gSmmCorePrivate->BufferSize - ); - - // - // Update CommunicationBuffer, BufferSize and ReturnStatus - // Communicate service finished, reset the pointer to CommBuffer to NULL - // - gSmmCorePrivate->BufferSize += OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data); - gSmmCorePrivate->CommunicationBuffer = NULL; - gSmmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND; + if (!IsValidPointer (gSmmCorePrivate->CommunicationBuffer, gSmmCorePrivate->BufferSize)) { + // + // If CommunicationBuffer is not in valid address scope, return EFI_INVALID_PARAMETER + // + gSmmCorePrivate->CommunicationBuffer = NULL; + gSmmCorePrivate->ReturnStatus = EFI_INVALID_PARAMETER; + } else { + CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)gSmmCorePrivate->CommunicationBuffer; + gSmmCorePrivate->BufferSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data); + Status = SmiManage ( + &CommunicateHeader->HeaderGuid, + NULL, + CommunicateHeader->Data, + &gSmmCorePrivate->BufferSize + ); + // + // Update CommunicationBuffer, BufferSize and ReturnStatus + // Communicate service finished, reset the pointer to CommBuffer to NULL + // + gSmmCorePrivate->BufferSize += OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data); + gSmmCorePrivate->CommunicationBuffer = NULL; + gSmmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND; + } } } @@ -430,5 +512,10 @@ SmmMain ( RegisterSmramProfileHandler (); + // + // Caculate and save maximum support address used in SmmEntryPoint(). + // + CaculateMaximumSupportAddress (); + return EFI_SUCCESS; } diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h index d494519d2c..34bd6411d6 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.h @@ -50,6 +50,7 @@ #include #include #include +#include #include "PiSmmCorePrivateData.h" diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf index 0c8e690846..bf030d60e7 100644 --- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf +++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf @@ -59,6 +59,7 @@ SmmCorePlatformHookLib PerformanceLib TimerLib + HobLib [Protocols] gEfiDxeSmmReadyToLockProtocolGuid ## UNDEFINED # SmiHandlerRegister