在 12/23/21 7:05 PM, Marvin Häuser 写道:
> On 23.12.21 11:46, Ming Huang wrote:
>>
>> 在 12/16/21 5:15 PM, Marvin Häuser 写道:
>>> Hey all,
>>>
>>>> On 15. Dec 2021, at 16:02, Ming Huang <huangm...@linux.alibaba.com> wrote:
>>>>
>>>>
>>>>
>>>>> On 12/9/21 1:46 AM, Omkar Anand Kulkarni wrote:
>>>>> Hi Ming,
>>>>> Thanks for this patch. This patch helps to resolve Standalone MM issue
>>>>> while exercising RAS use case.
>>>>> Few comments mentioned inline.
>>>>> - Omkar
>>>>>> On 10/15/21 2:39 PM, Ming Huang via groups.io wrote:
>>>>>> 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 <huangm...@linux.alibaba.com>
>>>>>> ---
>>>>>> StandaloneMmPkg/Drivers/StandaloneMmCpu/EventHandle.c | 70
>>>>>> ++++++++++++++++----
>>>>>> StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.c | 21
>>>>>> ++++++
>>>>>> StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.h | 1 +
>>>>>> 3 files changed, 79 insertions(+), 13 deletions(-)
>>>>>> diff --git a/StandaloneMmPkg/Drivers/StandaloneMmCpu/EventHandle.c
>>>>>> b/StandaloneMmPkg/Drivers/StandaloneMmCpu/EventHandle.c
>>>>>> index 5dfaf9d751..63fab1bd78 100644
>>>>>> --- a/StandaloneMmPkg/Drivers/StandaloneMmCpu/EventHandle.c
>>>>>> +++ b/StandaloneMmPkg/Drivers/StandaloneMmCpu/EventHandle.c
>>>>>> @@ -50,6 +50,7 @@ EFI_MM_COMMUNICATE_HEADER
>>>>>> **PerCpuGuidedEventContext = NULL;
>>>>>> // Descriptor with whereabouts of memory used for communication with
>>>>>> the normal world EFI_MMRAM_DESCRIPTOR mNsCommBuffer;
>>>>>> +EFI_MMRAM_DESCRIPTOR mSCommBuffer;
>>>>>> MP_INFORMATION_HOB_DATA *mMpInformationHobData;
>>>>>> @@ -60,6 +61,58 @@ EFI_MM_CONFIGURATION_PROTOCOL mMmConfig =
>>>>>> {
>>>>>> STATIC EFI_MM_ENTRY_POINT mMmEntryPoint = NULL;
>>>>>> +STATIC
>>>>>> +EFI_STATUS
>>>>>> +CheckBufferAddr (
>>>>>> + IN UINTN CommBufferAddr
>>>>>> + )
>>>>>> +{
>>>>>> + UINTN CommBufferSize;
>>>>>> + EFI_STATUS Status;
>>>>>> +
>>>>>> + Status = EFI_SUCCESS;
>>>>>> + if (CommBufferAddr < mNsCommBuffer.PhysicalStart) {
>>>>>> + Status = EFI_ACCESS_DENIED;
>>>>>> + }
>>>>>> +
>>>>>> + if ((CommBufferAddr + sizeof (EFI_MM_COMMUNICATE_HEADER)) >=
>>>>>> + (mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize)) {
>>>>>> + Status = EFI_INVALID_PARAMETER;
>>>>> Single space after "Status = "
>>>> Modify it in v2.
>>>>
>>>>> - Omkar
>>>>>> + }
>>>>>> +
>>>>>> + // Find out the size of the buffer passed CommBufferSize =
>>>>>> + ((EFI_MM_COMMUNICATE_HEADER *) CommBufferAddr)->MessageLength
>>>>>> +
>>>>>> + sizeof (EFI_MM_COMMUNICATE_HEADER);
>>>>>> +
>>>>>> + // perform bounds check.
>>>>>> + if (CommBufferAddr + CommBufferSize >=
>>>>>> + mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize) {
>>>>>> + Status = EFI_ACCESS_DENIED;
>>>>> Single space after "Status = "
>>>> Modify it in v2.
>>>>
>>>>> - Omkar
>>>>>> + }
>>>>>> +
>>>>>> + if (!EFI_ERROR (Status)) {
>>>>> In case of error this function call will not return from here. It will
>>>>> execute the code below comparing the MM Communicate buffer address with
>>>>> the Secure buffer address, which may cause wrong return type being
>>>>> returned. Can you check this, please?
>>>>> - Omkar
>>>>>> + return EFI_SUCCESS;
>>>>>> + }
>>>>>> +
>>>>>> + Status = EFI_SUCCESS;
>>>>>> + if (CommBufferAddr < mSCommBuffer.PhysicalStart) {
>>>>>> + Status = EFI_ACCESS_DENIED;
>>>>>> + }
>>>>>> +
>>>>>> + if ((CommBufferAddr + sizeof (EFI_MM_COMMUNICATE_HEADER)) >=
>>>>>> + (mSCommBuffer.PhysicalStart + mSCommBuffer.PhysicalSize)) {
>>>>>> + Status = EFI_INVALID_PARAMETER;
>>>>>> + }
>>>>>> +
>>>>>> + // perform bounds check.
>>>>>> + if (CommBufferAddr + CommBufferSize >=
>>>>>> + mSCommBuffer.PhysicalStart + mSCommBuffer.PhysicalSize) {
>>>>>> + Status = EFI_ACCESS_DENIED;
>>>>>> + }
>>>>>> +
>>>>>> + return Status;
>>>>>> +}
>>>>>> +
>>>>> CheckBufferAddr() function performs validity and overflow checks on the
>>>>> Communication buffers. These checks are same for both the non-secure
>>>>> MM communicate buffer and secure buffer shared between EL3 and S-EL0. Can
>>>>> this code be combined ( example below)? This will help mitigate the above
>>>>> mentioned return type issue as well.
>>>> Your example is a good idea to solve this case. I may modify it like below
>>>> in v2:
>>>>
>>>> STATIC
>>>> EFI_STATUS
>>>> CheckBufferAddr (
>>>> IN UINTN CommBufferAddr
>>>> )
>>>> {
>>>> UINTN CommBufferSize;
>>>> EFI_STATUS Status;
>>>> UINT64 NsCommBufferEnd;
>>>> UINT64 SCommBufferEnd;
>>>> UINT64 CommBufferEnd;
>>>>
>>>> Status = EFI_SUCCESS;
>>>> NsCommBufferEnd = mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize;
>>>> SCommBufferEnd = mSCommBuffer.PhysicalStart + mSCommBuffer.PhysicalSize;
>>>>
>>>> if ((CommBufferAddr >= mNsCommBuffer.PhysicalStart) &&
>>>> (CommBufferAddr < NsCommBufferEnd)) {
>>>> CommBufferEnd = NsCommBufferEnd;
>>>> } else if ((CommBufferAddr >= mSCommBuffer.PhysicalStart) &&
>>>> (CommBufferAddr <= SCommBufferEnd)) {
>>> I find it odd the check here (lesser-equals) is inconsistent with the check
>>> above (lesser). It’d be caught below anyway, but I’d change this to lesser
>>> to keep the return codes consistent.
>> Should be lesser, modify it in v3.
>>
>>>> CommBufferEnd = SCommBufferEnd;
>>>> } else {
>>>> return EFI_ACCESS_DENIED;
>>>> }
>>>>
>>>> if ((CommBufferAddr + sizeof (EFI_MM_COMMUNICATE_HEADER)) >=
>>>> CommBufferEnd) {
>>> Why is greater-equals used here? MessageLength == 0 is not filtered below,
>>> so this looks odd to be honest, as this is only the theoretical maximum
>>> buffer end.
>>>
>>> How do you know this cannot wraparound? I actually don’t think we do. We do
>>> know it holds that CommBufferAddr <= CommBufferEnd though, so checking
>>> CommBufferEnd - CommBufferAddr < sizeof (EFI_MM_COMMUNICATE_HEADER) would
>>> give you that for free, if we assume the UINT64 variables above are
>>> actually bounded by UINTN, which seems reasonable - could ASSERT.
>> In my mind, (CommBufferAddr + sizeof (EFI_MM_COMMUNICATE_HEADER)) >=
>> CommBufferEnd)
>> is the same with: CommBufferEnd - CommBufferAddr < sizeof
>> (EFI_MM_COMMUNICATE_HEADER)
>
> Okay, assume:
> CommBufferEnd = MAX_UINTN
> CommBufferAddr = MAX_UINTN - 1 (MAX_UINTN - 1 < MAX_UINTN, so the check above
> would pass)
> sizeof (EFI_MM_COMMUNICATE_HEADER) = 16 (should be accurate for 64-bit
> architectures)
>
> Then (assume implicit mod 2^N on both sides due to bounded integers!):
> (CommBufferAddr + sizeof (EFI_MM_COMMUNICATE_HEADER)) >= CommBufferEnd) <=>
> ((MAX_UINTN - 1) + 16) >= MAX_UINTN <=> MAX_UINTN + 15 >= MAX_UINTN
> <=>(wraparound!!) 14 >= MAX_UINTN <=> FALSE
>
> And (assume implicit mod 2^N on both sides due to bounded integers!):
> CommBufferEnd - CommBufferAddr < sizeof (EFI_MM_COMMUNICATE_HEADER) <=>
> MAX_UINTN - (MAX_UINTN - 1) < 16 <=> 1 < 16 <=> TRUE
>
> Due to wraparound semantics and the knowledge derived by the if-checks above
> they are by no means the same. The left term of the first equation can wrap
> around (or it cannot, but then we need some concrete proof that it cannot),
> and the left term of the second equation obviously cannot (directly follows
> from the if statements before).
I got it. Thanks for your proper comments.
I may modify it like below in v3:
----------------------------------------
STATIC
EFI_STATUS
CheckBufferAddr (
IN UINTN BufferAddr
)
{
UINTN BufferSize;
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_INVALID_PARAMETER;
}
// Find out the size of the buffer passed
BufferSize = ((EFI_MM_COMMUNICATE_HEADER *) BufferAddr)->MessageLength +
sizeof (EFI_MM_COMMUNICATE_HEADER);
// perform bounds check.
if ((CommBufferEnd - BufferAddr) < BufferSize) {
return EFI_ACCESS_DENIED;
}
return EFI_SUCCESS;
}
----------------------------------------
- Ming
>
>>> Alternatively, you could not store the maximum buffer end but the maximum
>>> buffer size, so the additions of the buffer start would just vanish. This
>>> might be more readable too I think.
>> As CommBufferAddr may be not at the begin of communicate buffer,
>> so check size with the maximum buffer size is not enough.
>>
>>>> Status = EFI_INVALID_PARAMETER;
>>> Why is there no return here? This can proceed when the buffer cannot fit
>>> this header, and yet below the header is dereferenced.
>> Modify it in v3.
>>
>>>> }
>>>>
>>>> // Find out the size of the buffer passed
>>>> CommBufferSize = ((EFI_MM_COMMUNICATE_HEADER *)
>>>> CommBufferAddr)->MessageLength +
>>>> sizeof (EFI_MM_COMMUNICATE_HEADER);
>>> Same wraparound concern, same suggestion for solving it.
>>>
>>>> // perform bounds check.
>>>> if (CommBufferAddr + CommBufferSize >= CommBufferEnd) {
>>>> Status = EFI_ACCESS_DENIED;
>>> It’s obviously not bad here, but for consistency’s sake, to mitigate bugs
>>> introduced by future changes, and readability, I’d return here and just
>>> return EFI_SUCCESS below, removing the code requirement of keeping Status
>>> consistent with the check results.
>> Modify it in v3.
>
> Thanks for the modifications.
>
> Best regards,
> Marvin
>
>>
>> - Ming
>>
>>> Finally, I really believe this kind of function should be abstracted in a
>>> way that it can be consumed by all places that accept any sort of
>>> communication buffer. Buffer validity checking is too critical than to
>>> duplicate it in every consumer.
>>>
>>> Thanks!
>>>
>>> Best regards,
>>> Marvin
>>>
>>>> }
>>>>
>>>> return Status;
>>>> }
>>>>
>>>> - Ming
>>>>
>>>>> STATIC
>>>>> EFI_STATUS
>>>>> CheckBufferAddr (
>>>>> IN UINTN CommBufferAddr
>>>>> )
>>>>> {
>>>>> UINTN CommBufferSize;
>>>>> EFI_STATUS Status;
>>>>> EFI_MMRAM_DESCRIPTOR CommBuffer;
>>>>> if (CommBufferAddr < mNsCommBuffer.PhysicalStart ||
>>>>> CommBufferAddr > (mNsCommBuffer.PhysicalStart +
>>>>> mNsCommBuffer.PhysicalSize)) {
>>>>> CommBuffer = mSCommBuffer;
>>>>> } else {
>>>>> CommBuffer = mNsCommBuffer;
>>>>> }
>>>>> if (CommBufferAddr < CommBuffer.PhysicalStart) {
>>>>> Status = EFI_ACCESS_DENIED;
>>>>> }
>>>>> if ((CommBufferAddr + sizeof (EFI_MM_COMMUNICATE_HEADER)) >=
>>>>> (CommBuffer.PhysicalStart + CommBuffer.PhysicalSize)) {
>>>>> Status = EFI_INVALID_PARAMETER;
>>>>> }
>>>>> // Find out the size of the buffer passed
>>>>> CommBufferSize = ((EFI_MM_COMMUNICATE_HEADER *)
>>>>> CommBufferAddr)->MessageLength +
>>>>> sizeof (EFI_MM_COMMUNICATE_HEADER);
>>>>> // perform bounds check.
>>>>> if (CommBufferAddr + CommBufferSize >=
>>>>> CommBuffer.PhysicalStart + CommBuffer.PhysicalSize) {
>>>>> Status = EFI_ACCESS_DENIED;
>>>>> }
>>>>> return Status;
>>>>> }
>>>>> - Omkar
>>>>>> /**
>>>>>> The PI Standalone MM entry point for the TF-A CPU driver.
>>>>>> @@ -104,25 +157,16 @@ PiMmStandaloneArmTfCpuDriverEntry (
>>>>>> return EFI_INVALID_PARAMETER;
>>>>>> }
>>>>>> - if (NsCommBufferAddr < mNsCommBuffer.PhysicalStart) {
>>>>>> - return EFI_ACCESS_DENIED;
>>>>>> - }
>>>>>> -
>>>>>> - if ((NsCommBufferAddr + sizeof (EFI_MM_COMMUNICATE_HEADER)) >=
>>>>>> - (mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize)) {
>>>>>> - return EFI_INVALID_PARAMETER;
>>>>>> + Status = CheckBufferAddr (NsCommBufferAddr); if (EFI_ERROR (Status))
>>>>>> + {
>>>>>> + DEBUG ((DEBUG_ERROR, "Check Buffer failed: %r\n", Status));
>>>>>> + return Status;
>>>>>> }
>>>>>> // Find out the size of the buffer passed
>>>>>> NsCommBufferSize = ((EFI_MM_COMMUNICATE_HEADER *)
>>>>>> NsCommBufferAddr)->MessageLength +
>>>>>> sizeof (EFI_MM_COMMUNICATE_HEADER);
>>>>>> - // perform bounds check.
>>>>>> - if (NsCommBufferAddr + NsCommBufferSize >=
>>>>>> - mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize) {
>>>>>> - return EFI_ACCESS_DENIED;
>>>>>> - }
>>>>>> -
>>>>>> GuidedEventContext = NULL;
>>>>>> // Now that the secure world can see the normal world buffer, allocate
>>>>>> // memory to copy the communication buffer to the secure world.
>>>>>> diff --git
>>>>>> a/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.c
>>>>>> b/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.c
>>>>>> index fd9c59b4da..96dad20dd1 100644
>>>>>> --- a/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.c
>>>>>> +++ b/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.c
>>>>>> @@ -107,6 +107,7 @@ StandaloneMmCpuInitialize (
>>>>>> UINTN Index;
>>>>>> UINTN ArraySize;
>>>>>> VOID *HobStart;
>>>>>> + EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHob;
>>>>>> ASSERT (SystemTable != NULL);
>>>>>> mMmst = SystemTable;
>>>>>> @@ -186,6 +187,26 @@ StandaloneMmCpuInitialize (
>>>>>> CopyMem (&mNsCommBuffer, NsCommBufMmramRange,
>>>>>> sizeof(EFI_MMRAM_DESCRIPTOR));
>>>>>> 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,
>>>>> Can this be changed to
>>>>> &MmramRangesHob->Descriptor[1],
>>>>> - Omkar
>>>>>> + sizeof(EFI_MMRAM_DESCRIPTOR)
>>>>>> + );
>>>>>> +
>>>>>> //
>>>>>> // Extract the MP information from the Hoblist
>>>>>> //
>>>>>> diff --git
>>>>>> a/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.h
>>>>>> b/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.h
>>>>>> index 2c96439c15..2e03b20d85 100644
>>>>>> --- a/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.h
>>>>>> +++ b/StandaloneMmPkg/Drivers/StandaloneMmCpu/StandaloneMmCpu.h
>>>>>> @@ -30,6 +30,7 @@ extern EFI_MM_CPU_PROTOCOL mMmCpuState; //
>>>>>> extern EFI_MM_COMMUNICATE_HEADER **PerCpuGuidedEventContext;
>>>>>> extern EFI_MMRAM_DESCRIPTOR mNsCommBuffer;
>>>>>> +extern EFI_MMRAM_DESCRIPTOR mSCommBuffer;
>>>>>> extern MP_INFORMATION_HOB_DATA *mMpInformationHobData;
>>>>>> extern EFI_MM_CONFIGURATION_PROTOCOL mMmConfig;
>>>>>> --
>>>>>> 2.17.1
>>>>> IMPORTANT NOTICE: The contents of this email and any attachments are
>>>>> confidential and may also be privileged. If you are not the intended
>>>>> recipient, please notify the sender immediately and do not disclose the
>>>>> contents to any other person, use it for any purpose, or store or copy
>>>>> the information in any medium. Thank you.
>>>>
>>>>
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#85206): https://edk2.groups.io/g/devel/message/85206
Mute This Topic: https://groups.io/mt/86334815/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-