mOnGuarding = TRUE;\r
//\r
// Note: This might overwrite other attributes needed by other features,\r
- // such as memory protection (NX). Please make sure they are not enabled\r
- // at the same time.\r
+ // such as NX memory protection.\r
//\r
gCpu->SetMemoryAttributes (gCpu, BaseAddress, EFI_PAGE_SIZE, EFI_MEMORY_RP);\r
mOnGuarding = FALSE;\r
IN EFI_PHYSICAL_ADDRESS BaseAddress\r
)\r
{\r
+ UINT64 Attributes;\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
+ // memory.\r
+ //\r
+ Attributes = 0;\r
+ if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & (1 << EfiConventionalMemory)) != 0) {\r
+ Attributes |= EFI_MEMORY_XP;\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
// such as memory protection (NX). Please make sure they are not enabled\r
// at the same time.\r
//\r
- gCpu->SetMemoryAttributes (gCpu, BaseAddress, EFI_PAGE_SIZE, 0);\r
+ gCpu->SetMemoryAttributes (gCpu, BaseAddress, EFI_PAGE_SIZE, Attributes);\r
mOnGuarding = FALSE;\r
}\r
\r
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
{\r
UINT64 Target;\r
\r
+ //\r
+ // UEFI spec requires that allocated pool must be 8-byte aligned. If it's\r
+ // indicated to put the pool near the Tail Guard, we need extra bytes to\r
+ // make sure alignment of the returned pool address.\r
+ //\r
+ if ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0) {\r
+ SizeRequested = ALIGN_VALUE(SizeRequested, 8);\r
+ }\r
+\r
Target = Start + Size - SizeRequested;\r
\r
//\r
IN UINTN Size\r
)\r
{\r
- if ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0) {\r
+ if (Memory == 0 || (PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0) {\r
//\r
// Pool head is put near the head Guard\r
//\r
//\r
// Pool head is put near the tail Guard\r
//\r
+ Size = ALIGN_VALUE (Size, 8);\r
return (VOID *)(UINTN)(Memory + EFI_PAGES_TO_SIZE (NoPages) - Size);\r
}\r
\r
IN EFI_PHYSICAL_ADDRESS Memory\r
)\r
{\r
- if ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0) {\r
+ if (Memory == 0 || (PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0) {\r
//\r
// Pool head is put near the head Guard\r
//\r
IN EFI_MEMORY_TYPE NewType\r
)\r
{\r
+ UINT64 OldStart;\r
+ UINTN OldPages;\r
+\r
if (NewType == EfiConventionalMemory) {\r
+ OldStart = Start;\r
+ OldPages = NumberOfPages;\r
+\r
AdjustMemoryF (&Start, &NumberOfPages);\r
+ //\r
+ // It's safe to unset Guard page inside memory lock because there should\r
+ // be no memory allocation occurred in updating memory page attribute at\r
+ // this point. And unsetting Guard page before free will prevent Guard\r
+ // page just freed back to pool from being allocated right away before\r
+ // marking it usable (from non-present to present).\r
+ //\r
+ UnsetGuardForMemory (OldStart, OldPages);\r
if (NumberOfPages == 0) {\r
return EFI_SUCCESS;\r
}\r