StandaloneMmPkg: Fix check buffer address failed issue from TF-A

There are two scene communicate with StandaloneMm(MM):
1 edk2 -> TF-A -> MM, communicate MM use non-secure buffer which
  specify by EFI_SECURE_PARTITION_BOOT_INFO.SpNsCommBufBase;
2 RAS scene: fiq -> TF-A -> MM, use secure buffer which
  specify by EFI_SECURE_PARTITION_BOOT_INFO.SpShareBufBase;

For now, the second scene will failed because check buffer address.
This patch add CheckBufferAddr() to support check address for secure
buffer.

Signed-off-by: Ming Huang <huangming@linux.alibaba.com>
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
This commit is contained in:
Ming Huang 2021-12-31 19:06:23 +08:00 committed by mergify[bot]
parent 31d3eeb103
commit 5496c763aa
3 changed files with 74 additions and 15 deletions

View File

@ -49,6 +49,7 @@ EFI_MM_COMMUNICATE_HEADER **PerCpuGuidedEventContext = NULL;
// Descriptor with whereabouts of memory used for communication with the normal world // Descriptor with whereabouts of memory used for communication with the normal world
EFI_MMRAM_DESCRIPTOR mNsCommBuffer; EFI_MMRAM_DESCRIPTOR mNsCommBuffer;
EFI_MMRAM_DESCRIPTOR mSCommBuffer;
MP_INFORMATION_HOB_DATA *mMpInformationHobData; MP_INFORMATION_HOB_DATA *mMpInformationHobData;
@ -59,6 +60,53 @@ EFI_MM_CONFIGURATION_PROTOCOL mMmConfig = {
STATIC EFI_MM_ENTRY_POINT mMmEntryPoint = NULL; STATIC EFI_MM_ENTRY_POINT mMmEntryPoint = NULL;
/**
Perform bounds check on the common buffer.
@param [in] BufferAddr Address of the common buffer.
@retval EFI_SUCCESS Success.
@retval EFI_ACCESS_DENIED Access not permitted.
**/
STATIC
EFI_STATUS
CheckBufferAddr (
IN UINTN BufferAddr
)
{
UINT64 NsCommBufferEnd;
UINT64 SCommBufferEnd;
UINT64 CommBufferEnd;
NsCommBufferEnd = mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize;
SCommBufferEnd = mSCommBuffer.PhysicalStart + mSCommBuffer.PhysicalSize;
if ((BufferAddr >= mNsCommBuffer.PhysicalStart) &&
(BufferAddr < NsCommBufferEnd))
{
CommBufferEnd = NsCommBufferEnd;
} else if ((BufferAddr >= mSCommBuffer.PhysicalStart) &&
(BufferAddr < SCommBufferEnd))
{
CommBufferEnd = SCommBufferEnd;
} else {
return EFI_ACCESS_DENIED;
}
if ((CommBufferEnd - BufferAddr) < sizeof (EFI_MM_COMMUNICATE_HEADER)) {
return EFI_ACCESS_DENIED;
}
// perform bounds check.
if ((CommBufferEnd - BufferAddr - sizeof (EFI_MM_COMMUNICATE_HEADER)) <
((EFI_MM_COMMUNICATE_HEADER *)BufferAddr)->MessageLength)
{
return EFI_ACCESS_DENIED;
}
return EFI_SUCCESS;
}
/** /**
The PI Standalone MM entry point for the TF-A CPU driver. The PI Standalone MM entry point for the TF-A CPU driver.
@ -104,27 +152,16 @@ PiMmStandaloneArmTfCpuDriverEntry (
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
if (NsCommBufferAddr < mNsCommBuffer.PhysicalStart) { Status = CheckBufferAddr (NsCommBufferAddr);
return EFI_ACCESS_DENIED; if (EFI_ERROR (Status)) {
} DEBUG ((DEBUG_ERROR, "Check Buffer failed: %r\n", Status));
return Status;
if ((NsCommBufferAddr + sizeof (EFI_MM_COMMUNICATE_HEADER)) >=
(mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize))
{
return EFI_INVALID_PARAMETER;
} }
// Find out the size of the buffer passed // Find out the size of the buffer passed
NsCommBufferSize = ((EFI_MM_COMMUNICATE_HEADER *)NsCommBufferAddr)->MessageLength + NsCommBufferSize = ((EFI_MM_COMMUNICATE_HEADER *)NsCommBufferAddr)->MessageLength +
sizeof (EFI_MM_COMMUNICATE_HEADER); sizeof (EFI_MM_COMMUNICATE_HEADER);
// perform bounds check.
if (NsCommBufferAddr + NsCommBufferSize >=
mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize)
{
return EFI_ACCESS_DENIED;
}
GuidedEventContext = NULL; GuidedEventContext = NULL;
// Now that the secure world can see the normal world buffer, allocate // Now that the secure world can see the normal world buffer, allocate
// memory to copy the communication buffer to the secure world. // memory to copy the communication buffer to the secure world.

View File

@ -106,6 +106,7 @@ StandaloneMmCpuInitialize (
UINTN Index; UINTN Index;
UINTN ArraySize; UINTN ArraySize;
VOID *HobStart; VOID *HobStart;
EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHob;
ASSERT (SystemTable != NULL); ASSERT (SystemTable != NULL);
mMmst = SystemTable; mMmst = SystemTable;
@ -188,6 +189,26 @@ StandaloneMmCpuInitialize (
CopyMem (&mNsCommBuffer, NsCommBufMmramRange, sizeof (EFI_MMRAM_DESCRIPTOR)); CopyMem (&mNsCommBuffer, NsCommBufMmramRange, sizeof (EFI_MMRAM_DESCRIPTOR));
DEBUG ((DEBUG_INFO, "mNsCommBuffer: 0x%016lx - 0x%lx\n", mNsCommBuffer.CpuStart, mNsCommBuffer.PhysicalSize)); DEBUG ((DEBUG_INFO, "mNsCommBuffer: 0x%016lx - 0x%lx\n", mNsCommBuffer.CpuStart, mNsCommBuffer.PhysicalSize));
Status = GetGuidedHobData (
HobStart,
&gEfiMmPeiMmramMemoryReserveGuid,
(VOID **)&MmramRangesHob
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "MmramRangesHob data extraction failed - 0x%x\n", Status));
return Status;
}
//
// As CreateHobListFromBootInfo(), the base and size of buffer shared with
// privileged Secure world software is in second one.
//
CopyMem (
&mSCommBuffer,
&MmramRangesHob->Descriptor[0] + 1,
sizeof (EFI_MMRAM_DESCRIPTOR)
);
// //
// Extract the MP information from the Hoblist // Extract the MP information from the Hoblist
// //

View File

@ -30,6 +30,7 @@ extern EFI_MM_CPU_PROTOCOL mMmCpuState;
// //
extern EFI_MM_COMMUNICATE_HEADER **PerCpuGuidedEventContext; extern EFI_MM_COMMUNICATE_HEADER **PerCpuGuidedEventContext;
extern EFI_MMRAM_DESCRIPTOR mNsCommBuffer; extern EFI_MMRAM_DESCRIPTOR mNsCommBuffer;
extern EFI_MMRAM_DESCRIPTOR mSCommBuffer;
extern MP_INFORMATION_HOB_DATA *mMpInformationHobData; extern MP_INFORMATION_HOB_DATA *mMpInformationHobData;
extern EFI_MM_CONFIGURATION_PROTOCOL mMmConfig; extern EFI_MM_CONFIGURATION_PROTOCOL mMmConfig;