X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FLockBox%2FSmmLockBox%2FSmmLockBox.c;h=c1e15c596bddd1410b19ba18ec637d6626968a00;hb=HEAD;hp=b9c819058b717d3f37beb18cc45d81cba74ec3b9;hpb=32177f69c40f81a8cdb2033c422f3c76f57945e5;p=mirror_edk2.git diff --git a/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c b/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c index b9c819058b..c1e15c596b 100644 --- a/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c +++ b/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c @@ -1,6 +1,5 @@ /** @file - -Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.
+ LockBox SMM driver. Caution: This module requires additional review when modified. This driver will have external input - communicate buffer in SMM mode. @@ -10,14 +9,9 @@ Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.
SmmLockBoxHandler(), SmmLockBoxRestore(), SmmLockBoxUpdate(), SmmLockBoxSave() will receive untrusted input and do basic validation. -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 -http://opensource.org/licenses/bsd-license.php +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -29,71 +23,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include + #include #include -#include #include #include -BOOLEAN mLocked = FALSE; - -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 -IsAddressInSmram ( - 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; -} - -/** - 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; -} +BOOLEAN mLocked = FALSE; /** Dispatch function for SMM lock box save. @@ -102,43 +40,52 @@ IsAddressValid ( Restore buffer and length are external input, so this function will validate it is in SMRAM. - @param LockBoxParameterSave parameter of lock box save + @param LockBoxParameterSave parameter of lock box save **/ VOID SmmLockBoxSave ( - IN EFI_SMM_LOCK_BOX_PARAMETER_SAVE *LockBoxParameterSave + IN EFI_SMM_LOCK_BOX_PARAMETER_SAVE *LockBoxParameterSave ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_SMM_LOCK_BOX_PARAMETER_SAVE TempLockBoxParameterSave; // // Sanity check // if (mLocked) { - DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n")); + DEBUG ((DEBUG_ERROR, "SmmLockBox Locked!\n")); LockBoxParameterSave->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; - return ; + return; } + CopyMem (&TempLockBoxParameterSave, LockBoxParameterSave, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SAVE)); + // // Sanity check // - if (!IsAddressValid ((UINTN)LockBoxParameterSave->Buffer, (UINTN)LockBoxParameterSave->Length)) { - DEBUG ((EFI_D_ERROR, "SmmLockBox Save address in SMRAM!\n")); + if (!SmmIsBufferOutsideSmmValid ((UINTN)TempLockBoxParameterSave.Buffer, (UINTN)TempLockBoxParameterSave.Length)) { + DEBUG ((DEBUG_ERROR, "SmmLockBox Save address in SMRAM or buffer overflow!\n")); LockBoxParameterSave->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; - return ; + 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 ( - &LockBoxParameterSave->Guid, - (VOID *)(UINTN)LockBoxParameterSave->Buffer, - (UINTN)LockBoxParameterSave->Length + &TempLockBoxParameterSave.Guid, + (VOID *)(UINTN)TempLockBoxParameterSave.Buffer, + (UINTN)TempLockBoxParameterSave.Length ); LockBoxParameterSave->Header.ReturnStatus = (UINT64)Status; - return ; + return; } /** @@ -148,29 +95,32 @@ SmmLockBoxSave ( **/ VOID SmmLockBoxSetAttributes ( - IN EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *LockBoxParameterSetAttributes + IN EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *LockBoxParameterSetAttributes ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES TempLockBoxParameterSetAttributes; // // Sanity check // if (mLocked) { - DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n")); + DEBUG ((DEBUG_ERROR, "SmmLockBox Locked!\n")); LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; - return ; + return; } + CopyMem (&TempLockBoxParameterSetAttributes, LockBoxParameterSetAttributes, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES)); + // // Update data // Status = SetLockBoxAttributes ( - &LockBoxParameterSetAttributes->Guid, - LockBoxParameterSetAttributes->Attributes + &TempLockBoxParameterSetAttributes.Guid, + TempLockBoxParameterSetAttributes.Attributes ); LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)Status; - return ; + return; } /** @@ -180,44 +130,53 @@ SmmLockBoxSetAttributes ( Restore buffer and length are external input, so this function will validate it is in SMRAM. - @param LockBoxParameterUpdate parameter of lock box update + @param LockBoxParameterUpdate parameter of lock box update **/ VOID SmmLockBoxUpdate ( - IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *LockBoxParameterUpdate + IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *LockBoxParameterUpdate ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_SMM_LOCK_BOX_PARAMETER_UPDATE TempLockBoxParameterUpdate; // // Sanity check // if (mLocked) { - DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n")); + DEBUG ((DEBUG_ERROR, "SmmLockBox Locked!\n")); LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; - return ; + return; } + CopyMem (&TempLockBoxParameterUpdate, LockBoxParameterUpdate, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_UPDATE)); + // // Sanity check // - if (!IsAddressValid ((UINTN)LockBoxParameterUpdate->Buffer, (UINTN)LockBoxParameterUpdate->Length)) { - DEBUG ((EFI_D_ERROR, "SmmLockBox Update address in SMRAM!\n")); + if (!SmmIsBufferOutsideSmmValid ((UINTN)TempLockBoxParameterUpdate.Buffer, (UINTN)TempLockBoxParameterUpdate.Length)) { + DEBUG ((DEBUG_ERROR, "SmmLockBox Update address in SMRAM or buffer overflow!\n")); LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; - return ; + 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 ( - &LockBoxParameterUpdate->Guid, - (UINTN)LockBoxParameterUpdate->Offset, - (VOID *)(UINTN)LockBoxParameterUpdate->Buffer, - (UINTN)LockBoxParameterUpdate->Length + &TempLockBoxParameterUpdate.Guid, + (UINTN)TempLockBoxParameterUpdate.Offset, + (VOID *)(UINTN)TempLockBoxParameterUpdate.Buffer, + (UINTN)TempLockBoxParameterUpdate.Length ); LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)Status; - return ; + return; } /** @@ -227,42 +186,52 @@ SmmLockBoxUpdate ( Restore buffer and length are external input, so this function will validate it is in SMRAM. - @param LockBoxParameterRestore parameter of lock box restore + @param LockBoxParameterRestore parameter of lock box restore **/ VOID SmmLockBoxRestore ( - IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *LockBoxParameterRestore + IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *LockBoxParameterRestore ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_SMM_LOCK_BOX_PARAMETER_RESTORE TempLockBoxParameterRestore; + + CopyMem (&TempLockBoxParameterRestore, LockBoxParameterRestore, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE)); // // Sanity check // - if (!IsAddressValid ((UINTN)LockBoxParameterRestore->Buffer, (UINTN)LockBoxParameterRestore->Length)) { - DEBUG ((EFI_D_ERROR, "SmmLockBox Restore address in SMRAM!\n")); + if (!SmmIsBufferOutsideSmmValid ((UINTN)TempLockBoxParameterRestore.Buffer, (UINTN)TempLockBoxParameterRestore.Length)) { + DEBUG ((DEBUG_ERROR, "SmmLockBox Restore address in SMRAM or buffer overflow!\n")); LockBoxParameterRestore->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; - return ; + return; } // // Restore data // - if ((LockBoxParameterRestore->Length == 0) && (LockBoxParameterRestore->Buffer == 0)) { + if ((TempLockBoxParameterRestore.Length == 0) && (TempLockBoxParameterRestore.Buffer == 0)) { Status = RestoreLockBox ( - &LockBoxParameterRestore->Guid, + &TempLockBoxParameterRestore.Guid, NULL, NULL ); } else { Status = RestoreLockBox ( - &LockBoxParameterRestore->Guid, - (VOID *)(UINTN)LockBoxParameterRestore->Buffer, - (UINTN *)&LockBoxParameterRestore->Length + &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 ; + return; } /** @@ -272,14 +241,14 @@ SmmLockBoxRestore ( **/ VOID SmmLockBoxRestoreAllInPlace ( - IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace + IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace ) { - EFI_STATUS Status; + EFI_STATUS Status; - Status = RestoreAllLockBoxInPlace (); + Status = RestoreAllLockBoxInPlace (); LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)Status; - return ; + return; } /** @@ -307,19 +276,30 @@ SmmLockBoxHandler ( IN OUT UINTN *CommBufferSize OPTIONAL ) { - EFI_SMM_LOCK_BOX_PARAMETER_HEADER *LockBoxParameterHeader; + 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; + } - DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Enter\n")); + TempCommBufferSize = *CommBufferSize; // // Sanity check // - if (*CommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_HEADER)) { - DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size invalid!\n")); + if (TempCommBufferSize < sizeof (EFI_SMM_LOCK_BOX_PARAMETER_HEADER)) { + DEBUG ((DEBUG_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")); + + if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) { + DEBUG ((DEBUG_ERROR, "SmmLockBox Command Buffer in SMRAM or overflow!\n")); return EFI_SUCCESS; } @@ -327,54 +307,59 @@ SmmLockBoxHandler ( LockBoxParameterHeader->ReturnStatus = (UINT64)-1; - DEBUG ((EFI_D_ERROR, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN)LockBoxParameterHeader)); + DEBUG ((DEBUG_INFO, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN)LockBoxParameterHeader)); - DEBUG ((EFI_D_ERROR, "SmmLockBox Command - %x\n", (UINTN)LockBoxParameterHeader->Command)); + DEBUG ((DEBUG_INFO, "SmmLockBox Command - %x\n", (UINTN)LockBoxParameterHeader->Command)); 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")); + case EFI_SMM_LOCK_BOX_COMMAND_SAVE: + if (TempCommBufferSize < sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SAVE)) { + DEBUG ((DEBUG_ERROR, "SmmLockBox Command Buffer Size for SAVE invalid!\n")); + break; + } + + SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE *)(UINTN)LockBoxParameterHeader); 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")); + case EFI_SMM_LOCK_BOX_COMMAND_UPDATE: + if (TempCommBufferSize < sizeof (EFI_SMM_LOCK_BOX_PARAMETER_UPDATE)) { + DEBUG ((DEBUG_ERROR, "SmmLockBox Command Buffer Size for UPDATE invalid!\n")); + break; + } + + SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *)(UINTN)LockBoxParameterHeader); 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")); + case EFI_SMM_LOCK_BOX_COMMAND_RESTORE: + if (TempCommBufferSize < sizeof (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE)) { + DEBUG ((DEBUG_ERROR, "SmmLockBox Command Buffer Size for RESTORE invalid!\n")); + break; + } + + SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)(UINTN)LockBoxParameterHeader); 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")); + case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES: + if (TempCommBufferSize < sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES)) { + DEBUG ((DEBUG_ERROR, "SmmLockBox Command Buffer Size for SET_ATTRIBUTES invalid!\n")); + break; + } + + SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *)(UINTN)LockBoxParameterHeader); 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")); + case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE: + if (TempCommBufferSize < sizeof (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE)) { + DEBUG ((DEBUG_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 ((DEBUG_ERROR, "SmmLockBox Command 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 ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Exit\n")); + DEBUG ((DEBUG_INFO, "SmmLockBox SmmLockBoxHandler Exit\n")); return EFI_SUCCESS; } @@ -383,7 +368,7 @@ SmmLockBoxHandler ( 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. @@ -408,7 +393,7 @@ SmmReadyToLockEventNotify ( @param[in] ImageHandle Image handle of this driver. @param[in] SystemTable A Pointer to the EFI System Table. - @retval EFI_SUCEESS + @retval EFI_SUCEESS @return Others Some error occurs. **/ EFI_STATUS @@ -418,33 +403,9 @@ SmmLockBoxEntryPoint ( IN EFI_SYSTEM_TABLE *SystemTable ) { - EFI_STATUS Status; - EFI_HANDLE DispatchHandle; - VOID *Registration; - EFI_SMM_ACCESS2_PROTOCOL *SmmAccess; - UINTN Size; - - // - // 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); + EFI_STATUS Status; + EFI_HANDLE DispatchHandle; + VOID *Registration; // // Register LockBox communication handler @@ -470,12 +431,12 @@ SmmLockBoxEntryPoint ( // Install NULL to DXE data base as notify // ImageHandle = NULL; - Status = gBS->InstallProtocolInterface ( - &ImageHandle, - &gEfiLockBoxProtocolGuid, - EFI_NATIVE_INTERFACE, - NULL - ); + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gEfiLockBoxProtocolGuid, + EFI_NATIVE_INTERFACE, + NULL + ); ASSERT_EFI_ERROR (Status); return Status;