public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel][PATCH v1 1/1] MdeModulePkg: DxeCore: Don't Guard Large Runtime Granularity Allocations
@ 2024-02-15  0:34 Oliver Smith-Denny
  2024-02-15  7:50 ` Ard Biesheuvel
  0 siblings, 1 reply; 8+ messages in thread
From: Oliver Smith-Denny @ 2024-02-15  0:34 UTC (permalink / raw)
  To: devel; +Cc: Leif Lindholm, Ard Biesheuvel, Sami Mujawar, Liming Gao

Currently, there are multiple issues when page or pool guards are
allocated for runtime and ACPI memory regions that are aligned to
non-EFI_PAGE_SIZE alignments. Multiple other issues have been fixed
for these same systems (notably ARM64 which has a 64k runtime page
allocation granularity) recently. The heap guard system is only
built to support 4k guard pages and 4k alignment.

Today, the address returned to a caller of AllocatePages will not
be aligned correctly to the runtime page allocation granularity,
because the heap guard system does not take non-4k alignment
requirements into consideration.

However, even with this bug fixed, the Memory Allocation Table
cannot be produced and an OS with a larger than 4k page granularity
will not have aligned memory regions because the guard pages are
reported as part of the same memory allocation. So what would have
been, on an ARM64 system, a 64k runtime memory allocation is actually
a 72k memory allocation as tracked by the Page.c code because the
guard pages are tracked as part of the same allocation. This is a
core function of the current heap guard architecture.

This could also be fixed with rearchitecting the heap guard system to
respect alignment requirements and shift the guard pages inside of the
outer rounded allocation or by having guard pages be the runtime
granularity. Both of these approaches have issues, in the former, the
allocator of runtime memory would get an address that was not aligned
with the runtime granularity (the head guard would be, but not the
usuable address), which seems fraught with peril. In the latter case,
an immense amount of memory is wasted to support such large guard pages,
and with pool guard many systems could not support an additional 128k
allocation for all runtime memory.

The simpler and safer solution is to disallow page and pool guards for
runtime memory allocations for systems that have a runtime granularity
greater than the EFI_PAGE_SIZE (4k). The usefulness of such guards is
limited, as OSes do not map guard pages today, so there is only boot
time protection of these ranges, which runtime memory is typically
used minimally in boot time. This also prevents other bugs from being
exposed by using guards for regions that have a non-4k alignment
requirement, as again, multiple have cropped up because the heap guard
system was not built to support it.

This patch adds both a static assert to ensure that either the runtime
granularity is the EFI_PAGE_SIZE or that the PCD bits are not set to
enable heap guard for runtime memory regions. It also adds a check in
the page and pool allocation system to ensure that at runtime we are not
allocating a runtime region and attempt to guard it (the PCDs are close to
being removed in favor of dynamic heap guard configurations).

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4674
Github PR: https://github.com/tianocore/edk2/pull/5378

Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>

Signed-off-by: Oliver Smith-Denny <osde@linux.microsoft.com>
---
 MdeModulePkg/MdeModulePkg.dec         | 10 ++++++++++
 MdeModulePkg/Core/Dxe/Mem/HeapGuard.h | 14 ++++++++++++++
 MdeModulePkg/Core/Dxe/Mem/Page.c      | 11 +++++++++++
 MdeModulePkg/Core/Dxe/Mem/Pool.c      | 11 +++++++++++
 4 files changed, 46 insertions(+)

diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index a2cd83345f5b..884734aff592 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -1027,6 +1027,11 @@ [PcdsFixedAtBuild]
   # free pages for all of them. The page allocation for the type related to
   # cleared bits keeps the same as ususal.
   #
+  # The heap guard system only supports guarding EfiRuntimeServicesCode, EfiRuntimeServicesData,
+  # EfiACPIReclaimMemory, and EfiACPIMemoryNVS memory types for systems that have
+  # RUNTIME_PAGE_ALLOCATION_GRANULARITY == EFI_PAGE_SIZE. This is to preserve alignment requirements
+  # without extending the page guard size to very large granularities.
+  #
   # This PCD is only valid if BIT0 and/or BIT2 are set in PcdHeapGuardPropertyMask.
   #
   # Below is bit mask for this PCD: (Order is same as UEFI spec)<BR>
@@ -1058,6 +1063,11 @@ [PcdsFixedAtBuild]
   # if there's enough free memory for all of them. The pool allocation for the
   # type related to cleared bits keeps the same as ususal.
   #
+  # The heap guard system only supports guarding EfiRuntimeServicesCode, EfiRuntimeServicesData,
+  # EfiACPIReclaimMemory, and EfiACPIMemoryNVS memory types for systems that have
+  # RUNTIME_PAGE_ALLOCATION_GRANULARITY == EFI_PAGE_SIZE. This is to preserve alignment requirements
+  # without extending the page guard size to very large granularities.
+  #
   # This PCD is only valid if BIT1 and/or BIT3 are set in PcdHeapGuardPropertyMask.
   #
   # Below is bit mask for this PCD: (Order is same as UEFI spec)<BR>
diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h
index 24b4206c0e02..d4f283977b04 100644
--- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h
+++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h
@@ -469,4 +469,18 @@ PromoteGuardedFreePages (
 
 extern BOOLEAN  mOnGuarding;
 
+//
+// the heap guard system does not support non-EFI_PAGE_SIZE alignments
+// architectures that require larger RUNTIME_PAGE_ALLOCATION_GRANULARITY
+// cannot have EfiRuntimeServicesCode, EfiRuntimeServicesData, EfiACPIReclaimMemory,
+// and EfiACPIMemoryNVS guarded. OSes do not map guard pages anyway, so this is a
+// minimal loss. Not guarding prevents alignment mismatches
+//
+STATIC_ASSERT (
+  RUNTIME_PAGE_ALLOCATION_GRANULARITY == EFI_PAGE_SIZE ||
+  (((FixedPcdGet64 (PcdHeapGuardPageType) & 0x660) == 0) &&
+   ((FixedPcdGet64 (PcdHeapGuardPoolType) & 0x660) == 0)),
+  "Unsupported Heap Guard configuration on system with greater than EFI_PAGE_SIZE RUNTIME_PAGE_ALLOCATION_GRANULARITY"
+  );
+
 #endif
diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c
index 3205732ede17..ed3908b9768e 100644
--- a/MdeModulePkg/Core/Dxe/Mem/Page.c
+++ b/MdeModulePkg/Core/Dxe/Mem/Page.c
@@ -1411,6 +1411,17 @@ CoreInternalAllocatePages (
     Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
   }
 
+  //
+  // the heap guard system does not support non-EFI_PAGE_SIZE alignments
+  // architectures that require larger RUNTIME_PAGE_ALLOCATION_GRANULARITY
+  // will have the runtime and ACPI memory regions unguarded. OSes do not
+  // map guard pages anyway, so this is a minimal loss. Not guarding prevents
+  // alignment mismatches
+  //
+  if (Alignment != EFI_PAGE_SIZE) {
+    NeedGuard = FALSE;
+  }
+
   if (Type == AllocateAddress) {
     if ((*Memory & (Alignment - 1)) != 0) {
       return EFI_NOT_FOUND;
diff --git a/MdeModulePkg/Core/Dxe/Mem/Pool.c b/MdeModulePkg/Core/Dxe/Mem/Pool.c
index 716dd045f9fd..beed5f814510 100644
--- a/MdeModulePkg/Core/Dxe/Mem/Pool.c
+++ b/MdeModulePkg/Core/Dxe/Mem/Pool.c
@@ -380,6 +380,17 @@ CoreAllocatePoolI (
     Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
   }
 
+  //
+  // the heap guard system does not support non-EFI_PAGE_SIZE alignments
+  // architectures that require larger RUNTIME_PAGE_ALLOCATION_GRANULARITY
+  // will have the runtime and ACPI memory regions unguarded. OSes do not
+  // map guard pages anyway, so this is a minimal loss. Not guarding prevents
+  // alignment mismatches
+  //
+  if (Granularity != EFI_PAGE_SIZE) {
+    NeedGuard = FALSE;
+  }
+
   //
   // Adjust the size by the pool header & tail overhead
   //
-- 
2.40.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#115474): https://edk2.groups.io/g/devel/message/115474
Mute This Topic: https://groups.io/mt/104364784/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2024-02-15 22:39 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-15  0:34 [edk2-devel][PATCH v1 1/1] MdeModulePkg: DxeCore: Don't Guard Large Runtime Granularity Allocations Oliver Smith-Denny
2024-02-15  7:50 ` Ard Biesheuvel
2024-02-15 17:08   ` Oliver Smith-Denny
2024-02-15 17:21     ` Ard Biesheuvel
2024-02-15 19:01       ` Oliver Smith-Denny
2024-02-15 19:55   ` Oliver Smith-Denny
2024-02-15 22:17     ` Ard Biesheuvel
2024-02-15 22:39       ` Oliver Smith-Denny

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox