summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2013-04-19 07:34:41 +0000
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2013-04-19 07:34:41 +0000
commitde0eb1d06f9506067006304c00e20a82021c51d8 (patch)
tree4d176b83758e71239ae05027fd06865102be1d40
parentdc9ef7ffb96446e5d78a08ba54e28ddf76ac3156 (diff)
downloadedk2-de0eb1d06f9506067006304c00e20a82021c51d8.zip
edk2-de0eb1d06f9506067006304c00e20a82021c51d8.tar.gz
edk2-de0eb1d06f9506067006304c00e20a82021c51d8.tar.bz2
Sync patches r13470, r13477, r13518, r13545, r13954, r13763 and r14145 from main trunk.
1. MdeModulePkg PI SMM Core: Unregister handler for SMM Ready To Lock event in SmmReadyToLockHandler() at first call so that it won't be invoked again. 2. Add more SMRAM range check to 3 SMI handler. 3. Add SMRAM range check to fault tolerant write SMM SMI handler. 4. Add more security check for CommBuffer+CommBufferSize. 5. Add more exact SMM check in SmmFaultTolerantWriteHandler. 6. In order to make sure the image is section alignment, after allocate buffer for TE image, it will adjust the base address. But it has two potential issues: One is the start address may not section alignment, second is the buffer is not bigger enough to do the adjustment. This patch fixes these two issues. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/branches/UDK2010.SR1@14299 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--MdeModulePkg/Core/Pei/Image/Image.c29
-rw-r--r--MdeModulePkg/Core/PiSmmCore/PiSmmCore.c2
-rw-r--r--MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c61
-rw-r--r--MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c48
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c112
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf3
-rw-r--r--MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c95
7 files changed, 318 insertions, 32 deletions
diff --git a/MdeModulePkg/Core/Pei/Image/Image.c b/MdeModulePkg/Core/Pei/Image/Image.c
index 0906548..b7a8835 100644
--- a/MdeModulePkg/Core/Pei/Image/Image.c
+++ b/MdeModulePkg/Core/Pei/Image/Image.c
@@ -1,7 +1,7 @@
/** @file
Pei Core Load Image Support
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -348,6 +348,7 @@ LoadAndRelocatePeCoffImage (
EFI_STATUS Status;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
PEI_CORE_INSTANCE *Private;
+ UINT64 AlignImageSize;
Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
@@ -377,6 +378,19 @@ LoadAndRelocatePeCoffImage (
// Allocate Memory for the image when memory is ready, boot mode is not S3, and image is relocatable.
//
if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
+ //
+ // Allocate more buffer to avoid buffer overflow.
+ //
+ if (ImageContext.IsTeImage) {
+ AlignImageSize = ImageContext.ImageSize + ((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
+ } else {
+ AlignImageSize = ImageContext.ImageSize;
+ }
+
+ if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
+ AlignImageSize += ImageContext.SectionAlignment;
+ }
+
if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {
Status = GetPeCoffImageFixLoadingAssignedAddress(&ImageContext, Private);
if (EFI_ERROR (Status)){
@@ -384,10 +398,10 @@ LoadAndRelocatePeCoffImage (
//
// The PEIM is not assiged valid address, try to allocate page to load it.
//
- ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) AlignImageSize));
}
} else {
- ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) AlignImageSize));
}
ASSERT (ImageContext.ImageAddress != 0);
if (ImageContext.ImageAddress == 0) {
@@ -395,6 +409,15 @@ LoadAndRelocatePeCoffImage (
}
//
+ // Adjust the Image Address to make sure it is section alignment.
+ //
+ if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
+ ImageContext.ImageAddress =
+ (ImageContext.ImageAddress + ImageContext.SectionAlignment - 1) &
+ ~((UINTN)ImageContext.SectionAlignment - 1);
+ }
+ //
+ // Fix alignment requirement when Load IPF TeImage into memory.
// Skip the reserved space for the stripped PeHeader when load TeImage into memory.
//
if (ImageContext.IsTeImage) {
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
index 23f072f..a7220e4 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
@@ -76,7 +76,7 @@ BOOLEAN mInLegacyBoot = FALSE;
//
SMM_CORE_SMI_HANDLERS mSmmCoreSmiHandlers[] = {
{ SmmDriverDispatchHandler, &gEfiEventDxeDispatchGuid, NULL, TRUE },
- { SmmReadyToLockHandler, &gEfiDxeSmmReadyToLockProtocolGuid, NULL, FALSE },
+ { SmmReadyToLockHandler, &gEfiDxeSmmReadyToLockProtocolGuid, NULL, TRUE },
{ SmmLegacyBootHandler, &gEfiEventLegacyBootGuid, NULL, FALSE },
{ SmmEndOfDxeHandler, &gEfiEndOfDxeEventGroupGuid, NULL, FALSE },
{ NULL, NULL, NULL, FALSE }
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
index 214d044..314d46d 100644
--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
@@ -9,6 +9,13 @@
This library is mainly used by SMM Core to start performance logging to ensure that
SMM Performance and PerformanceEx Protocol are installed at the very beginning of SMM phase.
+ Caution: This module requires additional review when modified.
+ This driver will have external input - performance data and communicate buffer in SMM mode.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ SmmPerformanceHandlerEx(), SmmPerformanceHandler() will receive untrusted input and do basic validation.
+
Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -474,6 +481,9 @@ IsAddressInSmram (
Communication service SMI Handler entry.
This SMI handler provides services for the performance wrapper driver.
+
+ Caution: This function may receive untrusted input.
+ Communicate buffer and buffer size are external input, so this function will do basic validation.
@param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
@param[in] RegisterContext Points to an optional handler context which was specified when the
@@ -506,8 +516,22 @@ SmmPerformanceHandlerEx (
GaugeEntryExArray = NULL;
- ASSERT (CommBuffer != NULL);
+ //
+ // If input is invalid, stop processing this SMI
+ //
+ if (CommBuffer == NULL || CommBufferSize == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ if(*CommBufferSize < sizeof (SMM_PERF_COMMUNICATE_EX)) {
+ return EFI_SUCCESS;
+ }
+ if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer, *CommBufferSize)) {
+ DEBUG ((EFI_D_ERROR, "SMM communcation data buffer is in SMRAM!\n"));
+ return EFI_SUCCESS;
+ }
+
SmmPerfCommData = (SMM_PERF_COMMUNICATE_EX *)CommBuffer;
switch (SmmPerfCommData->Function) {
@@ -528,9 +552,9 @@ SmmPerformanceHandlerEx (
//
DataSize = SmmPerfCommData->NumberOfEntries * sizeof(GAUGE_DATA_ENTRY_EX);
if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)SmmPerfCommData->GaugeDataEx, DataSize)) {
- DEBUG ((EFI_D_ERROR, "Smm Performance Data buffer is in SMRAM!\n"));
+ DEBUG ((EFI_D_ERROR, "SMM Performance Data buffer is in SMRAM!\n"));
Status = EFI_ACCESS_DENIED;
- break ;
+ break;
}
GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
@@ -543,11 +567,12 @@ SmmPerformanceHandlerEx (
break;
default:
- ASSERT (FALSE);
Status = EFI_UNSUPPORTED;
}
+
SmmPerfCommData->ReturnStatus = Status;
+
return EFI_SUCCESS;
}
@@ -556,6 +581,9 @@ SmmPerformanceHandlerEx (
This SMI handler provides services for the performance wrapper driver.
+ Caution: This function may receive untrusted input.
+ Communicate buffer and buffer size are external input, so this function will do basic validation.
+
@param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
@param[in] RegisterContext Points to an optional handler context which was specified when the
handler was registered.
@@ -586,10 +614,24 @@ SmmPerformanceHandler (
UINTN DataSize;
UINTN Index;
UINTN LogEntryKey;
-
+
GaugeEntryExArray = NULL;
- ASSERT (CommBuffer != NULL);
+ //
+ // If input is invalid, stop processing this SMI
+ //
+ if (CommBuffer == NULL || CommBufferSize == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ if(*CommBufferSize < sizeof (SMM_PERF_COMMUNICATE)) {
+ return EFI_SUCCESS;
+ }
+
+ if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer, *CommBufferSize)) {
+ DEBUG ((EFI_D_ERROR, "SMM communcation data buffer is in SMRAM!\n"));
+ return EFI_SUCCESS;
+ }
SmmPerfCommData = (SMM_PERF_COMMUNICATE *)CommBuffer;
@@ -611,9 +653,9 @@ SmmPerformanceHandler (
//
DataSize = SmmPerfCommData->NumberOfEntries * sizeof(GAUGE_DATA_ENTRY);
if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)SmmPerfCommData->GaugeData, DataSize)) {
- DEBUG ((EFI_D_ERROR, "Smm Performance Data buffer is in SMRAM!\n"));
+ DEBUG ((EFI_D_ERROR, "SMM Performance Data buffer is in SMRAM!\n"));
Status = EFI_ACCESS_DENIED;
- break ;
+ break;
}
GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
@@ -630,11 +672,12 @@ SmmPerformanceHandler (
break;
default:
- ASSERT (FALSE);
Status = EFI_UNSUPPORTED;
}
+
SmmPerfCommData->ReturnStatus = Status;
+
return EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c
index 6de22d4..e7a1e59 100644
--- a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c
+++ b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c
@@ -4,6 +4,13 @@
This module registers report status code listener to collect performance data
for SMM driver boot records and S3 Suspend Performance Record.
+ Caution: This module requires additional review when modified.
+ This driver will have external input - communicate buffer in SMM mode.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ FpdtSmiHandler() will receive untrusted input and do basic validation.
+
Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -203,6 +210,9 @@ InternalIsAddressInSmram (
This SMI handler provides services for report SMM boot records.
+ Caution: This function may receive untrusted input.
+ Communicate buffer and buffer size are external input, so this function will do basic validation.
+
@param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
@param[in] RegisterContext Points to an optional handler context which was specified when the
handler was registered.
@@ -210,10 +220,14 @@ InternalIsAddressInSmram (
be conveyed from a non-SMM environment into an SMM environment.
@param[in, out] CommBufferSize The size of the CommBuffer.
- @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers should still be called.
- @retval EFI_INVALID_PARAMETER The interrupt parameter is not valid.
- @retval EFI_ACCESS_DENIED The interrupt buffer can't be written.
- @retval EFI_UNSUPPORTED The interrupt is not supported.
+ @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
+ should still be called.
+ @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
+ still be called.
+ @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
+ be called.
+ @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
+
**/
EFI_STATUS
EFIAPI
@@ -226,15 +240,27 @@ FpdtSmiHandler (
{
EFI_STATUS Status;
SMM_BOOT_RECORD_COMMUNICATE *SmmCommData;
+
+ //
+ // If input is invalid, stop processing this SMI
+ //
+ if (CommBuffer == NULL || CommBufferSize == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ if(*CommBufferSize < sizeof (SMM_BOOT_RECORD_COMMUNICATE)) {
+ return EFI_SUCCESS;
+ }
- ASSERT (CommBuffer != NULL);
- if (CommBuffer == NULL || *CommBufferSize < sizeof (SMM_BOOT_RECORD_COMMUNICATE)) {
- return EFI_INVALID_PARAMETER;
+ if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer, *CommBufferSize)) {
+ DEBUG ((EFI_D_ERROR, "SMM communication data buffer is in SMRAM!\n"));
+ return EFI_SUCCESS;
}
- Status = EFI_SUCCESS;
SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE*)CommBuffer;
+ Status = EFI_SUCCESS;
+
switch (SmmCommData->Function) {
case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE :
SmmCommData->BootRecordSize = mBootRecordSize;
@@ -245,13 +271,13 @@ FpdtSmiHandler (
Status = EFI_INVALID_PARAMETER;
break;
}
-
+
//
// Sanity check
//
SmmCommData->BootRecordSize = mBootRecordSize;
if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)SmmCommData->BootRecordData, mBootRecordSize)) {
- DEBUG ((EFI_D_ERROR, "Smm Data buffer is in SMRAM!\n"));
+ DEBUG ((EFI_D_ERROR, "SMM Data buffer is in SMRAM!\n"));
Status = EFI_ACCESS_DENIED;
break;
}
@@ -264,11 +290,11 @@ FpdtSmiHandler (
break;
default:
- ASSERT (FALSE);
Status = EFI_UNSUPPORTED;
}
SmmCommData->ReturnStatus = Status;
+
return EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c
index 5736ce3..e7d79c1 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c
@@ -40,7 +40,10 @@
If one of them is not satisfied, FtwWrite may fail.
Usually, Spare area only takes one block. That's SpareAreaLength = BlockSize, NumberOfSpareBlock = 1.
-Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+ Caution: This module requires additional review when modified.
+ This driver need to make sure the CommBuffer is not in the SMRAM range.
+
+Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -56,9 +59,41 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/SmmSwapAddressRange.h>
#include "FaultTolerantWrite.h"
#include "FaultTolerantWriteSmmCommon.h"
+#include <Protocol/SmmAccess2.h>
EFI_EVENT mFvbRegistration = NULL;
EFI_FTW_DEVICE *mFtwDevice = NULL;
+EFI_SMRAM_DESCRIPTOR *mSmramRanges;
+UINTN mSmramRangeCount;
+
+
+/**
+ This function check if the address is in SMRAM.
+
+ @param Buffer the buffer address to be checked.
+ @param Length the buffer length to be checked.
+
+ @retval TRUE this address is in SMRAM.
+ @retval FALSE this address is NOT in SMRAM.
+**/
+BOOLEAN
+InternalIsAddressInSmram (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < mSmramRangeCount; Index ++) {
+ if (((Buffer >= mSmramRanges[Index].CpuStart) && (Buffer < mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize)) ||
+ ((mSmramRanges[Index].CpuStart >= Buffer) && (mSmramRanges[Index].CpuStart < Buffer + Length))) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
/**
Retrive the SMM FVB protocol interface by HANDLE.
@@ -263,6 +298,11 @@ GetFvbByAddressAndAttribute (
This SMI handler provides services for the fault tolerant write wrapper driver.
+ Caution: This function requires additional review when modified.
+ This driver need to make sure the CommBuffer is not in the SMRAM range.
+ Also in FTW_FUNCTION_GET_LAST_WRITE case, check SmmFtwGetLastWriteHeader->Data +
+ SmmFtwGetLastWriteHeader->PrivateDataSize within communication buffer.
+
@param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
@param[in] RegisterContext Points to an optional handler context which was specified when the
handler was registered.
@@ -297,14 +337,40 @@ SmmFaultTolerantWriteHandler (
SMM_FTW_GET_LAST_WRITE_HEADER *SmmFtwGetLastWriteHeader;
VOID *PrivateData;
EFI_HANDLE SmmFvbHandle;
+ UINTN InfoSize;
+
+
+ //
+ // If input is invalid, stop processing this SMI
+ //
+ if (CommBuffer == NULL || CommBufferSize == NULL) {
+ return EFI_SUCCESS;
+ }
- ASSERT (CommBuffer != NULL);
- ASSERT (CommBufferSize != NULL);
+ if (*CommBufferSize < SMM_FTW_COMMUNICATE_HEADER_SIZE) {
+ return EFI_SUCCESS;
+ }
+
+ if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer, *CommBufferSize)) {
+ DEBUG ((EFI_D_ERROR, "SMM communication buffer size is in SMRAM!\n"));
+ return EFI_SUCCESS;
+ }
SmmFtwFunctionHeader = (SMM_FTW_COMMUNICATE_FUNCTION_HEADER *)CommBuffer;
switch (SmmFtwFunctionHeader->Function) {
case FTW_FUNCTION_GET_MAX_BLOCK_SIZE:
- SmmGetMaxBlockSizeHeader = (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER *) SmmFtwFunctionHeader->Data;
+ SmmGetMaxBlockSizeHeader = (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER *) SmmFtwFunctionHeader->Data;
+ InfoSize = sizeof (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER);
+
+ //
+ // SMRAM range check already covered before
+ //
+ if (InfoSize > *CommBufferSize - SMM_FTW_COMMUNICATE_HEADER_SIZE) {
+ DEBUG ((EFI_D_ERROR, "Data size exceed communication buffer size limit!\n"));
+ Status = EFI_ACCESS_DENIED;
+ break;
+ }
+
Status = FtwGetMaxBlockSize (
&mFtwDevice->FtwInstance,
&SmmGetMaxBlockSizeHeader->BlockSize
@@ -364,6 +430,17 @@ SmmFaultTolerantWriteHandler (
case FTW_FUNCTION_GET_LAST_WRITE:
SmmFtwGetLastWriteHeader = (SMM_FTW_GET_LAST_WRITE_HEADER *) SmmFtwFunctionHeader->Data;
+ InfoSize = OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data) + SmmFtwGetLastWriteHeader->PrivateDataSize;
+
+ //
+ // SMRAM range check already covered before
+ //
+ if (InfoSize > *CommBufferSize - SMM_FTW_COMMUNICATE_HEADER_SIZE) {
+ DEBUG ((EFI_D_ERROR, "Data size exceed communication buffer size limit!\n"));
+ Status = EFI_ACCESS_DENIED;
+ break;
+ }
+
Status = FtwGetLastWrite (
&mFtwDevice->FtwInstance,
&SmmFtwGetLastWriteHeader->CallerId,
@@ -377,7 +454,6 @@ SmmFaultTolerantWriteHandler (
break;
default:
- ASSERT (FALSE);
Status = EFI_UNSUPPORTED;
}
@@ -477,6 +553,8 @@ SmmFaultTolerantWriteInitialize (
{
EFI_STATUS Status;
EFI_HANDLE FtwHandle;
+ EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;
+ UINTN Size;
//
// Allocate private data structure for SMM FTW protocol and do some initialization
@@ -485,7 +563,29 @@ SmmFaultTolerantWriteInitialize (
if (EFI_ERROR(Status)) {
return Status;
}
-
+
+ //
+ // Get SMRAM information
+ //
+ Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);
+ ASSERT_EFI_ERROR (Status);
+
+ Size = 0;
+ Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ Size,
+ (VOID **)&mSmramRanges
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);
+ ASSERT_EFI_ERROR (Status);
+
+ mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
+
//
// Register FvbNotificationEvent () notify function.
//
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
index 747ce3b..ec33465 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
@@ -4,7 +4,7 @@
# depends on the full functionality SMM FVB protocol that support read, write/erase
# flash access.
#
-# Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -57,6 +57,7 @@
gEfiSmmSwapAddressRangeProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable ## CONSUMES
gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES
gEfiSmmFaultTolerantWriteProtocolGuid ## PRODUCES
+ gEfiSmmAccess2ProtocolGuid ## CONSUMES
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable
diff --git a/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c b/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
index fb7a0a4..e8b831e 100644
--- a/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
+++ b/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
@@ -70,8 +70,39 @@ IsAddressInSmram (
}
/**
+ This function check if the address refered by Buffer and Length is valid.
+
+ @param Buffer the buffer address to be checked.
+ @param Length the buffer length to be checked.
+
+ @retval TRUE this address is valid.
+ @retval FALSE this address is NOT valid.
+**/
+BOOLEAN
+IsAddressValid (
+ IN UINTN Buffer,
+ IN UINTN Length
+ )
+{
+ if (Buffer > (MAX_ADDRESS - Length)) {
+ //
+ // Overflow happen
+ //
+ return FALSE;
+ }
+ if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)Buffer, (UINT64)Length)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
Dispatch function for SMM lock box save.
+ Caution: This function may receive untrusted input.
+ Restore buffer and length are external input, so this function will validate
+ it is in SMRAM.
+
@param LockBoxParameterSave parameter of lock box save
**/
VOID
@@ -91,6 +122,15 @@ SmmLockBoxSave (
}
//
+ // Sanity check
+ //
+ if (!IsAddressValid ((UINTN)LockBoxParameterSave->Buffer, (UINTN)LockBoxParameterSave->Length)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Save address in SMRAM!\n"));
+ LockBoxParameterSave->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
+ return ;
+ }
+
+ //
// Save data
//
Status = SaveLockBox (
@@ -137,6 +177,10 @@ SmmLockBoxSetAttributes (
/**
Dispatch function for SMM lock box update.
+ Caution: This function may receive untrusted input.
+ Restore buffer and length are external input, so this function will validate
+ it is in SMRAM.
+
@param LockBoxParameterUpdate parameter of lock box update
**/
VOID
@@ -156,6 +200,15 @@ SmmLockBoxUpdate (
}
//
+ // Sanity check
+ //
+ if (!IsAddressValid ((UINTN)LockBoxParameterUpdate->Buffer, (UINTN)LockBoxParameterUpdate->Length)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Update address in SMRAM!\n"));
+ LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
+ return ;
+ }
+
+ //
// Update data
//
Status = UpdateLockBox (
@@ -171,6 +224,10 @@ SmmLockBoxUpdate (
/**
Dispatch function for SMM lock box restore.
+ Caution: This function may receive untrusted input.
+ Restore buffer and length are external input, so this function will validate
+ it is in SMRAM.
+
@param LockBoxParameterRestore parameter of lock box restore
**/
VOID
@@ -183,7 +240,7 @@ SmmLockBoxRestore (
//
// Sanity check
//
- if (IsAddressInSmram (LockBoxParameterRestore->Buffer, LockBoxParameterRestore->Length)) {
+ if (!IsAddressValid ((UINTN)LockBoxParameterRestore->Buffer, (UINTN)LockBoxParameterRestore->Length)) {
DEBUG ((EFI_D_ERROR, "SmmLockBox Restore address in SMRAM!\n"));
LockBoxParameterRestore->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
return ;
@@ -229,6 +286,9 @@ SmmLockBoxRestoreAllInPlace (
/**
Dispatch function for a Software SMI handler.
+ Caution: This function may receive untrusted input.
+ Communicate buffer and buffer size are external input, so this function will do basic validation.
+
@param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
@param Context Points to an optional handler context which was specified when the
handler was registered.
@@ -252,6 +312,18 @@ SmmLockBoxHandler (
DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Enter\n"));
+ //
+ // Sanity check
+ //
+ if (*CommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size invalid!\n"));
+ return EFI_SUCCESS;
+ }
+ if (!IsAddressValid ((UINTN)CommBuffer, *CommBufferSize)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer in SMRAM!\n"));
+ return EFI_SUCCESS;
+ }
+
LockBoxParameterHeader = (EFI_SMM_LOCK_BOX_PARAMETER_HEADER *)((UINTN)CommBuffer);
LockBoxParameterHeader->ReturnStatus = (UINT64)-1;
@@ -262,21 +334,42 @@ SmmLockBoxHandler (
switch (LockBoxParameterHeader->Command) {
case EFI_SMM_LOCK_BOX_COMMAND_SAVE:
+ if (*CommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SAVE)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for SAVE invalid!\n"));
+ break;
+ }
SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE *)(UINTN)LockBoxParameterHeader);
break;
case EFI_SMM_LOCK_BOX_COMMAND_UPDATE:
+ if (*CommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_UPDATE)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for UPDATE invalid!\n"));
+ break;
+ }
SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *)(UINTN)LockBoxParameterHeader);
break;
case EFI_SMM_LOCK_BOX_COMMAND_RESTORE:
+ if (*CommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for RESTORE invalid!\n"));
+ break;
+ }
SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)(UINTN)LockBoxParameterHeader);
break;
case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES:
+ if (*CommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for SET_ATTRIBUTES invalid!\n"));
+ break;
+ }
SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *)(UINTN)LockBoxParameterHeader);
break;
case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE:
+ if (*CommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for RESTORE_ALL_IN_PLACE invalid!\n"));
+ break;
+ }
SmmLockBoxRestoreAllInPlace ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)(UINTN)LockBoxParameterHeader);
break;
default:
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Command invalid!\n"));
break;
}