Skip to content

Commit 144e3fe

Browse files
committed
Apply EFI_MEMORY_RP on Free Memory
Description This PR makes the necessary changes to apply EFI_MEMORY_RP on EfiConventionalMemory and adds a memory protection policy to configure the setting. - [x] Impacts functionality? - **Functionality** - Does the change ultimately impact how firmware functions? - Examples: Add a new library, publish a new PPI, update an algorithm, ... - [x] Impacts security? - **Security** - Does the change have a direct security impact on an application, flow, or firmware? - Examples: Crypto algorithm change, buffer overflow fix, parameter validation improvement, ... - [x] Breaking change? - **Breaking change** - Will anyone consuming this change experience a break in build or boot behavior? - Examples: Add a new library class, move a module to a different repo, call a function in a new library class in a pre-existing module, ... - [ ] Includes tests? - **Tests** - Does the change include any explicit test code? - Examples: Unit tests, integration tests, robot tests, ... - [ ] Includes documentation? - **Documentation** - Does the change contain explicit documentation additions outside direct code modifications (and comments)? - Examples: Update readme file, add feature readme file, link to documentation on an a separate Web page, ... How This Was Tested Tested by running the DXE Paging Audit on Q35 and SBSA with various memory protection profiles. Integration Instructions Platforms which use pre-built binaries of Mu repos will need to rebuild them to sync the memory protection policy between all modules.
1 parent c3d12d3 commit 144e3fe

File tree

14 files changed

+463
-317
lines changed

14 files changed

+463
-317
lines changed

MdeModulePkg/Core/Dxe/DxeMain.inf

+1
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@
183183
gMemoryProtectionDebugProtocolGuid ## SOMETIMES_PRODUCES ## MS_CHANGE
184184
gEfiMemoryAttributeProtocolGuid ## CONSUMES ## MS_CHANGE
185185
gMemoryProtectionSpecialRegionProtocolGuid ## PRODUCES ## MU_CHANGE
186+
gEdkiiGcdSyncCompleteProtocolGuid ## CONSUMES ## MU_CHANGE
186187

187188
[Pcd]
188189
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressBootTimeCodePageNumber ## SOMETIMES_CONSUMES

MdeModulePkg/Core/Dxe/Mem/HeapGuard.c

+28-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
1616
//
1717
GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mOnGuarding = FALSE;
1818

19+
extern BOOLEAN mPageAttributesInitialized; // MU_CHANGE
20+
1921
//
2022
// Pointer to table tracking the Guarded memory with bitmap, in which '1'
2123
// is used to indicate memory guarded. '0' might be free memory or Guard
@@ -252,6 +254,14 @@ FindGuardedMemoryMap (
252254
);
253255
ASSERT_EFI_ERROR (Status);
254256
ASSERT (MapMemory != 0);
257+
// MU_CHANGE START: Apply Protection policy to the allocated memory
258+
ApplyMemoryProtectionPolicy (
259+
EfiConventionalMemory,
260+
EfiBootServicesData,
261+
MapMemory,
262+
ALIGN_VALUE (Size, EFI_PAGE_SIZE)
263+
);
264+
// MU_CHANGE END
255265

256266
SetMem ((VOID *)(UINTN)MapMemory, Size, 0);
257267

@@ -283,6 +293,14 @@ FindGuardedMemoryMap (
283293
);
284294
ASSERT_EFI_ERROR (Status);
285295
ASSERT (MapMemory != 0);
296+
// MU_CHANGE START: Apply Protection policy to the allocated memory
297+
ApplyMemoryProtectionPolicy (
298+
EfiConventionalMemory,
299+
EfiBootServicesData,
300+
MapMemory,
301+
ALIGN_VALUE (Size, EFI_PAGE_SIZE)
302+
);
303+
// MU_CHANGE END
286304

287305
SetMem ((VOID *)(UINTN)MapMemory, Size, 0);
288306
*GuardMap = MapMemory;
@@ -560,6 +578,13 @@ UnsetGuardPage (
560578
Attributes |= EFI_MEMORY_XP;
561579
}
562580

581+
// MU_CHANGE START: Add support for RP on free mem
582+
if (gDxeMps.FreeMemoryReadProtected) {
583+
Attributes |= EFI_MEMORY_RP;
584+
}
585+
586+
// MU_CHANGE END
587+
563588
//
564589
// Set flag to make sure allocating memory without GUARD for page table
565590
// operation; otherwise infinite loops could be caused.
@@ -690,10 +715,10 @@ IsHeapGuardEnabled (
690715
UINT8 GuardType
691716
)
692717
{
693-
// MU_CHANGE START Update to work with memory protection settings HOB
718+
// MU_CHANGE START: Update to work with memory protection settings HOB,
719+
// remove freed memory guard.
694720
if ((GuardType & GUARD_HEAP_TYPE_PAGE && gDxeMps.HeapGuardPolicy.Fields.UefiPageGuard) ||
695-
(GuardType & GUARD_HEAP_TYPE_POOL && gDxeMps.HeapGuardPolicy.Fields.UefiPoolGuard) ||
696-
(GuardType & GUARD_HEAP_TYPE_FREED && gDxeMps.HeapGuardPolicy.Fields.UefiFreedMemoryGuard))
721+
(GuardType & GUARD_HEAP_TYPE_POOL && gDxeMps.HeapGuardPolicy.Fields.UefiPoolGuard))
697722
{
698723
return TRUE;
699724
}

