From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../Universal/LockBox/SmmLockBox/SmmLockBox.c | 434 +++++++++++++++++++++ 1 file changed, 434 insertions(+) create mode 100644 roms/edk2/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c (limited to 'roms/edk2/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c') diff --git a/roms/edk2/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c b/roms/edk2/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c new file mode 100644 index 000000000..f11c3a17e --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c @@ -0,0 +1,434 @@ +/** @file + LockBox SMM driver. + + 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. + + SmmLockBoxHandler(), SmmLockBoxRestore(), SmmLockBoxUpdate(), SmmLockBoxSave() + will receive untrusted input and do basic validation. + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +BOOLEAN mLocked = FALSE; + +/** + 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 +SmmLockBoxSave ( + IN EFI_SMM_LOCK_BOX_PARAMETER_SAVE *LockBoxParameterSave + ) +{ + EFI_STATUS Status; + EFI_SMM_LOCK_BOX_PARAMETER_SAVE TempLockBoxParameterSave; + + // + // Sanity check + // + if (mLocked) { + DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n")); + LockBoxParameterSave->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; + return ; + } + + CopyMem (&TempLockBoxParameterSave, LockBoxParameterSave, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SAVE)); + + // + // Sanity check + // + if (!SmmIsBufferOutsideSmmValid ((UINTN)TempLockBoxParameterSave.Buffer, (UINTN)TempLockBoxParameterSave.Length)) { + DEBUG ((EFI_D_ERROR, "SmmLockBox Save address in SMRAM or buffer overflow!\n")); + LockBoxParameterSave->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; + return ; + } + // + // The SpeculationBarrier() call here is to ensure the above range check for + // the CommBuffer have been completed before calling into SaveLockBox(). + // + SpeculationBarrier (); + + // + // Save data + // + Status = SaveLockBox ( + &TempLockBoxParameterSave.Guid, + (VOID *)(UINTN)TempLockBoxParameterSave.Buffer, + (UINTN)TempLockBoxParameterSave.Length + ); + LockBoxParameterSave->Header.ReturnStatus = (UINT64)Status; + return ; +} + +/** + Dispatch function for SMM lock box set attributes. + + @param LockBoxParameterSetAttributes parameter of lock box set attributes +**/ +VOID +SmmLockBoxSetAttributes ( + IN EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *LockBoxParameterSetAttributes + ) +{ + EFI_STATUS Status; + EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES TempLockBoxParameterSetAttributes; + + // + // Sanity check + // + if (mLocked) { + DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n")); + LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; + return ; + } + + CopyMem (&TempLockBoxParameterSetAttributes, LockBoxParameterSetAttributes, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES)); + + // + // Update data + // + Status = SetLockBoxAttributes ( + &TempLockBoxParameterSetAttributes.Guid, + TempLockBoxParameterSetAttributes.Attributes + ); + LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)Status; + return ; +} + +/** + 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 +SmmLockBoxUpdate ( + IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *LockBoxParameterUpdate + ) +{ + EFI_STATUS Status; + EFI_SMM_LOCK_BOX_PARAMETER_UPDATE TempLockBoxParameterUpdate; + + // + // Sanity check + // + if (mLocked) { + DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n")); + LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; + return ; + } + + CopyMem (&TempLockBoxParameterUpdate, LockBoxParameterUpdate, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_UPDATE)); + + // + // Sanity check + // + if (!SmmIsBufferOutsideSmmValid ((UINTN)TempLockBoxParameterUpdate.Buffer, (UINTN)TempLockBoxParameterUpdate.Length)) { + DEBUG ((EFI_D_ERROR, "SmmLockBox Update address in SMRAM or buffer overflow!\n")); + LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; + return ; + } + // + // The SpeculationBarrier() call here is to ensure the above range check for + // the CommBuffer have been completed before calling into UpdateLockBox(). + // + SpeculationBarrier (); + + // + // Update data + // + Status = UpdateLockBox ( + &TempLockBoxParameterUpdate.Guid, + (UINTN)TempLockBoxParameterUpdate.Offset, + (VOID *)(UINTN)TempLockBoxParameterUpdate.Buffer, + (UINTN)TempLockBoxParameterUpdate.Length + ); + LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)Status; + return ; +} + +/** + 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 +SmmLockBoxRestore ( + IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *LockBoxParameterRestore + ) +{ + EFI_STATUS Status; + EFI_SMM_LOCK_BOX_PARAMETER_RESTORE TempLockBoxParameterRestore; + + CopyMem (&TempLockBoxParameterRestore, LockBoxParameterRestore, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE)); + + // + // Sanity check + // + if (!SmmIsBufferOutsideSmmValid ((UINTN)TempLockBoxParameterRestore.Buffer, (UINTN)TempLockBoxParameterRestore.Length)) { + DEBUG ((EFI_D_ERROR, "SmmLockBox Restore address in SMRAM or buffer overflow!\n")); + LockBoxParameterRestore->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; + return ; + } + + // + // Restore data + // + if ((TempLockBoxParameterRestore.Length == 0) && (TempLockBoxParameterRestore.Buffer == 0)) { + Status = RestoreLockBox ( + &TempLockBoxParameterRestore.Guid, + NULL, + NULL + ); + } else { + Status = RestoreLockBox ( + &TempLockBoxParameterRestore.Guid, + (VOID *)(UINTN)TempLockBoxParameterRestore.Buffer, + (UINTN *)&TempLockBoxParameterRestore.Length + ); + if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_SUCCESS)) { + // + // Return the actual Length value. + // + LockBoxParameterRestore->Length = TempLockBoxParameterRestore.Length; + } + } + LockBoxParameterRestore->Header.ReturnStatus = (UINT64)Status; + return ; +} + +/** + Dispatch function for SMM lock box restore all in place. + + @param LockBoxParameterRestoreAllInPlace parameter of lock box restore all in place +**/ +VOID +SmmLockBoxRestoreAllInPlace ( + IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace + ) +{ + EFI_STATUS Status; + + Status = RestoreAllLockBoxInPlace (); + LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)Status; + return ; +} + +/** + 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. + @param CommBuffer A pointer to a collection of data in memory that will + be conveyed from a non-SMM environment into an SMM environment. + @param CommBufferSize The size of the CommBuffer. + + @retval EFI_SUCCESS Command is handled successfully. + +**/ +EFI_STATUS +EFIAPI +SmmLockBoxHandler ( + IN EFI_HANDLE DispatchHandle, + IN CONST VOID *Context OPTIONAL, + IN OUT VOID *CommBuffer OPTIONAL, + IN OUT UINTN *CommBufferSize OPTIONAL + ) +{ + EFI_SMM_LOCK_BOX_PARAMETER_HEADER *LockBoxParameterHeader; + UINTN TempCommBufferSize; + + DEBUG ((DEBUG_INFO, "SmmLockBox SmmLockBoxHandler Enter\n")); + + // + // If input is invalid, stop processing this SMI + // + if (CommBuffer == NULL || CommBufferSize == NULL) { + return EFI_SUCCESS; + } + + TempCommBufferSize = *CommBufferSize; + + // + // Sanity check + // + if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_HEADER)) { + DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size invalid!\n")); + return EFI_SUCCESS; + } + if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) { + DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer in SMRAM or overflow!\n")); + return EFI_SUCCESS; + } + + LockBoxParameterHeader = (EFI_SMM_LOCK_BOX_PARAMETER_HEADER *)((UINTN)CommBuffer); + + LockBoxParameterHeader->ReturnStatus = (UINT64)-1; + + DEBUG ((DEBUG_INFO, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN)LockBoxParameterHeader)); + + DEBUG ((DEBUG_INFO, "SmmLockBox Command - %x\n", (UINTN)LockBoxParameterHeader->Command)); + + switch (LockBoxParameterHeader->Command) { + case EFI_SMM_LOCK_BOX_COMMAND_SAVE: + if (TempCommBufferSize < 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 (TempCommBufferSize < 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 (TempCommBufferSize < 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 (TempCommBufferSize < 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 (TempCommBufferSize < 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; + } + + LockBoxParameterHeader->Command = (UINT32)-1; + + DEBUG ((DEBUG_INFO, "SmmLockBox SmmLockBoxHandler Exit\n")); + + 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 for LockBox SMM driver. + + @param[in] ImageHandle Image handle of this driver. + @param[in] SystemTable A Pointer to the EFI System Table. + + @retval EFI_SUCEESS + @return Others Some error occurs. +**/ +EFI_STATUS +EFIAPI +SmmLockBoxEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE DispatchHandle; + VOID *Registration; + + // + // Register LockBox communication handler + // + Status = gSmst->SmiHandlerRegister ( + SmmLockBoxHandler, + &gEfiSmmLockBoxCommunicationGuid, + &DispatchHandle + ); + ASSERT_EFI_ERROR (Status); + + // + // Register SMM Ready To Lock Protocol notification + // + Status = gSmst->SmmRegisterProtocolNotify ( + &gEfiSmmReadyToLockProtocolGuid, + SmmReadyToLockEventNotify, + &Registration + ); + ASSERT_EFI_ERROR (Status); + + // + // Install NULL to DXE data base as notify + // + ImageHandle = NULL; + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gEfiLockBoxProtocolGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} -- cgit 1.2.3-korg