]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
MdeModulePkg/Core: allow HeapGuard even before CpuArchProtocol installed
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Misc / MemoryProtection.c
index 21a52d0af55a6d94814d7859e168082054fc3ba1..2f7e490af18feac5fbe9753f9678e1d0c0c30b45 100644 (file)
@@ -19,7 +19,7 @@
 \r
   Once the image is unloaded, the protection is removed automatically.\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
@@ -48,6 +48,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/SimpleFileSystem.h>\r
 \r
 #include "DxeMain.h"\r
+#include "Mem/HeapGuard.h"\r
 \r
 #define CACHE_ATTRIBUTE_MASK   (EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP)\r
 #define MEMORY_ATTRIBUTE_MASK  (EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RO)\r
@@ -800,6 +801,9 @@ InitializeDxeNxMemoryProtectionPolicy (
   UINT64                            Attributes;\r
   LIST_ENTRY                        *Link;\r
   EFI_GCD_MAP_ENTRY                 *Entry;\r
+  EFI_PEI_HOB_POINTERS              Hob;\r
+  EFI_HOB_MEMORY_ALLOCATION         *MemoryHob;\r
+  EFI_PHYSICAL_ADDRESS              StackBase;\r
 \r
   //\r
   // Get the EFI memory map.\r
@@ -831,8 +835,45 @@ InitializeDxeNxMemoryProtectionPolicy (
   } while (Status == EFI_BUFFER_TOO_SMALL);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  DEBUG((DEBUG_ERROR, "%a: applying strict permissions to active memory regions\n",\r
-    __FUNCTION__));\r
+  StackBase = 0;\r
+  if (PcdGetBool (PcdCpuStackGuard)) {\r
+    //\r
+    // Get the base of stack from Hob.\r
+    //\r
+    Hob.Raw = GetHobList ();\r
+    while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {\r
+      MemoryHob = Hob.MemoryAllocation;\r
+      if (CompareGuid(&gEfiHobMemoryAllocStackGuid, &MemoryHob->AllocDescriptor.Name)) {\r
+        DEBUG ((\r
+          DEBUG_INFO,\r
+          "%a: StackBase = 0x%016lx  StackSize = 0x%016lx\n",\r
+          __FUNCTION__,\r
+          MemoryHob->AllocDescriptor.MemoryBaseAddress,\r
+          MemoryHob->AllocDescriptor.MemoryLength\r
+          ));\r
+\r
+        StackBase = MemoryHob->AllocDescriptor.MemoryBaseAddress;\r
+        //\r
+        // Ensure the base of the stack is page-size aligned.\r
+        //\r
+        ASSERT ((StackBase & EFI_PAGE_MASK) == 0);\r
+        break;\r
+      }\r
+      Hob.Raw = GET_NEXT_HOB (Hob);\r
+    }\r
+\r
+    //\r
+    // Ensure the base of stack can be found from Hob when stack guard is\r
+    // enabled.\r
+    //\r
+    ASSERT (StackBase != 0);\r
+  }\r
+\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "%a: applying strict permissions to active memory regions\n",\r
+    __FUNCTION__\r
+    ));\r
 \r
   MergeMemoryMapForProtectionPolicy (MemoryMap, &MemoryMapSize, DescriptorSize);\r
 \r
@@ -846,6 +887,37 @@ InitializeDxeNxMemoryProtectionPolicy (
         MemoryMapEntry->PhysicalStart,\r
         LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT),\r
         Attributes);\r
