StandaloneMmPkg: MmCommunicationDxe: Add integer overflow check

`ProcessCommunicationBuffer()` computes BufferSize by adding a fixed
offset (24 bytes) to an attacker-controlled MessageLength (UINT64):

`BufferSize = OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) +
CommunicateHeader->MessageLength;`

When `MessageLength >= 0xFFFFFFFFFFFFFFE8`, the addition wraps to a small
value (0–23 bytes) after UINTN truncation.

The subsequent bounds check evaluates FALSE on the wrapped value,
bypassing size validation and allowing CopyMem to proceed with a
corrupted size into the fixed MM communication buffer.

This change added an overflow check before the addition - rejects with
EFI_INVALID_PARAMETER if `MessageLength` is greater than `MAX_UINTN -
OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data).`

Co-authored-by: Gowtham Manikandan <gowthammanikandan@ami.com>
Signed-off-by: Kun Qin <kun.qin@microsoft.com>
This commit is contained in:
Kun Qin 2026-08-24 14:29:20 -07:00
parent eae5888e47
commit 6a55e01aba
3 changed files with 13 additions and 3 deletions

View file

@ -102,13 +102,18 @@ ProcessCommunicationBuffer (
CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;
if (CompareGuid (&CommunicateHeader->HeaderGuid, &gEfiMmCommunicateHeaderV3Guid)) {
CommunicateHeaderV3 = (EFI_MM_COMMUNICATE_HEADER_V3 *)CommBuffer;
if (CommunicateHeaderV3->BufferSize < sizeof (EFI_MM_COMMUNICATE_HEADER_V3) + CommunicateHeaderV3->MessageSize) {
Status = SafeUintnAdd (sizeof (EFI_MM_COMMUNICATE_HEADER_V3), CommunicateHeaderV3->MessageSize, &BufferSize);
if (EFI_ERROR (Status) || (CommunicateHeaderV3->BufferSize < BufferSize)) {
return EFI_INVALID_PARAMETER;
}
BufferSize = ((EFI_MM_COMMUNICATE_HEADER_V3 *)CommBuffer)->BufferSize;
} else {
BufferSize = OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data) + CommunicateHeader->MessageLength;
Status = SafeUintnAdd (OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data), (UINTN)CommunicateHeader->MessageLength, &BufferSize);
if (EFI_ERROR (Status)) {
return EFI_INVALID_PARAMETER;
}
}
if (BufferSize > EFI_PAGES_TO_SIZE (mMmCommonBuffer.NumberOfPages)) {
@ -141,6 +146,10 @@ ProcessCommunicationBuffer (
return EFI_UNSUPPORTED;
}
if (CommonBufferStatus->ReturnBufferSize > BufferSize) {
return EFI_BAD_BUFFER_SIZE;
}
//
// Copy the returned data to the non-mmram buffer (CommBuffer)
//

View file

@ -19,6 +19,7 @@
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiRuntimeLib.h>
#include <Library/ReportStatusCodeLib.h>
#include <Library/SafeIntLib.h>
#include <Protocol/SmmControl2.h>
#include <Protocol/MmCommunication3.h>

View file

@ -38,7 +38,7 @@
UefiLib
UefiRuntimeLib
ReportStatusCodeLib
SafeIntLib
[Guids]
gMmCommBufferHobGuid
gEfiEventVirtualAddressChangeGuid