diff options
| author | Gowtham Manikandan <gowthammanikandan@ami.com> | 2026-08-24 14:33:13 -0700 |
|---|---|---|
| committer | Ard Biesheuvel <ardb@kernel.org> | 2026-09-02 10:52:17 +0200 |
| commit | 046b1471e1688e6c756a17fbe9c4057701a0c383 (patch) | |
| tree | 9382285e2e54a02b6434f07ed32b37ed5524f07d | |
| parent | 73075417b0bc6d3ec40e8ec060f858bc7036954b (diff) | |
| download | edk2-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>
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
|
