On Sat, 9 Mar 2024 at 20:06, Oliver Smith-Denny <o...@linux.microsoft.com> wrote: > > Currently, there are multiple issues when page or pool guards are > allocated for runtime 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 case, > we break UEFI spec 2.10 section 2.3.6 for AARCH64, which states that > each 64k page for runtime memory regions may not have mixed memory > attributes, which pushing the guard pages inside would create. 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. 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/5382 > > Cc: Leif Lindholm <quic_llind...@quicinc.com> > Cc: Ard Biesheuvel <ardb+tianoc...@kernel.org> > Cc: Sami Mujawar <sami.muja...@arm.com> > Cc: Liming Gao <gaolim...@byosoft.com.cn> > > Signed-off-by: Oliver Smith-Denny <o...@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(+) >
Reviewed-by: Ard Biesheuvel <a...@kernel.org> > diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec > index a2cd83345f5b..a82dedc070df 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, > + # EfiReservedMemoryType, 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, > + # EfiReservedMemoryType, 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..578e85746585 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, > EfiReservedMemoryType, > +// 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) & 0x461) == 0) && > + ((FixedPcdGet64 (PcdHeapGuardPoolType) & 0x461) == 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 cd201d36a389..26584648c236 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 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 ccfce8c5f959..72293e6dfe40 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 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 (#116628): https://edk2.groups.io/g/devel/message/116628 Mute This Topic: https://groups.io/mt/104832607/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-