mirror of https://github.com/acidanthera/audk.git
MdeModulePkg/Core: prevent re-acquire GCD memory lock
This issue is hidden in current code but exposed by introduction of freed-memory guard feature due to the fact that the feature will turn all pool allocation to page allocation. The solution is moving the memory allocation in CoreGetMemorySpaceMap() to be out of the GCD memory map lock. CoreDumpGcdMemorySpaceMap() => CoreGetMemorySpaceMap() => CoreAcquireGcdMemoryLock () * AllocatePool() => InternalAllocatePool() => CoreAllocatePool() => CoreAllocatePoolI() => CoreAllocatePoolPagesI() => CoreAllocatePoolPages() => FindFreePages() => PromoteMemoryResource() => CoreAcquireGcdMemoryLock() ** Cc: Star Zeng <star.zeng@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jian J Wang <jian.j.wang@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com>
This commit is contained in:
parent
54efcfea81
commit
bb685071c2
|
@ -1691,10 +1691,10 @@ CoreGetMemorySpaceMap (
|
||||||
OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap
|
OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
|
||||||
LIST_ENTRY *Link;
|
LIST_ENTRY *Link;
|
||||||
EFI_GCD_MAP_ENTRY *Entry;
|
EFI_GCD_MAP_ENTRY *Entry;
|
||||||
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor;
|
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor;
|
||||||
|
UINTN DescriptorCount;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Make sure parameters are valid
|
// Make sure parameters are valid
|
||||||
|
@ -1706,38 +1706,75 @@ CoreGetMemorySpaceMap (
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*NumberOfDescriptors = 0;
|
||||||
|
*MemorySpaceMap = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Take the lock, for entering the loop with the lock held.
|
||||||
|
//
|
||||||
CoreAcquireGcdMemoryLock ();
|
CoreAcquireGcdMemoryLock ();
|
||||||
|
while (TRUE) {
|
||||||
|
//
|
||||||
|
// Count descriptors. It might be done more than once because the
|
||||||
|
// AllocatePool() called below has to be running outside the GCD lock.
|
||||||
|
//
|
||||||
|
DescriptorCount = CoreCountGcdMapEntry (&mGcdMemorySpaceMap);
|
||||||
|
if (DescriptorCount == *NumberOfDescriptors) {
|
||||||
|
//
|
||||||
|
// Fill in the MemorySpaceMap if no memory space map change.
|
||||||
|
//
|
||||||
|
Descriptor = *MemorySpaceMap;
|
||||||
|
Link = mGcdMemorySpaceMap.ForwardLink;
|
||||||
|
while (Link != &mGcdMemorySpaceMap) {
|
||||||
|
Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
|
||||||
|
BuildMemoryDescriptor (Descriptor, Entry);
|
||||||
|
Descriptor++;
|
||||||
|
Link = Link->ForwardLink;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// We're done; exit the loop with the lock held.
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Count the number of descriptors
|
// Release the lock before memory allocation, because it might cause
|
||||||
//
|
// GCD lock conflict in one of calling path in AllocatPool().
|
||||||
*NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdMemorySpaceMap);
|
//
|
||||||
|
CoreReleaseGcdMemoryLock ();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate the MemorySpaceMap
|
// Allocate memory to store the MemorySpaceMap. Note it might be already
|
||||||
//
|
// allocated if there's map descriptor change during memory allocation at
|
||||||
*MemorySpaceMap = AllocatePool (*NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));
|
// last time.
|
||||||
if (*MemorySpaceMap == NULL) {
|
//
|
||||||
Status = EFI_OUT_OF_RESOURCES;
|
if (*MemorySpaceMap != NULL) {
|
||||||
goto Done;
|
FreePool (*MemorySpaceMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
*MemorySpaceMap = AllocatePool (DescriptorCount *
|
||||||
|
sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));
|
||||||
|
if (*MemorySpaceMap == NULL) {
|
||||||
|
*NumberOfDescriptors = 0;
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Save the descriptor count got before for another round of check to make
|
||||||
|
// sure we won't miss any, since we have code running outside the GCD lock.
|
||||||
|
//
|
||||||
|
*NumberOfDescriptors = DescriptorCount;
|
||||||
|
//
|
||||||
|
// Re-acquire the lock, for the next iteration.
|
||||||
|
//
|
||||||
|
CoreAcquireGcdMemoryLock ();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Fill in the MemorySpaceMap
|
// We exited the loop with the lock held, release it.
|
||||||
//
|
//
|
||||||
Descriptor = *MemorySpaceMap;
|
|
||||||
Link = mGcdMemorySpaceMap.ForwardLink;
|
|
||||||
while (Link != &mGcdMemorySpaceMap) {
|
|
||||||
Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
|
|
||||||
BuildMemoryDescriptor (Descriptor, Entry);
|
|
||||||
Descriptor++;
|
|
||||||
Link = Link->ForwardLink;
|
|
||||||
}
|
|
||||||
Status = EFI_SUCCESS;
|
|
||||||
|
|
||||||
Done:
|
|
||||||
CoreReleaseGcdMemoryLock ();
|
CoreReleaseGcdMemoryLock ();
|
||||||
return Status;
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue