From: Eric Dong Date: Fri, 22 Apr 2016 07:40:46 +0000 (+0800) Subject: SecurityPkg-Opal(2): Enhance AHCI Bar MMIO region check. X-Git-Tag: edk2-stable201903~7208 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=009264f5cf0fa0009ff96f307eaac88860a998a8 SecurityPkg-Opal(2): Enhance AHCI Bar MMIO region check. This patch enhance OPAL password SMM driver to check SMM bar is valid MMIO besides outside of SMRAM. This is designed to meet Microsoft WSMT table definition on FIXED_COMM_BUFFERS requirement. Cc: Eric Dong Cc: Feng Tian Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Eric Dong Reviewed-by: Feng Tian --- diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.c b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.c index 0dc3490a36..33f77bd8a2 100644 --- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.c +++ b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.c @@ -1022,6 +1022,34 @@ GetAhciBarSize ( return Size; } +/** + This function check if the memory region is in GCD MMIO region. + + @param Addr The memory region start address to be checked. + @param Size The memory region length to be checked. + + @retval TRUE This memory region is in GCD MMIO region. + @retval FALSE This memory region is not in GCD MMIO region. +**/ +BOOLEAN +EFIAPI +OpalIsValidMmioSpace ( + IN EFI_PHYSICAL_ADDRESS Addr, + IN UINTN Size + ) +{ + UINTN Index; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Desc; + + for (Index = 0; Index < mNumberOfDescriptors; Index ++) { + Desc = &mGcdMemSpace[Index]; + if ((Desc->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) && (Addr >= Desc->BaseAddress) && ((Addr + Size) <= (Desc->BaseAddress + Desc->Length))) { + return TRUE; + } + } + + return FALSE; +} /** Get AHCI mode base address registers' Value. @@ -1055,7 +1083,7 @@ GetAhciBaseAddress ( // // Check if the AHCI Bar region is in SMRAM to avoid malicious attack by modifying MMIO Bar to point to SMRAM. // - if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)mAhciBar, Size)) { + if (!OpalIsValidMmioSpace ((EFI_PHYSICAL_ADDRESS)mAhciBar, Size)) { return EFI_UNSUPPORTED; } diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c index 57d10a17b7..b7e2d552d5 100644 --- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c +++ b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c @@ -61,6 +61,9 @@ VOID *mBuffer = NULL; // DMA can not read/write Data to smram, s // NVME NVME_CONTEXT mNvmeContext; +EFI_GCD_MEMORY_SPACE_DESCRIPTOR *mGcdMemSpace = NULL; +UINTN mNumberOfDescriptors = 0; + /** Add new bridge node or nvme device info to the device list. @@ -592,6 +595,44 @@ S3SleepEntryCallBack ( return Status; } +/** + OpalPassword Notification for SMM EndOfDxe protocol. + + @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 runs successfully. +**/ +EFI_STATUS +EFIAPI +OpalPasswordEndOfDxeNotification ( + IN CONST EFI_GUID *Protocol, + IN VOID *Interface, + IN EFI_HANDLE Handle + ) +{ + UINTN NumberOfDescriptors; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemSpaceMap; + EFI_STATUS Status; + + Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemSpaceMap); + if (EFI_ERROR (Status)) { + return Status; + } + + mGcdMemSpace = AllocateCopyPool (NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR), MemSpaceMap); + if (EFI_ERROR (Status)) { + gBS->FreePool (MemSpaceMap); + return Status; + } + + mNumberOfDescriptors = NumberOfDescriptors; + gBS->FreePool (MemSpaceMap); + + return EFI_SUCCESS; +} + /** Main entry for this driver. @@ -618,6 +659,7 @@ OpalPasswordSmmInit ( EFI_SMM_VARIABLE_PROTOCOL *SmmVariable; OPAL_EXTRA_INFO_VAR OpalExtraInfo; UINTN DataSize; + EFI_EVENT EndOfDxeEvent; EFI_PHYSICAL_ADDRESS Address; mBuffer = NULL; @@ -726,6 +768,15 @@ OpalPasswordSmmInit ( // mSwSmiValue = (UINT8) Context.SwSmiInputValue; + // + // Create event to record GCD descriptors at end of dxe for judging AHCI/NVMe PCI Bar + // is in MMIO space to avoid attack. + // + Status = gSmst->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid, OpalPasswordEndOfDxeNotification, &EndOfDxeEvent); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "OpalPasswordSmm: Register SmmEndOfDxe fail, Status: %r\n", Status)); + goto EXIT; + } Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&SmmVariable); if (!EFI_ERROR (Status)) { DataSize = sizeof (OPAL_EXTRA_INFO_VAR); diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h index f365136918..ab31a6bfe7 100644 --- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h +++ b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h @@ -25,6 +25,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include #include @@ -43,8 +44,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include -#include - #include #include @@ -71,6 +70,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. extern VOID *mBuffer; +extern EFI_GCD_MEMORY_SPACE_DESCRIPTOR *mGcdMemSpace; +extern UINTN mNumberOfDescriptors; #pragma pack(1) typedef struct { diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf index dae51ece02..cab0fd5656 100644 --- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf +++ b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf @@ -58,7 +58,6 @@ DxeServicesTableLib DevicePathLib OpalPasswordSupportLib - SmmMemLib [Guids] gOpalExtraInfoVariableGuid ## CONSUMES ## GUID @@ -70,6 +69,7 @@ gEfiSmmSxDispatch2ProtocolGuid ## CONSUMES gEfiSmmVariableProtocolGuid ## CONSUMES gEfiStorageSecurityCommandProtocolGuid ## CONSUMES + gEfiSmmEndOfDxeProtocolGuid ## CONSUMES [Depex] gEfiSmmSwDispatch2ProtocolGuid AND