MdeModulePkg/Core/Dxe/Mem/Page.c

+38-21
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,15 @@ AllocateMemoryMapEntry (
288288
DEFAULT_PAGE_ALLOCATION_GRANULARITY,
289289
FALSE
290290
);
291+
// MU_CHANGE START: The above call to CoreAllocatePoolPages() sidesteps the application of the
292+
// memory protection policy so apply it here to avoid a potential page fault
293+
ApplyMemoryProtectionPolicy (
294+
EfiConventionalMemory,
295+
EfiBootServicesData,
296+
(EFI_PHYSICAL_ADDRESS)(UINTN)FreeDescriptorEntries,
297+
DEFAULT_PAGE_ALLOCATION_GRANULARITY
298+
);
299+
// MU_CHANGE END
291300
if (FreeDescriptorEntries != NULL) {
292301
//
293302
// Enque the free memmory map entries into the list
@@ -947,6 +956,21 @@ CoreConvertPagesEx (
947956
Entry = NULL;
948957
}
949958

959+
// MU_CHANGE [BEGIN]
960+
// The below call may allocate pages which, if we're freeing memory (implied by
961+
// the new type being EfiConventionalMemory), could cause the memory we're currently
962+
// freeing to be allocated before we're done freeing it if CoreFreeMemoryMapStack()
963+
// is called after AddRange(). So, if we are freeing, let's free the memory map
964+
// stack before adding memory we're converting to the free list.
965+
if (ChangingType && (NewType == EfiConventionalMemory)) {
966+
//
967+
// Move any map descriptor stack to general pool
968+
//
969+
CoreFreeMemoryMapStack ();
970+
}
971+
972+
// MU_CHANGE [END]
973+
950974
//
951975
// Add our new range in. Don't do this for freed pages if freed-memory
952976
// guard is enabled.
@@ -973,10 +997,20 @@ CoreConvertPagesEx (
973997
}
974998
}
975999

976-
//
977-
// Move any map descriptor stack to general pool
978-
//
979-
CoreFreeMemoryMapStack ();
1000+
// MU_CHANGE [BEGIN]
1001+
// The below call may allocate pages which, if we're allocating memory (implied by
1002+
// the new type not being EfiConventionalMemory), could cause the range we're currently
1003+
// converting to also be allocated in the below call. To avoid this case, we should
1004+
// call CoreFreeMemoryMapStack() after we've called AddRange() to mark this memory
1005+
// as allocated.
1006+
if (!ChangingType || (ChangingType && (NewType != EfiConventionalMemory))) {
1007+
//
1008+
// Move any map descriptor stack to general pool
1009+
//
1010+
CoreFreeMemoryMapStack ();
1011+
}
1012+
1013+
// MU_CHANGE [END]
9801014

9811015
//
9821016
// Bump the starting address, and convert the next range
@@ -1578,23 +1612,6 @@ CoreInternalFreePages (
15781612
UINTN Alignment;
15791613
BOOLEAN IsGuarded;
15801614

1581-
// MU_CHANGE Start: Unprotect page(s) before free if the memory will be cleared on free
1582-
UINT64 Attributes;
1583-
1584-
if (DebugClearMemoryEnabled () && (mMemoryAttributeProtocol != NULL)) {
1585-
Status = mMemoryAttributeProtocol->GetMemoryAttributes (mMemoryAttributeProtocol, Memory, EFI_PAGES_TO_SIZE (NumberOfPages), &Attributes);
1586-
1587-
if ((Attributes & EFI_MEMORY_RO) || (Attributes & EFI_MEMORY_RP) || (Status == EFI_NO_MAPPING)) {
1588-
Status = ClearAccessAttributesFromMemoryRange (Memory, EFI_PAGES_TO_SIZE (NumberOfPages));
1589-
1590-
if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
1591-
DEBUG ((DEBUG_WARN, "%a - Unable to clear attributes from memory at base: 0x%llx\n", __FUNCTION__, Memory));
1592-
}
1593-
}
1594-
}
1595-
1596-
// MU_CHANGE End
1597-
15981615
//
15991616
// Free the range
16001617
//

0 commit comments

Comments
 (0)