+\r
+      //\r
+      // Add EFI_MEMORY_RP attribute for page 0 if NULL pointer detection is\r
+      // enabled.\r
+      //\r
+      if (MemoryMapEntry->PhysicalStart == 0 &&\r
+          PcdGet8 (PcdNullPointerDetectionPropertyMask) != 0) {\r
+\r
+        ASSERT (MemoryMapEntry->NumberOfPages > 0);\r
+        SetUefiImageMemoryAttributes (\r
+          0,\r
+          EFI_PAGES_TO_SIZE (1),\r
+          EFI_MEMORY_RP | Attributes);\r
+      }\r
+\r
+      //\r
+      // Add EFI_MEMORY_RP attribute for the first page of the stack if stack\r
+      // guard is enabled.\r
+      //\r
+      if (StackBase != 0 &&\r
+          (StackBase >= MemoryMapEntry->PhysicalStart &&\r
+           StackBase <  MemoryMapEntry->PhysicalStart +\r
+                        LShiftU64 (MemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT)) &&\r
+          PcdGetBool (PcdCpuStackGuard)) {\r
+\r
+        SetUefiImageMemoryAttributes (\r
+          StackBase,\r
+          EFI_PAGES_TO_SIZE (1),\r
+          EFI_MEMORY_RP | Attributes);\r
+      }\r
+\r
     }\r
     MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
   }\r
@@ -856,9 +928,11 @@ InitializeDxeNxMemoryProtectionPolicy (
   // accessible, but have not been added to the UEFI memory map (yet).\r
   //\r
   if (GetPermissionAttributeForMemoryType (EfiConventionalMemory) != 0) {\r
-    DEBUG((DEBUG_ERROR,\r
+    DEBUG ((\r
+      DEBUG_INFO,\r
       "%a: applying strict permissions to inactive memory regions\n",\r
-      __FUNCTION__));\r
+      __FUNCTION__\r
+      ));\r
 \r
     CoreAcquireGcdMemoryLock ();\r
 \r
@@ -927,6 +1001,11 @@ MemoryProtectionCpuArchProtocolNotify (
     InitializeDxeNxMemoryProtectionPolicy ();\r
   }\r
 \r
+  //\r
+  // Call notify function meant for Heap Guard.\r
+  //\r
+  HeapGuardCpuArchProtocolNotify ();\r
+\r
   if (mImageProtectionPolicy == 0) {\r
     return;\r
   }\r
@@ -1065,15 +1144,12 @@ CoreInitializeMemoryProtection (
   // - code regions should have no EFI_MEMORY_XP attribute\r
   // - EfiConventionalMemory and EfiBootServicesData should use the\r
   //   same attribute\r
-  // - heap guard should not be enabled for the same type of memory\r
   //\r
   ASSERT ((GetPermissionAttributeForMemoryType (EfiBootServicesCode) & EFI_MEMORY_XP) == 0);\r
   ASSERT ((GetPermissionAttributeForMemoryType (EfiRuntimeServicesCode) & EFI_MEMORY_XP) == 0);\r
   ASSERT ((GetPermissionAttributeForMemoryType (EfiLoaderCode) & EFI_MEMORY_XP) == 0);\r
   ASSERT (GetPermissionAttributeForMemoryType (EfiBootServicesData) ==\r
           GetPermissionAttributeForMemoryType (EfiConventionalMemory));\r
-  ASSERT ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & PcdGet64 (PcdHeapGuardPoolType)) == 0);\r
-  ASSERT ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & PcdGet64 (PcdHeapGuardPageType)) == 0);\r
 \r
   if (mImageProtectionPolicy != 0 || PcdGet64 (PcdDxeNxMemoryProtectionPolicy) != 0) {\r
     Status = CoreCreateEvent (\r
@@ -1186,6 +1262,27 @@ ApplyMemoryProtectionPolicy (
     return EFI_SUCCESS;\r
   }\r
 \r
+  //\r
+  // Don't overwrite Guard pages, which should be the first and/or last page,\r
+  // if any.\r
+  //\r
+  if (IsHeapGuardEnabled ()) {\r
+    if (IsGuardPage (Memory))  {\r
+      Memory += EFI_PAGE_SIZE;\r
+      Length -= EFI_PAGE_SIZE;\r
+      if (Length == 0) {\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+\r
+    if (IsGuardPage (Memory + Length - EFI_PAGE_SIZE))  {\r
+      Length -= EFI_PAGE_SIZE;\r
+      if (Length == 0) {\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+\r
   //\r
   // Update the executable permissions according to the DXE memory\r
   // protection policy, but only if\r