UefiCpuPkg/PiSmmCpu: Check EFI_RUNTIME_RO in UEFI mem attrib table.
authorJiewen Yao <jiewen.yao@intel.com>
Wed, 22 Nov 2017 15:11:54 +0000 (23:11 +0800)
committerJiewen Yao <jiewen.yao@intel.com>
Thu, 26 Jul 2018 14:51:26 +0000 (22:51 +0800)
It treats the UEFI runtime page with EFI_MEMORY_RO attribute as
invalid SMM communication buffer.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c

index 1d01659..e3c7cff 100644 (file)
@@ -28,6 +28,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/SmmMemoryAttribute.h>\r
 \r
 #include <Guid/AcpiS3Context.h>\r
+#include <Guid/MemoryAttributesTable.h>\r
 #include <Guid/PiSmmMemoryAttributesTable.h>\r
 \r
 #include <Library/BaseLib.h>\r
@@ -45,6 +46,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiRuntimeServicesTableLib.h>\r
 #include <Library/DebugAgentLib.h>\r
+#include <Library/UefiLib.h>\r
 #include <Library/HobLib.h>\r
 #include <Library/LocalApicLib.h>\r
 #include <Library/UefiCpuLib.h>\r
index 52d8c55..a7fb7b0 100644 (file)
   gEfiAcpi20TableGuid                      ## SOMETIMES_CONSUMES ## SystemTable\r
   gEfiAcpi10TableGuid                      ## SOMETIMES_CONSUMES ## SystemTable\r
   gEdkiiPiSmmMemoryAttributesTableGuid     ## CONSUMES ## SystemTable\r
+  gEfiMemoryAttributesTableGuid            ## CONSUMES ## SystemTable\r
 \r
 [FeaturePcd]\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug                         ## CONSUMES\r
index b2ace63..7d99f23 100644 (file)
@@ -20,9 +20,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define EFI_MEMORY_INITIALIZED  0x0200000000000000ULL\r
 #define EFI_MEMORY_TESTED       0x0400000000000000ULL\r
 \r
-#define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \\r
-  ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size)))\r
-\r
 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \\r
   ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))\r
 \r
@@ -33,6 +30,8 @@ UINTN                 mUefiDescriptorSize;
 EFI_GCD_MEMORY_SPACE_DESCRIPTOR   *mGcdMemSpace       = NULL;\r
 UINTN                             mGcdMemNumberOfDesc = 0;\r
 \r
+EFI_MEMORY_ATTRIBUTES_TABLE  *mUefiMemoryAttributesTable = NULL;\r
+\r
 PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = {\r
   {Page4K,  SIZE_4KB, PAGING_4K_ADDRESS_MASK_64},\r
   {Page2M,  SIZE_2MB, PAGING_2M_ADDRESS_MASK_64},\r
@@ -1086,6 +1085,26 @@ GetGcdMemoryMap (
   gBS->FreePool (MemSpaceMap);\r
 }\r
 \r
+/**\r
+  Get UEFI MemoryAttributesTable.\r
+**/\r
+VOID\r
+GetUefiMemoryAttributesTable (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_MEMORY_ATTRIBUTES_TABLE  *MemoryAttributesTable;\r
+  UINTN                        MemoryAttributesTableSize;\r
+\r
+  Status = EfiGetSystemConfigurationTable (&gEfiMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable);\r
+  if (!EFI_ERROR (Status)) {\r
+    MemoryAttributesTableSize = sizeof(EFI_MEMORY_ATTRIBUTES_TABLE) + MemoryAttributesTable->DescriptorSize * MemoryAttributesTable->NumberOfEntries;\r
+    mUefiMemoryAttributesTable = AllocateCopyPool (MemoryAttributesTableSize, MemoryAttributesTable);\r
+    ASSERT (mUefiMemoryAttributesTable != NULL);\r
+  }\r
+}\r
+\r
 /**\r
   This function caches the UEFI memory map information.\r
 **/\r
@@ -1150,6 +1169,11 @@ GetUefiMemoryMap (
   // Get additional information from GCD memory map.\r
   //\r
   GetGcdMemoryMap ();\r
+\r
+  //\r
+  // Get UEFI memory attributes table.\r
+  //\r
+  GetUefiMemoryAttributesTable ();\r
 }\r
 \r
 /**\r
@@ -1168,6 +1192,7 @@ SetUefiMemMapAttributes (
   EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
   UINTN                 MemoryMapEntryCount;\r
   UINTN                 Index;\r
+  EFI_MEMORY_DESCRIPTOR *Entry;\r
 \r
   DEBUG ((DEBUG_INFO, "SetUefiMemMapAttributes\n"));\r
 \r
@@ -1218,6 +1243,35 @@ SetUefiMemMapAttributes (
   //\r
   // Do not free mGcdMemSpace, it will be checked in IsSmmCommBufferForbiddenAddress().\r
   //\r
+\r
+  //\r
+  // Set UEFI runtime memory with EFI_MEMORY_RO as not present.\r
+  //\r
+  if (mUefiMemoryAttributesTable != NULL) {\r
+    Entry = (EFI_MEMORY_DESCRIPTOR *)(mUefiMemoryAttributesTable + 1);\r
+    for (Index = 0; Index < mUefiMemoryAttributesTable->NumberOfEntries; Index++) {\r
+      if (Entry->Type == EfiRuntimeServicesCode || Entry->Type == EfiRuntimeServicesData) {\r
+        if ((Entry->Attribute & EFI_MEMORY_RO) != 0) {\r
+          Status = SmmSetMemoryAttributes (\r
+                     Entry->PhysicalStart,\r
+                     EFI_PAGES_TO_SIZE((UINTN)Entry->NumberOfPages),\r
+                     EFI_MEMORY_RP\r
+                     );\r
+          DEBUG ((\r
+            DEBUG_INFO,\r
+            "UefiMemoryAttribute protection: 0x%lx - 0x%lx %r\n",\r
+            Entry->PhysicalStart,\r
+            Entry->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE((UINTN)Entry->NumberOfPages),\r
+            Status\r
+            ));\r
+        }\r
+      }\r
+      Entry = NEXT_MEMORY_DESCRIPTOR (Entry, mUefiMemoryAttributesTable->DescriptorSize);\r
+    }\r
+  }\r
+  //\r
+  // Do not free mUefiMemoryAttributesTable, it will be checked in IsSmmCommBufferForbiddenAddress().\r
+  //\r
 }\r
 \r
 /**\r
@@ -1236,6 +1290,7 @@ IsSmmCommBufferForbiddenAddress (
   EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
   UINTN                 MemoryMapEntryCount;\r
   UINTN                 Index;\r
+  EFI_MEMORY_DESCRIPTOR *Entry;\r
 \r
   if (mUefiMemoryMap != NULL) {\r
     MemoryMap = mUefiMemoryMap;\r
@@ -1260,6 +1315,20 @@ IsSmmCommBufferForbiddenAddress (
     }\r
   }\r
 \r
+  if (mUefiMemoryAttributesTable != NULL) {\r
+    Entry = (EFI_MEMORY_DESCRIPTOR *)(mUefiMemoryAttributesTable + 1);\r
+    for (Index = 0; Index < mUefiMemoryAttributesTable->NumberOfEntries; Index++) {\r
+      if (Entry->Type == EfiRuntimeServicesCode || Entry->Type == EfiRuntimeServicesData) {\r
+        if ((Entry->Attribute & EFI_MEMORY_RO) != 0) {\r
+          if ((Address >= Entry->PhysicalStart) &&\r
+              (Address < Entry->PhysicalStart + LShiftU64 (Entry->NumberOfPages, EFI_PAGE_SHIFT))) {\r
+            return TRUE;\r
+          }\r
+          Entry = NEXT_MEMORY_DESCRIPTOR (Entry, mUefiMemoryAttributesTable->DescriptorSize);\r
+        }\r
+      }\r
+    }\r
+  }\r
   return FALSE;\r
 }\r
 \r