MdeModulePkg/Core: fix feature conflict between NX and heap guard
authorJian J Wang <jian.j.wang@intel.com>
Mon, 29 Jan 2018 12:03:33 +0000 (20:03 +0800)
committerStar Zeng <star.zeng@intel.com>
Fri, 2 Feb 2018 01:50:16 +0000 (09:50 +0800)
Considering following scenario (both NX memory protection and heap guard
are enabled):

   1. Allocate 3 pages. The attributes of adjacent memory pages will be

      |NOT-PRESENT|  present  |  present  |  present  |NOT-PRESENT|

   2. Free the middle page. The attributes of adjacent memory pages should be

      |NOT-PRESENT|  present  |NOT-PRESENT|  present  |NOT-PRESENT|

      But the NX feature will overwrite the attributes of middle page. So it
      looks still like below, which is wrong.

      |NOT-PRESENT|  present  |  PRESENT  |  present  |NOT-PRESENT|

The solution is checking the first and/or last page of a memory block to be
marked as NX, and skipping them if they are Guard pages.

Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
MdeModulePkg/Core/Dxe/Mem/HeapGuard.c
MdeModulePkg/Core/Dxe/Mem/HeapGuard.h
MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c

index 392aeb8..d7906e0 100644 (file)
@@ -728,6 +728,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
index 30ac0e6..7208ab1 100644 (file)
@@ -389,6 +389,16 @@ AdjustPoolHeadF (
   IN EFI_PHYSICAL_ADDRESS    Memory\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
 extern BOOLEAN mOnGuarding;\r
 \r
 #endif\r
index a4705bc..455ed35 100644 (file)
@@ -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
@@ -1202,6 +1203,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