summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg/Core/Dxe/Mem/Pool.c
diff options
context:
space:
mode:
authorOliver Smith-Denny <osde@linux.microsoft.com>2023-08-10 05:34:57 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2023-08-19 03:18:50 +0000
commit00b51e0d78a547dd78119ec44fcc74a01b6f79c8 (patch)
tree36f119bc7d9d6e8d60a5e90eb979993e22099592 /MdeModulePkg/Core/Dxe/Mem/Pool.c
parent48089f3a7cdf308651234f5bf8d8a301f4b8acf9 (diff)
downloadedk2-00b51e0d78a547dd78119ec44fcc74a01b6f79c8.tar.gz
edk2-00b51e0d78a547dd78119ec44fcc74a01b6f79c8.tar.bz2
edk2-00b51e0d78a547dd78119ec44fcc74a01b6f79c8.zip
MdeModulePkg: HeapGuard: Don't Assume Pool Head Allocated In First Page
Currently, HeapGuard, when in the GuardAlignedToTail mode, assumes that the pool head has been allocated in the first page of memory that was allocated. This is not the case for ARM64 platforms when allocating runtime pools, as RUNTIME_PAGE_ALLOCATION_GRANULARITY is 64k, unlike X64, which has RUNTIME_PAGE_ALLOCATION_GRANULARITY as 4k. When a runtime pool is allocated on ARM64, the minimum number of pages allocated is 16, to match the runtime granularity. When a small pool is allocated and GuardAlignedToTail is true, HeapGuard instructs the pool head to be placed as (MemoryAllocated + EFI_PAGES_TO_SIZE(Number of Pages) - SizeRequiredForPool). This gives this scenario: |Head Guard|Large Free Number of Pages|PoolHead|TailGuard| When this pool goes to be freed, HeapGuard instructs the pool code to free from (PoolHead & ~EFI_PAGE_MASK). However, this assumes that the PoolHead is in the first page allocated, which as shown above is not true in this case. For the 4k granularity case (i.e. where the correct number of pages are allocated for this pool), this logic does work. In this failing case, HeapGuard then instructs the pool code to free 16 (or more depending) pages from the page the pool head was allocated on, which as seen above means we overrun the pool and attempt to free memory far past the pool. We end up running into the tail guard and getting an access flag fault. This causes ArmVirtQemu to fail to boot with an access flag fault when GuardAlignedToTail is set to true (and pool guard enabled for runtime memory). It should also cause all ARM64 platforms to fail in this configuration, for exactly the same reason, as this is core code making the assumption. This patch removes HeapGuard's assumption that the pool head is allocated on the first page and instead undoes the same logic that HeapGuard did when allocating the pool head in the first place. With this patch in place, ArmVirtQemu boots with GuardAlignedToTail set to true (and when it is false, also). BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4521 Github PR: https://github.com/tianocore/edk2/pull/4731 Cc: Leif Lindholm <quic_llindhol@quicinc.com> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Cc: Jian J Wang <jian.j.wang@intel.com> Cc: Liming Gao <gaoliming@byosoft.com.cn> Cc: Dandan Bi <dandan.bi@intel.com> Signed-off-by: Oliver Smith-Denny <osde@linux.microsoft.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org> Acked-by: Leif Lindholm <quic_llindhol@quicinc.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
Diffstat (limited to 'MdeModulePkg/Core/Dxe/Mem/Pool.c')
-rw-r--r--MdeModulePkg/Core/Dxe/Mem/Pool.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/MdeModulePkg/Core/Dxe/Mem/Pool.c b/MdeModulePkg/Core/Dxe/Mem/Pool.c
index b20cbfdedb..716dd045f9 100644
--- a/MdeModulePkg/Core/Dxe/Mem/Pool.c
+++ b/MdeModulePkg/Core/Dxe/Mem/Pool.c
@@ -783,7 +783,7 @@ CoreFreePoolI (
NoPages = EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity) - 1;
NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1);
if (IsGuarded) {
- Head = AdjustPoolHeadF ((EFI_PHYSICAL_ADDRESS)(UINTN)Head);
+ Head = AdjustPoolHeadF ((EFI_PHYSICAL_ADDRESS)(UINTN)Head, NoPages, Size);
CoreFreePoolPagesWithGuard (
Pool->MemoryType,
(EFI_PHYSICAL_ADDRESS)(UINTN)Head,