summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MdeModulePkg/Core/Dxe/Gcd/Gcd.c10
-rw-r--r--MdeModulePkg/Core/Dxe/Mem/HeapGuard.c132
-rw-r--r--MdeModulePkg/Core/Dxe/Mem/HeapGuard.h8
-rw-r--r--MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c5
4 files changed, 154 insertions, 1 deletions
diff --git a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
index 8fbc3d2..77f4adb 100644
--- a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
+++ b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
@@ -16,6 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "DxeMain.h"
#include "Gcd.h"
+#include "Mem/HeapGuard.h"
#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
@@ -391,12 +392,21 @@ CoreAllocateGcdMapEntry (
IN OUT EFI_GCD_MAP_ENTRY **BottomEntry
)
{
+ //
+ // Set to mOnGuarding to TRUE before memory allocation. This will make sure
+ // that the entry memory is not "guarded" by HeapGuard. Otherwise it might
+ // cause problem when it's freed (if HeapGuard is enabled).
+ //
+ mOnGuarding = TRUE;
*TopEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY));
+ mOnGuarding = FALSE;
if (*TopEntry == NULL) {
return EFI_OUT_OF_RESOURCES;
}
+ mOnGuarding = TRUE;
*BottomEntry = AllocateZeroPool (sizeof (EFI_GCD_MAP_ENTRY));
+ mOnGuarding = FALSE;
if (*BottomEntry == NULL) {
CoreFreePool (*TopEntry);
return EFI_OUT_OF_RESOURCES;
diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c
index ac043b5..f6068c4 100644
--- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c
+++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c
@@ -576,6 +576,10 @@ SetGuardPage (
IN EFI_PHYSICAL_ADDRESS BaseAddress
)
{
+ if (gCpu == NULL) {
+ return;
+ }
+
//
// Set flag to make sure allocating memory without GUARD for page table
// operation; otherwise infinite loops could be caused.
@@ -606,6 +610,10 @@ UnsetGuardPage (
{
UINT64 Attributes;
+ if (gCpu == NULL) {
+ return;
+ }
+
//
// Once the Guard page is unset, it will be freed back to memory pool. NX
// memory protection must be restored for this page if NX is enabled for free
@@ -652,7 +660,7 @@ IsMemoryTypeToGuard (
UINT64 ConfigBit;
BOOLEAN InSmm;
- if (gCpu == NULL || AllocateType == AllocateAddress) {
+ if (AllocateType == AllocateAddress) {
return FALSE;
}
@@ -1165,6 +1173,128 @@ CoreConvertPagesWithGuard (
}
/**
+ Set all Guard pages which cannot be set before CPU Arch Protocol installed.
+**/
+VOID
+SetAllGuardPages (
+ VOID
+ )
+{
+ UINTN Entries[GUARDED_HEAP_MAP_TABLE_DEPTH];
+ UINTN Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH];
+ UINTN Indices[GUARDED_HEAP_MAP_TABLE_DEPTH];
+ UINT64 Tables[GUARDED_HEAP_MAP_TABLE_DEPTH];
+ UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH];
+ UINT64 TableEntry;
+ UINT64 Address;
+ UINT64 GuardPage;
+ INTN Level;
+ UINTN Index;
+ BOOLEAN OnGuarding;
+
+ if (mGuardedMemoryMap == 0 ||
+ mMapLevel == 0 ||
+ mMapLevel > GUARDED_HEAP_MAP_TABLE_DEPTH) {
+ return;
+ }
+
+ CopyMem (Entries, mLevelMask, sizeof (Entries));
+ CopyMem (Shifts, mLevelShift, sizeof (Shifts));
+
+ SetMem (Tables, sizeof(Tables), 0);
+ SetMem (Addresses, sizeof(Addresses), 0);
+ SetMem (Indices, sizeof(Indices), 0);
+
+ Level = GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel;
+ Tables[Level] = mGuardedMemoryMap;
+ Address = 0;
+ OnGuarding = FALSE;
+
+ DEBUG_CODE (
+ DumpGuardedMemoryBitmap ();
+ );
+
+ while (TRUE) {
+ if (Indices[Level] > Entries[Level]) {
+ Tables[Level] = 0;
+ Level -= 1;
+ } else {
+
+ TableEntry = ((UINT64 *)(UINTN)(Tables[Level]))[Indices[Level]];
+ Address = Addresses[Level];
+
+ if (TableEntry == 0) {
+
+ OnGuarding = FALSE;
+
+ } else if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) {
+
+ Level += 1;
+ Tables[Level] = TableEntry;
+ Addresses[Level] = Address;
+ Indices[Level] = 0;
+
+ continue;
+
+ } else {
+
+ Index = 0;
+ while (Index < GUARDED_HEAP_MAP_ENTRY_BITS) {
+ if ((TableEntry & 1) == 1) {
+ if (OnGuarding) {
+ GuardPage = 0;
+ } else {
+ GuardPage = Address - EFI_PAGE_SIZE;
+ }
+ OnGuarding = TRUE;
+ } else {
+ if (OnGuarding) {
+ GuardPage = Address;
+ } else {
+ GuardPage = 0;
+ }
+ OnGuarding = FALSE;
+ }
+
+ if (GuardPage != 0) {
+ SetGuardPage (GuardPage);
+ }
+
+ if (TableEntry == 0) {
+ break;
+ }
+
+ TableEntry = RShiftU64 (TableEntry, 1);
+ Address += EFI_PAGE_SIZE;
+ Index += 1;
+ }
+ }
+ }
+
+ if (Level < (GUARDED_HEAP_MAP_TABLE_DEPTH - (INTN)mMapLevel)) {
+ break;
+ }
+
+ Indices[Level] += 1;
+ Address = (Level == 0) ? 0 : Addresses[Level - 1];
+ Addresses[Level] = Address | LShiftU64(Indices[Level], Shifts[Level]);
+
+ }
+}
+
+/**
+ Notify function used to set all Guard pages before CPU Arch Protocol installed.
+**/
+VOID
+HeapGuardCpuArchProtocolNotify (
+ VOID
+ )
+{
+ ASSERT (gCpu != NULL);
+ SetAllGuardPages ();
+}
+
+/**
Helper function to convert a UINT64 value in binary to a string.
@param[in] Value Value of a UINT64 integer.
diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h
index 7208ab1..8c34692 100644
--- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h
+++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h
@@ -399,6 +399,14 @@ IsHeapGuardEnabled (
VOID
);
+/**
+ Notify function used to set all Guard pages after CPU Arch Protocol installed.
+**/
+VOID
+HeapGuardCpuArchProtocolNotify (
+ VOID
+ );
+
extern BOOLEAN mOnGuarding;
#endif
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
index 407aece..2f7e490 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
@@ -1001,6 +1001,11 @@ MemoryProtectionCpuArchProtocolNotify (
InitializeDxeNxMemoryProtectionPolicy ();
}
+ //
+ // Call notify function meant for Heap Guard.
+ //
+ HeapGuardCpuArchProtocolNotify ();
+
if (mImageProtectionPolicy == 0) {
return;
}