Security enhancement to SMM Base thunk drivers: Framework SMM drivers can't be loaded after SMRAM is locked.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10316 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
rsun3
2010-03-26 08:41:06 +00:00
parent 123e0cacd0
commit 8edfbe027c
4 changed files with 104 additions and 9 deletions

View File

@ -32,6 +32,7 @@
#include <Protocol/SmmCpuSaveState.h> #include <Protocol/SmmCpuSaveState.h>
#include <Protocol/MpService.h> #include <Protocol/MpService.h>
#include <Protocol/LoadPe32Image.h> #include <Protocol/LoadPe32Image.h>
#include <Protocol/SmmReadyToLock.h>
/// ///
/// Structure for tracking paired information of registered Framework SMI handler /// Structure for tracking paired information of registered Framework SMI handler
@ -67,6 +68,7 @@ EFI_GUID mEfiSmmCpuIoGuid = EFI_SMM_CPU_IO_GUID;
EFI_SMM_BASE_HELPER_READY_PROTOCOL *mSmmBaseHelperReady; EFI_SMM_BASE_HELPER_READY_PROTOCOL *mSmmBaseHelperReady;
EFI_SMM_SYSTEM_TABLE *mFrameworkSmst; EFI_SMM_SYSTEM_TABLE *mFrameworkSmst;
UINTN mNumberOfProcessors; UINTN mNumberOfProcessors;
BOOLEAN mLocked = FALSE;
LIST_ENTRY mCallbackInfoListHead = INITIALIZE_LIST_HEAD_VARIABLE (mCallbackInfoListHead); LIST_ENTRY mCallbackInfoListHead = INITIALIZE_LIST_HEAD_VARIABLE (mCallbackInfoListHead);
@ -272,7 +274,7 @@ Register (
{ {
EFI_STATUS Status; EFI_STATUS Status;
if (FunctionData->Args.Register.LegacyIA32Binary) { if (mLocked || FunctionData->Args.Register.LegacyIA32Binary) {
Status = EFI_UNSUPPORTED; Status = EFI_UNSUPPORTED;
} else { } else {
Status = LoadImage ( Status = LoadImage (
@ -463,6 +465,11 @@ RegisterCallback (
{ {
CALLBACK_INFO *Buffer; CALLBACK_INFO *Buffer;
if (mLocked) {
FunctionData->Status = EFI_UNSUPPORTED;
return;
}
/// ///
/// Note that MakeLast and FloatingPointSave options are not supported in PI SMM /// Note that MakeLast and FloatingPointSave options are not supported in PI SMM
/// ///
@ -512,11 +519,15 @@ HelperAllocatePool (
IN OUT SMMBASE_FUNCTION_DATA *FunctionData IN OUT SMMBASE_FUNCTION_DATA *FunctionData
) )
{ {
if (mLocked) {
FunctionData->Status = EFI_UNSUPPORTED;
} else {
FunctionData->Status = gSmst->SmmAllocatePool ( FunctionData->Status = gSmst->SmmAllocatePool (
FunctionData->Args.AllocatePool.PoolType, FunctionData->Args.AllocatePool.PoolType,
FunctionData->Args.AllocatePool.Size, FunctionData->Args.AllocatePool.Size,
FunctionData->Args.AllocatePool.Buffer FunctionData->Args.AllocatePool.Buffer
); );
}
} }
/** /**
@ -529,8 +540,12 @@ HelperFreePool (
IN OUT SMMBASE_FUNCTION_DATA *FunctionData IN OUT SMMBASE_FUNCTION_DATA *FunctionData
) )
{ {
if (mLocked) {
FunctionData->Status = EFI_UNSUPPORTED;
} else {
FreePool (FunctionData->Args.FreePool.Buffer); FreePool (FunctionData->Args.FreePool.Buffer);
FunctionData->Status = EFI_SUCCESS; FunctionData->Status = EFI_SUCCESS;
}
} }
/** /**
@ -633,6 +648,29 @@ SmmHandlerEntry (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
/**
Smm Ready To Lock event notification handler.
It sets a flag indicating that SMRAM has been locked.
@param[in] Protocol Points to the protocol's unique identifier.
@param[in] Interface Points to the interface instance.
@param[in] Handle The handle on which the interface was installed.
@retval EFI_SUCCESS Notification handler runs successfully.
**/
EFI_STATUS
EFIAPI
SmmReadyToLockEventNotify (
IN CONST EFI_GUID *Protocol,
IN VOID *Interface,
IN EFI_HANDLE Handle
)
{
mLocked = TRUE;
return EFI_SUCCESS;
}
/** /**
Entry point function of the SMM Base Helper SMM driver. Entry point function of the SMM Base Helper SMM driver.
@ -653,6 +691,7 @@ SmmBaseHelperMain (
EFI_MP_SERVICES_PROTOCOL *MpServices; EFI_MP_SERVICES_PROTOCOL *MpServices;
EFI_HANDLE Handle; EFI_HANDLE Handle;
UINTN NumberOfEnabledProcessors; UINTN NumberOfEnabledProcessors;
VOID *Registration;
Handle = NULL; Handle = NULL;
/// ///
@ -697,6 +736,16 @@ SmmBaseHelperMain (
mSmmBaseHelperReady->FrameworkSmst = mFrameworkSmst; mSmmBaseHelperReady->FrameworkSmst = mFrameworkSmst;
mSmmBaseHelperReady->ServiceEntry = SmmHandlerEntry; mSmmBaseHelperReady->ServiceEntry = SmmHandlerEntry;
//
// Register SMM Ready To Lock Protocol notification
//
Status = gSmst->SmmRegisterProtocolNotify (
&gEfiSmmReadyToLockProtocolGuid,
SmmReadyToLockEventNotify,
&Registration
);
ASSERT_EFI_ERROR (Status);
/// ///
/// Register SMM Base Helper services for SMM Base Thunk driver /// Register SMM Base Helper services for SMM Base Thunk driver
/// ///

View File

@ -59,6 +59,7 @@
gEfiMpServiceProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiMpServiceProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiSmmCpuIo2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiSmmCpuIo2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiLoadPeImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiLoadPeImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_CONSUMED
[Depex] [Depex]
gEfiSmmCpuProtocolGuid AND gEfiSmmCpuProtocolGuid AND

View File

@ -44,6 +44,7 @@ EFI_HANDLE mSmmBaseHandle = NULL;
EFI_SMM_BASE2_PROTOCOL *mSmmBase2 = NULL; EFI_SMM_BASE2_PROTOCOL *mSmmBase2 = NULL;
EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL; EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL;
EFI_SMM_BASE_HELPER_READY_PROTOCOL *mSmmBaseHelperReady = NULL; EFI_SMM_BASE_HELPER_READY_PROTOCOL *mSmmBaseHelperReady = NULL;
BOOLEAN mAtRuntime = FALSE;
/** /**
Determine if in SMM mode. Determine if in SMM mode.
@ -133,7 +134,7 @@ SmmBaseRegister (
IN BOOLEAN LegacyIA32Binary IN BOOLEAN LegacyIA32Binary
) )
{ {
if (LegacyIA32Binary) { if (mAtRuntime || LegacyIA32Binary) {
return EFI_UNSUPPORTED; return EFI_UNSUPPORTED;
} }
@ -166,6 +167,10 @@ SmmBaseUnregister (
IN EFI_HANDLE ImageHandle IN EFI_HANDLE ImageHandle
) )
{ {
if (mAtRuntime) {
return EFI_UNSUPPORTED;
}
mCommunicationData.FunctionData.Function = SmmBaseFunctionUnregister; mCommunicationData.FunctionData.Function = SmmBaseFunctionUnregister;
mCommunicationData.FunctionData.Args.UnRegister.ImageHandle = ImageHandle; mCommunicationData.FunctionData.Args.UnRegister.ImageHandle = ImageHandle;
@ -308,6 +313,10 @@ SmmBaseSmmAllocatePool (
OUT VOID **Buffer OUT VOID **Buffer
) )
{ {
if (mAtRuntime) {
return EFI_UNSUPPORTED;
}
mCommunicationData.FunctionData.Function = SmmBaseFunctionAllocatePool; mCommunicationData.FunctionData.Function = SmmBaseFunctionAllocatePool;
mCommunicationData.FunctionData.Args.AllocatePool.PoolType = PoolType; mCommunicationData.FunctionData.Args.AllocatePool.PoolType = PoolType;
mCommunicationData.FunctionData.Args.AllocatePool.Size = Size; mCommunicationData.FunctionData.Args.AllocatePool.Size = Size;
@ -336,6 +345,10 @@ SmmBaseSmmFreePool (
IN VOID *Buffer IN VOID *Buffer
) )
{ {
if (mAtRuntime) {
return EFI_UNSUPPORTED;
}
mCommunicationData.FunctionData.Function = SmmBaseFunctionFreePool; mCommunicationData.FunctionData.Function = SmmBaseFunctionFreePool;
mCommunicationData.FunctionData.Args.FreePool.Buffer = Buffer; mCommunicationData.FunctionData.Args.FreePool.Buffer = Buffer;
@ -408,6 +421,24 @@ EFI_SMM_BASE_PROTOCOL mSmmBase = {
SmmBaseGetSmstLocation SmmBaseGetSmstLocation
}; };
/**
Notification function on Exit Boot Services Event.
This function sets a flag indicating it is in Runtime phase.
@param Event Event whose notification function is being invoked
@param Context Pointer to the notification function's context
**/
VOID
EFIAPI
SmmBaseExitBootServicesEventNotify (
IN EFI_EVENT Event,
IN VOID *Context
)
{
mAtRuntime = TRUE;
}
/** /**
Entry Point for SMM Base Protocol on SMM Base2 Protocol Thunk driver. Entry Point for SMM Base Protocol on SMM Base2 Protocol Thunk driver.
@ -449,6 +480,19 @@ SmmBaseThunkMain (
Status = gBS->LocateProtocol (&gEfiSmmBaseHelperReadyProtocolGuid, NULL, (VOID **) &mSmmBaseHelperReady); Status = gBS->LocateProtocol (&gEfiSmmBaseHelperReadyProtocolGuid, NULL, (VOID **) &mSmmBaseHelperReady);
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
//
// Create event notification on Exit Boot Services event.
//
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
SmmBaseExitBootServicesEventNotify,
NULL,
&gEfiEventExitBootServicesGuid,
&Event
);
ASSERT_EFI_ERROR (Status);
// //
// Create event on SetVirtualAddressMap() to convert mSmmCommunication from a physical address to a virtual address // Create event on SetVirtualAddressMap() to convert mSmmCommunication from a physical address to a virtual address
// //

View File

@ -44,6 +44,7 @@
[Guids] [Guids]
gEfiEventVirtualAddressChangeGuid # GUID ALWAYS_CONSUMED gEfiEventVirtualAddressChangeGuid # GUID ALWAYS_CONSUMED
gEfiEventExitBootServicesGuid # GUID ALWAYS_CONSUMED
[Protocols] [Protocols]
gEfiSmmBase2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiSmmBase2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED