From 8edfbe027cc9f20624e64a392a160b7c9240e087 Mon Sep 17 00:00:00 2001 From: rsun3 Date: Fri, 26 Mar 2010 08:41:06 +0000 Subject: [PATCH] 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 --- .../SmmBaseHelper/SmmBaseHelper.c | 65 ++++++++++++++++--- .../SmmBaseHelper/SmmBaseHelper.inf | 1 + .../SmmBaseOnSmmBase2Thunk.c | 46 ++++++++++++- .../SmmBaseOnSmmBase2Thunk.inf | 1 + 4 files changed, 104 insertions(+), 9 deletions(-) diff --git a/EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.c b/EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.c index 033d93eff8..e7976b9c0c 100644 --- a/EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.c +++ b/EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.c @@ -32,6 +32,7 @@ #include #include #include +#include /// /// 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_SYSTEM_TABLE *mFrameworkSmst; UINTN mNumberOfProcessors; +BOOLEAN mLocked = FALSE; LIST_ENTRY mCallbackInfoListHead = INITIALIZE_LIST_HEAD_VARIABLE (mCallbackInfoListHead); @@ -272,7 +274,7 @@ Register ( { EFI_STATUS Status; - if (FunctionData->Args.Register.LegacyIA32Binary) { + if (mLocked || FunctionData->Args.Register.LegacyIA32Binary) { Status = EFI_UNSUPPORTED; } else { Status = LoadImage ( @@ -463,6 +465,11 @@ RegisterCallback ( { CALLBACK_INFO *Buffer; + if (mLocked) { + FunctionData->Status = EFI_UNSUPPORTED; + return; + } + /// /// Note that MakeLast and FloatingPointSave options are not supported in PI SMM /// @@ -512,11 +519,15 @@ HelperAllocatePool ( IN OUT SMMBASE_FUNCTION_DATA *FunctionData ) { - FunctionData->Status = gSmst->SmmAllocatePool ( - FunctionData->Args.AllocatePool.PoolType, - FunctionData->Args.AllocatePool.Size, - FunctionData->Args.AllocatePool.Buffer - ); + if (mLocked) { + FunctionData->Status = EFI_UNSUPPORTED; + } else { + FunctionData->Status = gSmst->SmmAllocatePool ( + FunctionData->Args.AllocatePool.PoolType, + FunctionData->Args.AllocatePool.Size, + FunctionData->Args.AllocatePool.Buffer + ); + } } /** @@ -529,8 +540,12 @@ HelperFreePool ( IN OUT SMMBASE_FUNCTION_DATA *FunctionData ) { - FreePool (FunctionData->Args.FreePool.Buffer); - FunctionData->Status = EFI_SUCCESS; + if (mLocked) { + FunctionData->Status = EFI_UNSUPPORTED; + } else { + FreePool (FunctionData->Args.FreePool.Buffer); + FunctionData->Status = EFI_SUCCESS; + } } /** @@ -633,6 +648,29 @@ SmmHandlerEntry ( 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. @@ -653,6 +691,7 @@ SmmBaseHelperMain ( EFI_MP_SERVICES_PROTOCOL *MpServices; EFI_HANDLE Handle; UINTN NumberOfEnabledProcessors; + VOID *Registration; Handle = NULL; /// @@ -697,6 +736,16 @@ SmmBaseHelperMain ( mSmmBaseHelperReady->FrameworkSmst = mFrameworkSmst; 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 /// diff --git a/EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.inf b/EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.inf index e4c0f42bd6..88e7f0a588 100644 --- a/EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.inf +++ b/EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.inf @@ -59,6 +59,7 @@ gEfiMpServiceProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiSmmCpuIo2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiLoadPeImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiSmmReadyToLockProtocolGuid # PROTOCOL ALWAYS_CONSUMED [Depex] gEfiSmmCpuProtocolGuid AND diff --git a/EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.c b/EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.c index e470da0af0..4834036a6b 100644 --- a/EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.c +++ b/EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.c @@ -44,6 +44,7 @@ EFI_HANDLE mSmmBaseHandle = NULL; EFI_SMM_BASE2_PROTOCOL *mSmmBase2 = NULL; EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL; EFI_SMM_BASE_HELPER_READY_PROTOCOL *mSmmBaseHelperReady = NULL; +BOOLEAN mAtRuntime = FALSE; /** Determine if in SMM mode. @@ -133,7 +134,7 @@ SmmBaseRegister ( IN BOOLEAN LegacyIA32Binary ) { - if (LegacyIA32Binary) { + if (mAtRuntime || LegacyIA32Binary) { return EFI_UNSUPPORTED; } @@ -166,6 +167,10 @@ SmmBaseUnregister ( IN EFI_HANDLE ImageHandle ) { + if (mAtRuntime) { + return EFI_UNSUPPORTED; + } + mCommunicationData.FunctionData.Function = SmmBaseFunctionUnregister; mCommunicationData.FunctionData.Args.UnRegister.ImageHandle = ImageHandle; @@ -308,6 +313,10 @@ SmmBaseSmmAllocatePool ( OUT VOID **Buffer ) { + if (mAtRuntime) { + return EFI_UNSUPPORTED; + } + mCommunicationData.FunctionData.Function = SmmBaseFunctionAllocatePool; mCommunicationData.FunctionData.Args.AllocatePool.PoolType = PoolType; mCommunicationData.FunctionData.Args.AllocatePool.Size = Size; @@ -336,6 +345,10 @@ SmmBaseSmmFreePool ( IN VOID *Buffer ) { + if (mAtRuntime) { + return EFI_UNSUPPORTED; + } + mCommunicationData.FunctionData.Function = SmmBaseFunctionFreePool; mCommunicationData.FunctionData.Args.FreePool.Buffer = Buffer; @@ -408,6 +421,24 @@ EFI_SMM_BASE_PROTOCOL mSmmBase = { 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. @@ -449,6 +480,19 @@ SmmBaseThunkMain ( Status = gBS->LocateProtocol (&gEfiSmmBaseHelperReadyProtocolGuid, NULL, (VOID **) &mSmmBaseHelperReady); 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 // diff --git a/EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.inf b/EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.inf index 976128165c..778c90cc3a 100644 --- a/EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.inf +++ b/EdkCompatibilityPkg/Compatibility/SmmBaseOnSmmBase2Thunk/SmmBaseOnSmmBase2Thunk.inf @@ -44,6 +44,7 @@ [Guids] gEfiEventVirtualAddressChangeGuid # GUID ALWAYS_CONSUMED + gEfiEventExitBootServicesGuid # GUID ALWAYS_CONSUMED [Protocols] gEfiSmmBase2ProtocolGuid # PROTOCOL ALWAYS_CONSUMED -- 2.39.2