MdeModulePkg: Don't Allocate Page 0

Currently DxeIpl attempts to set page 0 to all 0's and to
create a memory allocation HOB for it. However, DxeIpl will
also unmap the page when mapping page tables and if null
detection is not enabled, DxeCore will set the page to 0,
regardless of allocation status.

Because no consumers are using the memory allocation HOB for
page 0, drop it. Instead, ensure that PeiCore and DxeCore do
not allow allocating page 0; it should always be reserved for
null pointer detection. It also complicates the story for
platforms that are attempting to audit the system and ensure that
no modules are using page 0. With these memory allocation HOBs
in place, it is difficult to tell if it is simply DxeIpl who
has allocated the memory or another module.

This commit drops the memory allocation HOB publishing and ensures
that DxeCore and PeiCore do not allocate page 0. DxeCore already
will not allocate page 0 to callers of AllocatePages who call with
a type other than AllocateAddress, this just changes so that
AllocateAddress cannot allocate at page 0 (which if null detection
is enabled will cause a page fault). PeiCore does not have
AllocateAddress and so this ensures standard allocations do not
receive page 0.

Signed-off-by: Oliver Smith-Denny <osde@microsoft.com>
This commit is contained in:
Oliver Smith-Denny 2025-06-17 15:29:13 -07:00 committed by mergify[bot]
parent 83b30736bf
commit 91bb5cee36
6 changed files with 8 additions and 98 deletions

View file

@ -1459,6 +1459,11 @@ CoreInternalAllocatePages (
// return EFI_NOT_FOUND.
//
if (Type == AllocateAddress) {
// Page 0 is not allowed to be allocated as it is reserved for null pointer detection
if (Start == 0) {
return EFI_NOT_FOUND;
}
if ((NumberOfPages == 0) ||
(NumberOfPages > RShiftU64 (MaxAddress, EFI_PAGE_SHIFT)))
{

View file

@ -265,14 +265,6 @@ HandOffToDxeCore (
EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
BOOLEAN BuildPageTablesIa32Pae;
//
// Clear page 0 and mark it as allocated if NULL pointer detection is enabled.
//
if (IsNullDetectionEnabled ()) {
ClearFirst4KPage (HobList.Raw);
BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData);
}
Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);
ASSERT_EFI_ERROR (Status);

View file

@ -36,14 +36,6 @@ HandOffToDxeCore (
VOID *GhcbBase;
UINTN GhcbSize;
//
// Clear page 0 and mark it as allocated if NULL pointer detection is enabled.
//
if (IsNullDetectionEnabled ()) {
ClearFirst4KPage (HobList.Raw);
BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData);
}
//
// Get Vector Hand-off Info PPI and build Guided HOB
//

View file

@ -31,72 +31,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
//
PAGE_TABLE_POOL *mPageTablePool = NULL;
/**
Clear legacy memory located at the first 4K-page, if available.
This function traverses the whole HOB list to check if memory from 0 to 4095
exists and has not been allocated, and then clear it if so.
@param HobStart The start of HobList passed to DxeCore.
**/
VOID
ClearFirst4KPage (
IN VOID *HobStart
)
{
EFI_PEI_HOB_POINTERS RscHob;
EFI_PEI_HOB_POINTERS MemHob;
BOOLEAN DoClear;
RscHob.Raw = HobStart;
MemHob.Raw = HobStart;
DoClear = FALSE;
//
// Check if page 0 exists and free
//
while ((RscHob.Raw = GetNextHob (
EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,
RscHob.Raw
)) != NULL)
{
if ((RscHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
(RscHob.ResourceDescriptor->PhysicalStart == 0))
{
DoClear = TRUE;
//
// Make sure memory at 0-4095 has not been allocated.
//
while ((MemHob.Raw = GetNextHob (
EFI_HOB_TYPE_MEMORY_ALLOCATION,
MemHob.Raw
)) != NULL)
{
if (MemHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress
< EFI_PAGE_SIZE)
{
DoClear = FALSE;
break;
}
MemHob.Raw = GET_NEXT_HOB (MemHob);
}
break;
}
RscHob.Raw = GET_NEXT_HOB (RscHob);
}
if (DoClear) {
DEBUG ((DEBUG_INFO, "Clearing first 4K-page!\r\n"));
SetMem (NULL, EFI_PAGE_SIZE, 0);
}
return;
}
/**
Return configure status of NULL pointer detection feature.

View file

@ -267,20 +267,6 @@ AsmGetVectorTemplatInfo (
OUT VOID **TemplateBase
);
/**
Clear legacy memory located at the first 4K-page.
This function traverses the whole HOB list to check if memory from 0 to 4095
exists and has not been allocated, and then clear it if so.
@param HobStart The start of HobList passed to DxeCore.
**/
VOID
ClearFirst4KPage (
IN VOID *HobStart
);
/**
Return configure status of NULL pointer detection feature.

View file

@ -613,10 +613,11 @@ PeiAllocatePages (
//
// Check to see if on correct boundary for the memory type.
// If not aligned, make the allocation aligned.
// If not aligned, make the allocation aligned and that we are not trying to allocate page 0, which is used for
// null detection.
//
Padding = *(FreeMemoryTop) & (Granularity - 1);
if ((UINTN)(*FreeMemoryTop - *FreeMemoryBottom) < Padding) {
if (((UINTN)(*FreeMemoryTop - *FreeMemoryBottom) < Padding) || (*(FreeMemoryTop) - Padding == 0)) {
DEBUG ((DEBUG_ERROR, "AllocatePages failed: Out of space after padding.\n"));
return EFI_OUT_OF_RESOURCES;
}