diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c index faeaabb224..93a300a846 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c @@ -21,6 +21,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include "Variable.h" typedef struct { @@ -33,6 +34,8 @@ VARIABLE_TYPE mMorVariableType[] = { {MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, &gEfiMemoryOverwriteRequestControlLockGuid}, }; +BOOLEAN mMorPassThru = FALSE; + #define MOR_LOCK_DATA_UNLOCKED 0x0 #define MOR_LOCK_DATA_LOCKED_WITHOUT_KEY 0x1 #define MOR_LOCK_DATA_LOCKED_WITH_KEY 0x2 @@ -362,6 +365,13 @@ SetVariableCheckHandlerMor ( // Mor Variable // + // + // Permit deletion for passthru request. + // + if (((Attributes == 0) || (DataSize == 0)) && mMorPassThru) { + return EFI_SUCCESS; + } + // // Basic Check // @@ -409,6 +419,8 @@ MorLockInitAtEndOfDxe ( { UINTN MorSize; EFI_STATUS MorStatus; + EFI_STATUS TcgStatus; + VOID *TcgInterface; if (!mMorLockInitializationRequired) { // @@ -437,17 +449,72 @@ MorLockInitAtEndOfDxe ( if (MorStatus == EFI_BUFFER_TOO_SMALL) { // - // The MOR variable exists; set the MOR Control Lock variable to report the - // capability to the OS. + // The MOR variable exists. // - SetMorLockVariable (0); - return; + // Some OSes don't follow the TCG's Platform Reset Attack Mitigation spec + // in that the OS should never create the MOR variable, only read and write + // it -- these OSes (unintentionally) create MOR if the platform firmware + // does not produce it. Whether this is the case (from the last OS boot) + // can be deduced from the absence of the TCG / TCG2 protocols, as edk2's + // MOR implementation depends on (one of) those protocols. + // + TcgStatus = gBS->LocateProtocol ( + &gEfiTcgProtocolGuid, + NULL, // Registration + &TcgInterface + ); + if (EFI_ERROR (TcgStatus)) { + TcgStatus = gBS->LocateProtocol ( + &gEfiTcg2ProtocolGuid, + NULL, // Registration + &TcgInterface + ); + } + + if (!EFI_ERROR (TcgStatus)) { + // + // The MOR variable originates from the platform firmware; set the MOR + // Control Lock variable to report the locking capability to the OS. + // + SetMorLockVariable (0); + return; + } + + // + // The MOR variable's origin is inexplicable; delete it. + // + DEBUG (( + DEBUG_WARN, + "%a: deleting unexpected / unsupported variable %g:%s\n", + __FUNCTION__, + &gEfiMemoryOverwriteControlDataGuid, + MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME + )); + + mMorPassThru = TRUE; + VariableServiceSetVariable ( + MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, + &gEfiMemoryOverwriteControlDataGuid, + 0, // Attributes + 0, // DataSize + NULL // Data + ); + mMorPassThru = FALSE; } // - // The platform does not support the MOR variable. Delete the MOR Control - // Lock variable (should it exists for some reason) and prevent other modules - // from creating it. + // The MOR variable is absent; the platform firmware does not support it. + // Lock the variable so that no other module may create it. + // + VariableLockRequestToLock ( + NULL, // This + MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, + &gEfiMemoryOverwriteControlDataGuid + ); + + // + // Delete the MOR Control Lock variable too (should it exists for some + // reason) and prevent other modules from creating it. // mMorLockPassThru = TRUE; VariableServiceSetVariable ( diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf index 4041643665..69966f0d37 100644 --- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf +++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf @@ -74,6 +74,7 @@ SmmMemLib AuthVariableLib VarCheckLib + UefiBootServicesTableLib [Protocols] gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES @@ -85,6 +86,8 @@ gEfiSmmVariableProtocolGuid gEfiSmmEndOfDxeProtocolGuid ## NOTIFY gEdkiiSmmVarCheckProtocolGuid ## PRODUCES + gEfiTcgProtocolGuid ## SOMETIMES_CONSUMES + gEfiTcg2ProtocolGuid ## SOMETIMES_CONSUMES [Guids] ## SOMETIMES_CONSUMES ## GUID # Signature of Variable store header