Oliver: This change reverts the changes done in AdjustPoolHeadA(). It matches the allocation logic. I think this change is good. Reviewed-by: Liming Gao <gaolim...@byosoft.com.cn> I am also OK to merge this change for the stable tag 202308.
Besides, AdjustPoolHeadA() implementation has the extra logic " Size = ALIGN_VALUE (Size, 8);". Seemly, this logic is not required, because Size has aligned by ALIGN_VARIABLE before enter into AdjustPoolHeadA. Thanks Liming > -----邮件原件----- > 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Leif Lindholm > 发送时间: 2023年8月15日 18:58 > 收件人: Ard Biesheuvel <a...@kernel.org>; Oliver Smith-Denny > <o...@linux.microsoft.com>; Liming Gao <gaolim...@byosoft.com.cn> > 抄送: devel@edk2.groups.io; Jian J Wang <jian.j.w...@intel.com>; Dandan > Bi <dandan...@intel.com>; Kinney, Michael D <michael.d.kin...@intel.com>; > 'Andrew Fish' <af...@apple.com> > 主题: edk2-stable202308 Re: [edk2-devel][PATCH v1 1/1] MdeModulePkg: > HeapGuard: Don't Assume Pool Head Allocated In First Page > > On 2023-08-09 22:51, Ard Biesheuvel wrote: > > On Wed, 9 Aug 2023 at 23:35, Oliver Smith-Denny > > <o...@linux.microsoft.com> wrote: > >> > >> 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_llind...@quicinc.com> > >> Cc: Ard Biesheuvel <ardb+tianoc...@kernel.org> > >> Cc: Jian J Wang <jian.j.w...@intel.com> > >> Cc: Liming Gao <gaolim...@byosoft.com.cn> > >> Cc: Dandan Bi <dandan...@intel.com> > >> > >> Signed-off-by: Oliver Smith-Denny <o...@linux.microsoft.com> > > > > Thanks a lot for fixing this - I ran into this a while ago but didn't > > quite figure out what exactly was going wrong, although the runtime > > allocation granularity was obviously a factor here. > > > > Reviewed-by: Ard Biesheuvel <a...@kernel.org> > > > > Can we include this in the stable tag please? > > Bugfix, submitted during soft freeze. I think it can go in. > *but* this affects !AARCH64 also - need a reaction from MdeModulePkg > maintainers. > > Acked-by: Leif Lindholm <quic_llind...@quicinc.com> > > >> --- > >> MdeModulePkg/Core/Dxe/Mem/HeapGuard.h | 7 ++++++- > >> MdeModulePkg/Core/Dxe/Mem/HeapGuard.c | 14 +++++++++++--- > >> MdeModulePkg/Core/Dxe/Mem/Pool.c | 2 +- > >> 3 files changed, 18 insertions(+), 5 deletions(-) > >> > >> diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h > b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h > >> index 9a32b4dd51d5..24b4206c0e02 100644 > >> --- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h > >> +++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.h > >> @@ -378,12 +378,17 @@ AdjustPoolHeadA ( > >> Get the page base address according to pool head address. > >> > >> @param[in] Memory Head address of pool to free. > >> + @param[in] NoPages Number of pages actually allocated. > >> + @param[in] Size Size of memory requested. > >> + (plus pool head/tail overhead) > >> > >> @return Address of pool head. > >> **/ > >> VOID * > >> AdjustPoolHeadF ( > >> - IN EFI_PHYSICAL_ADDRESS Memory > >> + IN EFI_PHYSICAL_ADDRESS Memory, > >> + IN UINTN NoPages, > >> + IN UINTN Size > >> ); > >> > >> /** > >> diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c > b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c > >> index 9377f620c5a5..0c0ca61872b4 100644 > >> --- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c > >> +++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c > >> @@ -1037,12 +1037,17 @@ AdjustPoolHeadA ( > >> Get the page base address according to pool head address. > >> > >> @param[in] Memory Head address of pool to free. > >> + @param[in] NoPages Number of pages actually allocated. > >> + @param[in] Size Size of memory requested. > >> + (plus pool head/tail overhead) > >> > >> @return Address of pool head. > >> **/ > >> VOID * > >> AdjustPoolHeadF ( > >> - IN EFI_PHYSICAL_ADDRESS Memory > >> + IN EFI_PHYSICAL_ADDRESS Memory, > >> + IN UINTN NoPages, > >> + IN UINTN Size > >> ) > >> { > >> if ((Memory == 0) || ((PcdGet8 (PcdHeapGuardPropertyMask) & > BIT7) != 0)) { > >> @@ -1053,9 +1058,12 @@ AdjustPoolHeadF ( > >> } > >> > >> // > >> - // Pool head is put near the tail Guard > >> + // Pool head is put near the tail Guard. We need to exactly undo the > addition done in AdjustPoolHeadA > >> + // because we may not have allocated the pool head on the first > allocated page, since we are aligned to > >> + // the tail and on some architectures, the runtime page allocation > granularity is > one page. So we allocate > >> + // more pages than we need and put the pool head somewhere past > the first page. > >> // > >> - return (VOID *)(UINTN)(Memory & ~EFI_PAGE_MASK); > >> + return (VOID *)(UINTN)(Memory + Size - EFI_PAGES_TO_SIZE > (NoPages)); > >> } > >> > >> /** > >> diff --git a/MdeModulePkg/Core/Dxe/Mem/Pool.c > b/MdeModulePkg/Core/Dxe/Mem/Pool.c > >> index b20cbfdedbab..716dd045f9fd 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, > >> -- > >> 2.40.1 > >> > > > > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#107777): https://edk2.groups.io/g/devel/message/107777 Mute This Topic: https://groups.io/mt/100771741/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-