summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGowtham Manikandan <gowthammanikandan@ami.com>2026-08-24 14:33:13 -0700
committerArd Biesheuvel <ardb@kernel.org>2026-09-02 10:52:17 +0200
commit046b1471e1688e6c756a17fbe9c4057701a0c383 (patch)
tree9382285e2e54a02b6434f07ed32b37ed5524f07d
parent73075417b0bc6d3ec40e8ec060f858bc7036954b (diff)
downloadedk2-046b1471e1688e6c756a17fbe9c4057701a0c383.tar.gz
edk2-046b1471e1688e6c756a17fbe9c4057701a0c383.zip
StandaloneMmPkg: MmCommunicationDxe: Created GoogleTests
This change adds 5 unit tests to cover the incoming buffer validation routine in the MmCommunicate function. Signed-off-by: Kun Qin <kun.qin@microsoft.com>
-rw-r--r--StandaloneMmPkg/Drivers/MmCommunicationDxe/GoogleTest/MmCommunicationDxeGoogleTest.cpp206
-rw-r--r--StandaloneMmPkg/Drivers/MmCommunicationDxe/GoogleTest/MmCommunicationDxeGoogleTest.inf51
-rw-r--r--StandaloneMmPkg/StandaloneMmPkg.ci.yaml4
-rw-r--r--StandaloneMmPkg/Test/StandaloneMmPkgHostTest.dsc39
4 files changed, 298 insertions, 2 deletions
diff --git a/StandaloneMmPkg/Drivers/MmCommunicationDxe/GoogleTest/MmCommunicationDxeGoogleTest.cpp b/StandaloneMmPkg/Drivers/MmCommunicationDxe/GoogleTest/MmCommunicationDxeGoogleTest.cpp
new file mode 100644
index 0000000000..2440cef69d
--- /dev/null
+++ b/StandaloneMmPkg/Drivers/MmCommunicationDxe/GoogleTest/MmCommunicationDxeGoogleTest.cpp
@@ -0,0 +1,206 @@
+/** @file
+ GoogleTest for MmCommunicationDxe.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/GoogleTestLib.h>
+
+extern "C" {
+ #include <Uefi.h>
+ #include <Library/BaseLib.h>
+ #include <Library/BaseMemoryLib.h>
+ #include <Protocol/MmControl.h>
+ #include <Protocol/SmmControl2.h>
+ #include <Protocol/MmCommunication.h>
+ #include <Pi/PiMultiPhase.h>
+ #include <Guid/MmCommBuffer.h>
+
+ //
+ // Declare the function under test (defined in MmCommunicationDxe.c)
+ //
+ EFI_STATUS
+ EFIAPI
+ ProcessCommunicationBuffer (
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommSize OPTIONAL
+ );
+
+ //
+ // Globals defined in MmCommunicationDxe.c that we need to set up
+ //
+ extern MM_COMM_BUFFER mMmCommonBuffer;
+ extern EFI_SMM_CONTROL2_PROTOCOL *mSmmControl2;
+}
+
+////////////////////////////////////////////////////////////////////////
+// Symbol Definitions
+// These functions are not directly under test - but required to compile
+////////////////////////////////////////////////////////////////////////
+
+//
+// Mock Trigger function for SmmControl2 protocol
+//
+static EFI_STATUS EFIAPI
+MockTrigger (
+ IN CONST EFI_MM_CONTROL_PROTOCOL *This,
+ IN OUT UINT8 *CommandPort OPTIONAL,
+ IN OUT UINT8 *DataPort OPTIONAL,
+ IN BOOLEAN Periodic OPTIONAL,
+ IN UINTN ActivationInterval OPTIONAL
+ )
+{
+ return EFI_SUCCESS;
+}
+
+//
+// Mock Deactivate (Clear) function
+//
+static EFI_STATUS EFIAPI
+MockClear (
+ IN CONST EFI_MM_CONTROL_PROTOCOL *This,
+ IN BOOLEAN Periodic OPTIONAL
+ )
+{
+ return EFI_SUCCESS;
+}
+
+////////////////////////////////////////////////////////////////////////
+// Defines
+////////////////////////////////////////////////////////////////////////
+
+#define COMM_BUFFER_PAGES 4 // 16 KiB common buffer
+#define COMM_BUFFER_SIZE EFI_PAGES_TO_SIZE (COMM_BUFFER_PAGES)
+
+////////////////////////////////////////////////////////////////////////
+// MmCommunicationOverflowTest Tests
+////////////////////////////////////////////////////////////////////////
+
+class MmCommunicationOverflowTest : public ::testing::Test {
+public:
+ UINT8 mCommonBuffer[COMM_BUFFER_SIZE];
+ MM_COMM_BUFFER_STATUS mCommonBufferStatus;
+ EFI_MM_CONTROL_PROTOCOL mMockSmmControl2;
+ UINT8 mCommBuffer[COMM_BUFFER_SIZE];
+
+protected:
+ virtual void
+ SetUp (
+ )
+ {
+ ZeroMem (mCommonBuffer, sizeof (mCommonBuffer));
+ ZeroMem (&mCommonBufferStatus, sizeof (mCommonBufferStatus));
+ ZeroMem (mCommBuffer, sizeof (mCommBuffer));
+
+ // Set up the global MM common buffer struct
+ mMmCommonBuffer.PhysicalStart = (EFI_PHYSICAL_ADDRESS)(UINTN)mCommonBuffer;
+ mMmCommonBuffer.NumberOfPages = COMM_BUFFER_PAGES;
+ mMmCommonBuffer.Status = (EFI_PHYSICAL_ADDRESS)(UINTN)&mCommonBufferStatus;
+
+ // Set up the mock SmmControl2 protocol
+ mMockSmmControl2.Trigger = MockTrigger;
+ mMockSmmControl2.Clear = MockClear;
+ mMockSmmControl2.MinimumTriggerPeriod = 0;
+ mSmmControl2 = &mMockSmmControl2;
+ }
+
+ virtual void
+ TearDown (
+ )
+ {
+ // Clean up any resources or variables
+ }
+};
+
+// Test Description:
+// Normal V1 path works with small MessageLength
+TEST_F (MmCommunicationOverflowTest, V1NormalMessageLengthSucceeds) {
+ EFI_MM_COMMUNICATE_HEADER *Header = (EFI_MM_COMMUNICATE_HEADER *)mCommBuffer;
+
+ ZeroMem (&Header->HeaderGuid, sizeof (EFI_GUID));
+ Header->MessageLength = 64;
+
+ UINTN CommSize = OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data) + 64;
+
+ EFI_STATUS Status = ProcessCommunicationBuffer (mCommBuffer, &CommSize);
+
+ // BufferSize = 24 + 64 = 88, well within 16KiB
+ ASSERT_EQ (Status, EFI_SUCCESS);
+}
+
+// Test Description:
+// V1 path - CWE-190 integer overflow wraps BufferSize to 0.
+// MessageLength = MAX_UINT64 - OFFSET_OF(...) + 1 causes addition to wrap to 0.
+TEST_F (MmCommunicationOverflowTest, V1MessageLengthOverflowWrapsToZero) {
+ EFI_MM_COMMUNICATE_HEADER *Header = (EFI_MM_COMMUNICATE_HEADER *)mCommBuffer;
+
+ ZeroMem (&Header->HeaderGuid, sizeof (EFI_GUID));
+
+ //
+ // Craft MessageLength so that OFFSET_OF(Data) + MessageLength = 0 (wraps)
+ // OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) = 0x18 (24)
+ // MAX_UINT64 - 0x18 + 1 = 0xFFFFFFFFFFFFFFE8
+ //
+ Header->MessageLength = MAX_UINT64 - OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data) + 1;
+
+ EFI_STATUS Status = ProcessCommunicationBuffer (mCommBuffer, NULL);
+
+ // Without fix: BufferSize wraps to 0, passes bounds check, returns EFI_SUCCESS
+ ASSERT_EQ (Status, EFI_INVALID_PARAMETER);
+}
+
+// Test Description:
+// V1 path - Integer overflow wraps BufferSize to a small nonzero value (0x08)
+TEST_F (MmCommunicationOverflowTest, V1MessageLengthOverflowWrapsToSmallValue) {
+ EFI_MM_COMMUNICATE_HEADER *Header = (EFI_MM_COMMUNICATE_HEADER *)mCommBuffer;
+
+ ZeroMem (&Header->HeaderGuid, sizeof (EFI_GUID));
+
+ //
+ // MessageLength = MAX_UINT64 - 0x18 + 1 + 8 = MAX_UINT64 - 0x0F
+ // Result: OFFSET_OF(Data) + MessageLength = 0x18 + (MAX_UINT64 - 0x0F) = 0x08 (wraps)
+ //
+ Header->MessageLength = MAX_UINT64 - OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data) + 1 + 8;
+
+ EFI_STATUS Status = ProcessCommunicationBuffer (mCommBuffer, NULL);
+
+ // Without fix: BufferSize = 8, passes bounds check, returns EFI_SUCCESS
+ ASSERT_EQ (Status, EFI_INVALID_PARAMETER);
+}
+
+// Test Description:
+// V1 path - Large MessageLength without overflow is rejected by bounds check
+TEST_F (MmCommunicationOverflowTest, V1LargeMessageLengthWithoutOverflowIsRejected) {
+ EFI_MM_COMMUNICATE_HEADER *Header = (EFI_MM_COMMUNICATE_HEADER *)mCommBuffer;
+
+ ZeroMem (&Header->HeaderGuid, sizeof (EFI_GUID));
+
+ //
+ // Set MessageLength larger than common buffer but not large enough to overflow.
+ // BufferSize = 0x18 + 0x10000 = 0x10018, which exceeds 16KiB (0x4000).
+ //
+ Header->MessageLength = 0x10000;
+
+ EFI_STATUS Status = ProcessCommunicationBuffer (mCommBuffer, NULL);
+
+ ASSERT_EQ (Status, EFI_INVALID_PARAMETER);
+}
+
+// Test Description:
+// NULL CommBuffer is rejected
+TEST_F (MmCommunicationOverflowTest, NullCommBufferReturnsInvalidParameter) {
+ EFI_STATUS Status = ProcessCommunicationBuffer (NULL, NULL);
+
+ ASSERT_EQ (Status, EFI_INVALID_PARAMETER);
+}
+
+int
+main (
+ int argc,
+ char *argv[]
+ )
+{
+ testing::InitGoogleTest (&argc, argv);
+ return RUN_ALL_TESTS ();
+}
diff --git a/StandaloneMmPkg/Drivers/MmCommunicationDxe/GoogleTest/MmCommunicationDxeGoogleTest.inf b/StandaloneMmPkg/Drivers/MmCommunicationDxe/GoogleTest/MmCommunicationDxeGoogleTest.inf
new file mode 100644
index 0000000000..69bd87b80a
--- /dev/null
+++ b/StandaloneMmPkg/Drivers/MmCommunicationDxe/GoogleTest/MmCommunicationDxeGoogleTest.inf
@@ -0,0 +1,51 @@
+## @file
+# GoogleTest for MmCommunicationDxe.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = MmCommunicationDxeGoogleTest
+ FILE_GUID = 5bf153cc-013c-4c61-95b7-cd86b263bd9f
+ VERSION_STRING = 1.0
+ MODULE_TYPE = HOST_APPLICATION
+
+[Sources]
+ MmCommunicationDxeGoogleTest.cpp
+ ../MmCommunicationDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ StandaloneMmPkg/StandaloneMmPkg.dec
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[LibraryClasses]
+ GoogleTestLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ HobLib
+ MemoryAllocationLib
+ ReportStatusCodeLib
+ UefiBootServicesTableLib
+ UefiLib
+ UefiRuntimeLib
+ SafeIntLib
+[Protocols]
+ gEfiMmCommunication3ProtocolGuid
+ gEfiMmCommunication2ProtocolGuid
+ gEfiMmCommunicationProtocolGuid
+ gEfiSmmControl2ProtocolGuid
+ gEfiSmmAccess2ProtocolGuid
+
+[Guids]
+ gMmCommBufferHobGuid
+ gEfiEventVirtualAddressChangeGuid
+ gEfiMmCommunicateHeaderV3Guid
+
+[BuildOptions]
+ MSFT:*_*_*_CC_FLAGS = /EHsc
diff --git a/StandaloneMmPkg/StandaloneMmPkg.ci.yaml b/StandaloneMmPkg/StandaloneMmPkg.ci.yaml
index 232c60e20f..226b58f1c5 100644
--- a/StandaloneMmPkg/StandaloneMmPkg.ci.yaml
+++ b/StandaloneMmPkg/StandaloneMmPkg.ci.yaml
@@ -28,7 +28,7 @@
## options defined .pytool/Plugin/HostUnitTestCompilerPlugin
"HostUnitTestCompilerPlugin": {
- "DscPath": "" # Don't support this test
+ "DscPath": "Test/StandaloneMmPkgHostTest.dsc"
},
## options defined .pytool/Plugin/CharEncodingCheck
@@ -64,7 +64,7 @@
## options defined .pytool/Plugin/HostUnitTestDscCompleteCheck
"HostUnitTestDscCompleteCheck": {
"IgnoreInf": [""],
- "DscPath": "" # Don't support this test
+ "DscPath": "Test/StandaloneMmPkgHostTest.dsc"
},
## options defined .pytool/Plugin/GuidCheck
diff --git a/StandaloneMmPkg/Test/StandaloneMmPkgHostTest.dsc b/StandaloneMmPkg/Test/StandaloneMmPkgHostTest.dsc
new file mode 100644
index 0000000000..a577196038
--- /dev/null
+++ b/StandaloneMmPkg/Test/StandaloneMmPkgHostTest.dsc
@@ -0,0 +1,39 @@
+## @file
+# StandaloneMmPkgHostTest DSC file used to build host-based unit tests.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+[Defines]
+ PLATFORM_NAME = StandaloneMmPkgHostTest
+ PLATFORM_GUID = A3D4B87C-5E2F-4A19-8C6D-1F7E09B23D56
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/StandaloneMmPkg/HostTest
+ SUPPORTED_ARCHITECTURES = IA32|X64|AARCH64
+ BUILD_TARGETS = NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+
+!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[Components]
+ #
+ # Build HOST_APPLICATION that tests StandaloneMmPkg
+ #
+ StandaloneMmPkg/Drivers/MmCommunicationDxe/GoogleTest/MmCommunicationDxeGoogleTest.inf
+
+[LibraryClasses]
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf