]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / SmmCpuMemoryManagement.c
index 684b14dc285e6286b567613debafe911d050d4da..48f5f954cbc9b03beed8a9661f6090ab74cc1438 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
-Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -38,6 +38,23 @@ PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = {
   {Page1G,  SIZE_1GB, PAGING_1G_ADDRESS_MASK_64},\r
 };\r
 \r
+UINTN  mInternalGr3;\r
+\r
+/**\r
+  Set the internal page table base address.\r
+  If it is non zero, further MemoryAttribute modification will be on this page table.\r
+  If it is zero, further MemoryAttribute modification will be on real page table.\r
+\r
+  @param Cr3 page table base.\r
+**/\r
+VOID\r
+SetPageTableBase (\r
+  IN UINTN   Cr3\r
+  )\r
+{\r
+  mInternalGr3 = Cr3;\r
+}\r
+\r
 /**\r
   Return page table base.\r
 \r
@@ -48,6 +65,9 @@ GetPageTableBase (
   VOID\r
   )\r
 {\r
+  if (mInternalGr3 != 0) {\r
+    return mInternalGr3;\r
+  }\r
   return (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64);\r
 }\r
 \r
@@ -220,6 +240,17 @@ ConvertPageEntryAttribute (
   if ((Attributes & EFI_MEMORY_RO) != 0) {\r
     if (IsSet) {\r
       NewPageEntry &= ~(UINT64)IA32_PG_RW;\r
+      if (mInternalGr3 != 0) {\r
+        // Environment setup\r
+        // ReadOnly page need set Dirty bit for shadow stack\r
+        NewPageEntry |= IA32_PG_D;\r
+        // Clear user bit for supervisor shadow stack\r
+        NewPageEntry &= ~(UINT64)IA32_PG_U;\r
+      } else {\r
+        // Runtime update\r
+        // Clear dirty bit for non shadow stack, to protect RO page.\r
+        NewPageEntry &= ~(UINT64)IA32_PG_D;\r
+      }\r
     } else {\r
       NewPageEntry |= IA32_PG_RW;\r
     }\r
@@ -661,7 +692,59 @@ SmmClearMemoryAttributes (
   return SmmClearMemoryAttributesEx (BaseAddress, Length, Attributes, NULL);\r
 }\r
 \r
+/**\r
+  Set ShadowStack memory.\r
+\r
+  @param[in]  Cr3              The page table base address.\r
+  @param[in]  BaseAddress      The physical address that is the start address of a memory region.\r
+  @param[in]  Length           The size in bytes of the memory region.\r
+\r
+  @retval EFI_SUCCESS           The shadow stack memory is set.\r
+**/\r
+EFI_STATUS\r
+SetShadowStack (\r
+  IN  UINTN                                      Cr3,\r
+  IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,\r
+  IN  UINT64                                     Length\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  SetPageTableBase (Cr3);\r
+\r
+  Status = SmmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_RO);\r
+\r
+  SetPageTableBase (0);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Set not present memory.\r
+\r
+  @param[in]  Cr3              The page table base address.\r
+  @param[in]  BaseAddress      The physical address that is the start address of a memory region.\r
+  @param[in]  Length           The size in bytes of the memory region.\r
 \r
+  @retval EFI_SUCCESS           The not present memory is set.\r
+**/\r
+EFI_STATUS\r
+SetNotPresentPage (\r
+  IN  UINTN                                      Cr3,\r
+  IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,\r
+  IN  UINT64                                     Length\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  SetPageTableBase (Cr3);\r
+\r
+  Status = SmmSetMemoryAttributes (BaseAddress, Length, EFI_MEMORY_RP);\r
+\r
+  SetPageTableBase (0);\r
+\r
+  return Status;\r
+}\r
 \r
 /**\r
   Retrieves a pointer to the system configuration table from the SMM System Table\r