]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Mem/HeapGuard.c
MdeModulePkg/Core: allow HeapGuard even before CpuArchProtocol installed
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Mem / HeapGuard.c
index 392aeb8a0210f1cee6cf94029efe16e9890ca818..f6068c459ca75385c242da9639146a67508c5bba 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   UEFI Heap Guard functions.\r
 \r
-Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2017-2018, 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
@@ -225,8 +225,8 @@ FindGuardedMemoryMap (
   //\r
   // Adjust current map table depth according to the address to access\r
   //\r
-  while (mMapLevel < GUARDED_HEAP_MAP_TABLE_DEPTH\r
-         &&\r
+  while (AllocMapUnit &&\r
+         mMapLevel < GUARDED_HEAP_MAP_TABLE_DEPTH &&\r
          RShiftU64 (\r
            Address,\r
            mLevelShift[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - 1]\r
@@ -576,6 +576,10 @@ SetGuardPage (
   IN  EFI_PHYSICAL_ADDRESS      BaseAddress\r
   )\r
 {\r
+  if (gCpu == NULL) {\r
+    return;\r
+  }\r
+\r
   //\r
   // Set flag to make sure allocating memory without GUARD for page table\r
   // operation; otherwise infinite loops could be caused.\r
@@ -606,6 +610,10 @@ UnsetGuardPage (
 {\r
   UINT64          Attributes;\r
 \r
+  if (gCpu == NULL) {\r
+    return;\r
+  }\r
+\r
   //\r
   // Once the Guard page is unset, it will be freed back to memory pool. NX\r
   // memory protection must be restored for this page if NX is enabled for free\r
@@ -652,7 +660,7 @@ IsMemoryTypeToGuard (
   UINT64 ConfigBit;\r
   BOOLEAN     InSmm;\r
 \r
-  if (gCpu == NULL || AllocateType == AllocateAddress) {\r
+  if (AllocateType == AllocateAddress) {\r
     return FALSE;\r
   }\r
 \r
@@ -728,6 +736,20 @@ IsPageTypeToGuard (
   return IsMemoryTypeToGuard (MemoryType, AllocateType, GUARD_HEAP_TYPE_PAGE);\r
 }\r
 \r
+/**\r
+  Check to see if the heap guard is enabled for page and/or pool allocation.\r
+\r
+  @return TRUE/FALSE.\r
+**/\r
+BOOLEAN\r
+IsHeapGuardEnabled (\r
+  VOID\r
+  )\r
+{\r
+  return IsMemoryTypeToGuard (EfiMaxMemoryType, AllocateAnyPages,\r
+                              GUARD_HEAP_TYPE_POOL|GUARD_HEAP_TYPE_PAGE);\r
+}\r
+\r
 /**\r
   Set head Guard and tail Guard for the given memory range.\r
 \r
@@ -890,11 +912,8 @@ AdjustMemoryS (
   }\r
 \r
   Target = Start + Size - SizeRequested;\r
-\r
-  //\r
-  // At least one more page needed for Guard page.\r
-  //\r
-  if (Size < (SizeRequested + EFI_PAGES_TO_SIZE (1))) {\r
+  ASSERT (Target >= Start);\r
+  if (Target == 0) {\r
     return 0;\r
   }\r
 \r
@@ -1153,6 +1172,128 @@ CoreConvertPagesWithGuard (
   return CoreConvertPages (Start, NumberOfPages, NewType);\r
 }\r
 \r
+/**\r
+  Set all Guard pages which cannot be set before CPU Arch Protocol installed.\r
+**/\r
+VOID\r
+SetAllGuardPages (\r
+  VOID\r
+  )\r
+{\r
+  UINTN     Entries[GUARDED_HEAP_MAP_TABLE_DEPTH];\r
+  UINTN     Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH];\r
+  UINTN     Indices[GUARDED_HEAP_MAP_TABLE_DEPTH];\r
+  UINT64    Tables[GUARDED_HEAP_MAP_TABLE_DEPTH];\r
+  UINT64    Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH];\r
+  UINT64    TableEntry;\r
+  UINT64    Address;\r
+  UINT64    GuardPage;\r
+  INTN      Level;\r
+  UINTN     Index;\r
+  BOOLEAN   OnGuarding;\r
+\r
+  if (mGuardedMemoryMap == 0 ||\r
+      mMapLevel == 0 ||\r
+      mMapLevel > GUARDED_HEAP_MAP_TABLE_DEPTH) {\r
+    return;\r
+  }\r
+\r
+  CopyMem (Entries, mLevelMask, sizeof (Entries));\r
+  CopyMem (Shifts, mLevelShift, sizeof (Shifts));\r
+\r
+  SetMem (Tables, sizeof(Tables), 0);\r
+  SetMem (Addresses, sizeof(Addresses), 0);\r
+  SetMem (Indices, sizeof(Indices), 0);\r
+\r
+  Level         = GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel;\r
+  Tables[Level] = mGuardedMemoryMap;\r
+  Address       = 0;\r
+  OnGuarding    = FALSE;\r
+\r
+  DEBUG_CODE (\r
+    DumpGuardedMemoryBitmap ();\r
+  );\r
+\r
+  while (TRUE) {\r
+    if (Indices[Level] > Entries[Level]) {\r
+      Tables[Level] = 0;\r
+      Level        -= 1;\r
+    } else {\r
+\r
+      TableEntry  = ((UINT64 *)(UINTN)(Tables[Level]))[Indices[Level]];\r
+      Address     = Addresses[Level];\r
+\r
+      if (TableEntry == 0) {\r
+\r
+        OnGuarding = FALSE;\r
+\r
+      } else if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) {\r
+\r
+        Level            += 1;\r
+        Tables[Level]     = TableEntry;\r
+        Addresses[Level]  = Address;\r
+        Indices[Level]    = 0;\r
+\r
+        continue;\r
+\r
+      } else {\r
+\r
+        Index = 0;\r
+        while (Index < GUARDED_HEAP_MAP_ENTRY_BITS) {\r
+          if ((TableEntry & 1) == 1) {\r
+            if (OnGuarding) {\r
+              GuardPage = 0;\r
+            } else {\r
+              GuardPage = Address - EFI_PAGE_SIZE;\r
+            }\r
+            OnGuarding = TRUE;\r
+          } else {\r
+            if (OnGuarding) {\r
+              GuardPage = Address;\r
+            } else {\r
+              GuardPage = 0;\r
+            }\r
+            OnGuarding = FALSE;\r
+          }\r
+\r
+          if (GuardPage != 0) {\r
+            SetGuardPage (GuardPage);\r
+          }\r
+\r
+          if (TableEntry == 0) {\r
+            break;\r
+          }\r
+\r
+          TableEntry = RShiftU64 (TableEntry, 1);\r
+          Address   += EFI_PAGE_SIZE;\r
+          Index     += 1;\r
+        }\r
+      }\r
+    }\r
+\r
+    if (Level < (GUARDED_HEAP_MAP_TABLE_DEPTH - (INTN)mMapLevel)) {\r
+      break;\r
+    }\r
+\r
+    Indices[Level] += 1;\r
+    Address = (Level == 0) ? 0 : Addresses[Level - 1];\r
+    Addresses[Level] = Address | LShiftU64(Indices[Level], Shifts[Level]);\r
+\r
+  }\r
+}\r
+\r
+/**\r
+  Notify function used to set all Guard pages before CPU Arch Protocol installed.\r
+**/\r
+VOID\r
+HeapGuardCpuArchProtocolNotify (\r
+  VOID\r
+  )\r
+{\r
+  ASSERT (gCpu != NULL);\r
+  SetAllGuardPages ();\r
+}\r
+\r
 /**\r
   Helper function to convert a UINT64 value in binary to a string.\r
 \r