]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Mem/Pool.c
MdeModulePkg/DxeCore: Implement heap guard feature for UEFI
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Mem / Pool.c
index ced64443c77d982b1db4cfaaf947d91e28a0c3f8..77ca5671dcfea69d08273d18c8823f871c8d32e3 100644 (file)
@@ -14,6 +14,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "DxeMain.h"\r
 #include "Imem.h"\r
+#include "HeapGuard.h"
 \r
 STATIC EFI_LOCK mPoolMemoryLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
 \r
@@ -169,7 +170,7 @@ LookupPoolHead (
       }\r
     }\r
 \r
-    Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL));\r
+    Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL), FALSE);
     if (Pool == NULL) {\r
       return NULL;\r
     }\r
@@ -214,7 +215,8 @@ CoreInternalAllocatePool (
   OUT VOID            **Buffer\r
   )\r
 {\r
-  EFI_STATUS    Status;\r
+  EFI_STATUS            Status;
+  BOOLEAN               NeedGuard;
 \r
   //\r
   // If it's not a valid type, fail it\r
@@ -238,6 +240,8 @@ CoreInternalAllocatePool (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
+  NeedGuard = IsPoolTypeToGuard (PoolType) && !mOnGuarding;
+
   //\r
   // Acquire the memory lock and make the allocation\r
   //\r
@@ -246,7 +250,7 @@ CoreInternalAllocatePool (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  *Buffer = CoreAllocatePoolI (PoolType, Size);\r
+  *Buffer = CoreAllocatePoolI (PoolType, Size, NeedGuard);
   CoreReleaseLock (&mPoolMemoryLock);\r
   return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;\r
 }\r
@@ -291,12 +295,25 @@ CoreAllocatePool (
   return Status;\r
 }\r
 \r
+/**\r
+  Internal function.  Used by the pool functions to allocate pages\r
+  to back pool allocation requests.\r
+\r
+  @param  PoolType               The type of memory for the new pool pages\r
+  @param  NoPages                No of pages to allocate\r
+  @param  Granularity            Bits to align.\r
+  @param  NeedGuard              Flag to indicate Guard page is needed or not
+\r
+  @return The allocated memory, or NULL\r
+\r
+**/\r
 STATIC\r
 VOID *\r
 CoreAllocatePoolPagesI (\r
   IN EFI_MEMORY_TYPE    PoolType,\r
   IN UINTN              NoPages,\r
-  IN UINTN              Granularity\r
+  IN UINTN              Granularity,
+  IN BOOLEAN            NeedGuard
   )\r
 {\r
   VOID        *Buffer;\r
@@ -307,11 +324,14 @@ CoreAllocatePoolPagesI (
     return NULL;\r
   }\r
 \r
-  Buffer = CoreAllocatePoolPages (PoolType, NoPages, Granularity);\r
+  Buffer = CoreAllocatePoolPages (PoolType, NoPages, Granularity, NeedGuard);
   CoreReleaseMemoryLock ();\r
 \r
   if (Buffer != NULL) {\r
-    ApplyMemoryProtectionPolicy (EfiConventionalMemory, PoolType,\r
+    if (NeedGuard) {
+      SetGuardForMemory ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, NoPages);
+    }
+    ApplyMemoryProtectionPolicy(EfiConventionalMemory, PoolType,
       (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, EFI_PAGES_TO_SIZE (NoPages));\r
   }\r
   return Buffer;\r
@@ -323,6 +343,7 @@ CoreAllocatePoolPagesI (
 \r
   @param  PoolType               Type of pool to allocate\r
   @param  Size                   The amount of pool to allocate\r
+  @param  NeedGuard              Flag to indicate Guard page is needed or not
 \r
   @return The allocate pool, or NULL\r
 \r
@@ -330,7 +351,8 @@ CoreAllocatePoolPagesI (
 VOID *\r
 CoreAllocatePoolI (\r
   IN EFI_MEMORY_TYPE  PoolType,\r
-  IN UINTN            Size\r
+  IN UINTN            Size,
+  IN BOOLEAN          NeedGuard
   )\r
 {\r
   POOL        *Pool;\r
@@ -344,6 +366,7 @@ CoreAllocatePoolI (
   UINTN       Offset, MaxOffset;\r
   UINTN       NoPages;\r
   UINTN       Granularity;\r
+  BOOLEAN     HasPoolTail;
 \r
   ASSERT_LOCKED (&mPoolMemoryLock);\r
 \r
@@ -352,15 +375,18 @@ CoreAllocatePoolI (
        PoolType == EfiRuntimeServicesCode ||\r
        PoolType == EfiRuntimeServicesData) {\r
 \r
-    Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;\r
+    Granularity = RUNTIME_PAGE_ALLOCATION_GRANULARITY;\r
   } else {\r
-    Granularity = DEFAULT_PAGE_ALLOCATION;\r
+    Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY;\r
   }\r
 \r
   //\r
   // Adjust the size by the pool header & tail overhead\r
   //\r
 \r
+  HasPoolTail  = !(NeedGuard &&
+                   ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0));
+
   //\r
   // Adjusting the Size to be of proper alignment so that\r
   // we don't get an unaligned access fault later when\r
@@ -380,10 +406,16 @@ CoreAllocatePoolI (
   // If allocation is over max size, just allocate pages for the request\r
   // (slow)\r
   //\r
-  if (Index >= SIZE_TO_LIST (Granularity)) {\r
-    NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;\r
+  if (Index >= SIZE_TO_LIST (Granularity) || NeedGuard) {
+    if (!HasPoolTail) {
+      Size -= sizeof (POOL_TAIL);
+    }
+    NoPages = EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;
     NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1);\r
-    Head = CoreAllocatePoolPagesI (PoolType, NoPages, Granularity);\r
+    Head = CoreAllocatePoolPagesI (PoolType, NoPages, Granularity, NeedGuard);
+    if (NeedGuard) {
+      Head = AdjustPoolHeadA ((EFI_PHYSICAL_ADDRESS)(UINTN)Head, NoPages, Size);
+    }
     goto Done;\r
   }\r
 \r
@@ -411,7 +443,8 @@ CoreAllocatePoolI (
     //\r
     // Get another page\r
     //\r
-    NewPage = CoreAllocatePoolPagesI (PoolType, EFI_SIZE_TO_PAGES (Granularity), Granularity);\r
+    NewPage = CoreAllocatePoolPagesI (PoolType, EFI_SIZE_TO_PAGES (Granularity),
+                                      Granularity, NeedGuard);
     if (NewPage == NULL) {\r
       goto Done;\r
     }\r
@@ -457,30 +490,39 @@ Done:
 \r
   if (Head != NULL) {\r
 \r
+    //
+    // Account the allocation
+    //
+    Pool->Used += Size;
+
     //\r
     // If we have a pool buffer, fill in the header & tail info\r
     //\r
     Head->Signature = POOL_HEAD_SIGNATURE;\r
     Head->Size      = Size;\r
     Head->Type      = (EFI_MEMORY_TYPE) PoolType;\r
-    Tail            = HEAD_TO_TAIL (Head);\r
-    Tail->Signature = POOL_TAIL_SIGNATURE;\r
-    Tail->Size      = Size;\r
     Buffer          = Head->Data;\r
-    DEBUG_CLEAR_MEMORY (Buffer, Size - POOL_OVERHEAD);\r
+
+    if (HasPoolTail) {
+      Tail            = HEAD_TO_TAIL (Head);
+      Tail->Signature = POOL_TAIL_SIGNATURE;
+      Tail->Size      = Size;
+
+      Size -= POOL_OVERHEAD;
+    } else {
+      Size -= SIZE_OF_POOL_HEAD;
+    }
+
+    DEBUG_CLEAR_MEMORY (Buffer, Size);
 \r
     DEBUG ((\r
       DEBUG_POOL,\r
       "AllocatePoolI: Type %x, Addr %p (len %lx) %,ld\n", PoolType,\r
       Buffer,\r
-      (UINT64)(Size - POOL_OVERHEAD),\r
+      (UINT64)Size,
       (UINT64) Pool->Used\r
       ));\r
 \r
-    //\r
-    // Account the allocation\r
-    //\r
-    Pool->Used += Size;\r
 \r
   } else {\r
     DEBUG ((DEBUG_ERROR | DEBUG_POOL, "AllocatePool: failed to allocate %ld bytes\n", (UINT64) Size));\r
@@ -553,6 +595,14 @@ CoreFreePool (
   return Status;\r
 }\r
 \r
+/**\r
+  Internal function.  Frees pool pages allocated via CoreAllocatePoolPagesI().\r
+\r
+  @param  PoolType               The type of memory for the pool pages\r
+  @param  Memory                 The base address to free\r
+  @param  NoPages                The number of pages to free\r
+\r
+**/\r
 STATIC\r
 VOID\r
 CoreFreePoolPagesI (\r
@@ -569,6 +619,34 @@ CoreFreePoolPagesI (
     (EFI_PHYSICAL_ADDRESS)(UINTN)Memory, EFI_PAGES_TO_SIZE (NoPages));\r
 }\r
 \r
+/**
+  Internal function.  Frees guarded pool pages.
+
+  @param  PoolType               The type of memory for the pool pages
+  @param  Memory                 The base address to free
+  @param  NoPages                The number of pages to free
+
+**/
+STATIC
+VOID
+CoreFreePoolPagesWithGuard (
+  IN EFI_MEMORY_TYPE        PoolType,
+  IN EFI_PHYSICAL_ADDRESS   Memory,
+  IN UINTN                  NoPages
+  )
+{
+  EFI_PHYSICAL_ADDRESS    MemoryGuarded;
+  UINTN                   NoPagesGuarded;
+
+  MemoryGuarded  = Memory;
+  NoPagesGuarded = NoPages;
+
+  AdjustMemoryF (&Memory, &NoPages);
+  CoreFreePoolPagesI (PoolType, Memory, NoPages);
+
+  UnsetGuardForMemory (MemoryGuarded, NoPagesGuarded);
+}
+
 /**\r
   Internal function to free a pool entry.\r
   Caller must have the memory lock held\r
@@ -597,6 +675,8 @@ CoreFreePoolI (
   UINTN       Offset;\r
   BOOLEAN     AllFree;\r
   UINTN       Granularity;\r
+  BOOLEAN     IsGuarded;
+  BOOLEAN     HasPoolTail;
 \r
   ASSERT(Buffer != NULL);\r
   //\r
@@ -609,24 +689,32 @@ CoreFreePoolI (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Tail = HEAD_TO_TAIL (Head);\r
-  ASSERT(Tail != NULL);\r
-\r
-  //\r
-  // Debug\r
-  //\r
-  ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);\r
-  ASSERT (Head->Size == Tail->Size);\r
-  ASSERT_LOCKED (&mPoolMemoryLock);\r
-\r
-  if (Tail->Signature != POOL_TAIL_SIGNATURE) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (Head->Size != Tail->Size) {\r
-    return EFI_INVALID_PARAMETER;\r
+  IsGuarded   = IsPoolTypeToGuard (Head->Type) &&
+                IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)Head);
+  HasPoolTail = !(IsGuarded &&
+                  ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0));
+\r
+  if (HasPoolTail) {
+    Tail = HEAD_TO_TAIL (Head);
+    ASSERT (Tail != NULL);
+\r
+    //
+    // Debug
+    //
+    ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);
+    ASSERT (Head->Size == Tail->Size);
+\r
+    if (Tail->Signature != POOL_TAIL_SIGNATURE) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if (Head->Size != Tail->Size) {
+      return EFI_INVALID_PARAMETER;
+    }
   }\r
 \r
+  ASSERT_LOCKED (&mPoolMemoryLock);
+
   //\r
   // Determine the pool type and account for it\r
   //\r
@@ -643,9 +731,9 @@ CoreFreePoolI (
        Head->Type == EfiRuntimeServicesCode ||\r
        Head->Type == EfiRuntimeServicesData) {\r
 \r
-    Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;\r
+    Granularity = RUNTIME_PAGE_ALLOCATION_GRANULARITY;\r
   } else {\r
-    Granularity = DEFAULT_PAGE_ALLOCATION;\r
+    Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY;\r
   }\r
 \r
   if (PoolType != NULL) {\r
@@ -661,14 +749,27 @@ CoreFreePoolI (
   //\r
   // If it's not on the list, it must be pool pages\r
   //\r
-  if (Index >= SIZE_TO_LIST (Granularity)) {\r
+  if (Index >= SIZE_TO_LIST (Granularity) || IsGuarded) {
 \r
     //\r
     // Return the memory pages back to free memory\r
     //\r
-    NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;\r
+    NoPages = EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;
     NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1);\r
-    CoreFreePoolPagesI (Pool->MemoryType, (EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages);\r
+    if (IsGuarded) {
+      Head = AdjustPoolHeadF ((EFI_PHYSICAL_ADDRESS)(UINTN)Head);
+      CoreFreePoolPagesWithGuard (
+        Pool->MemoryType,
+        (EFI_PHYSICAL_ADDRESS)(UINTN)Head,
+        NoPages
+        );
+    } else {
+      CoreFreePoolPagesI (
+        Pool->MemoryType,
+        (EFI_PHYSICAL_ADDRESS)(UINTN)Head,
+        NoPages
+        );
+    }
 \r
   } else {\r
 \r