MdeModulePkg/PiSmmCore: Implement heap guard feature for SMM mode
This feature makes use of paging mechanism to add a hidden (not present) page just before and after the allocated memory block. If the code tries to access memory outside of the allocated part, page fault exception will be triggered. This feature is controlled by three PCDs: gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPageType BIT2 and BIT3 of PcdHeapGuardPropertyMask can be used to enable or disable memory guard for SMM page and pool respectively. PcdHeapGuardPoolType and/or PcdHeapGuardPageType are used to enable or disable guard for specific type of memory. For example, we can turn on guard only for EfiRuntimeServicesCode and EfiRuntimeServicesData by setting the PCD with value 0x60. Pool memory is not ususally integer multiple of one page, and is more likely less than a page. There's no way to monitor the overflow at both top and bottom of pool memory. BIT7 of PcdHeapGuardPropertyMask is used to control how to position the head of pool memory so that it's easier to catch memory overflow in memory growing direction or in decreasing direction. Cc: Eric Dong <eric.dong@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Cc: Ruiyu Ni <ruiyu.ni@intel.com> Suggested-by: Ayellet Wolman <ayellet.wolman@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jian J Wang <jian.j.wang@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
@@ -64,6 +64,8 @@ LIST_ENTRY mFreeMemoryMapEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mFreeMemor
|
||||
@param[out] Memory A pointer to receive the base allocated memory
|
||||
address.
|
||||
@param[in] AddRegion If this memory is new added region.
|
||||
@param[in] NeedGuard Flag to indicate Guard page is needed
|
||||
or not
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
|
||||
@retval EFI_NOT_FOUND Could not allocate pages match the requirement.
|
||||
@@ -77,7 +79,8 @@ SmmInternalAllocatePagesEx (
|
||||
IN EFI_MEMORY_TYPE MemoryType,
|
||||
IN UINTN NumberOfPages,
|
||||
OUT EFI_PHYSICAL_ADDRESS *Memory,
|
||||
IN BOOLEAN AddRegion
|
||||
IN BOOLEAN AddRegion,
|
||||
IN BOOLEAN NeedGuard
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -112,7 +115,8 @@ AllocateMemoryMapEntry (
|
||||
EfiRuntimeServicesData,
|
||||
EFI_SIZE_TO_PAGES (RUNTIME_PAGE_ALLOCATION_GRANULARITY),
|
||||
&Mem,
|
||||
TRUE
|
||||
TRUE,
|
||||
FALSE
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
if(!EFI_ERROR (Status)) {
|
||||
@@ -688,6 +692,8 @@ InternalAllocAddress (
|
||||
@param[out] Memory A pointer to receive the base allocated memory
|
||||
address.
|
||||
@param[in] AddRegion If this memory is new added region.
|
||||
@param[in] NeedGuard Flag to indicate Guard page is needed
|
||||
or not
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
|
||||
@retval EFI_NOT_FOUND Could not allocate pages match the requirement.
|
||||
@@ -701,7 +707,8 @@ SmmInternalAllocatePagesEx (
|
||||
IN EFI_MEMORY_TYPE MemoryType,
|
||||
IN UINTN NumberOfPages,
|
||||
OUT EFI_PHYSICAL_ADDRESS *Memory,
|
||||
IN BOOLEAN AddRegion
|
||||
IN BOOLEAN AddRegion,
|
||||
IN BOOLEAN NeedGuard
|
||||
)
|
||||
{
|
||||
UINTN RequestedAddress;
|
||||
@@ -723,6 +730,21 @@ SmmInternalAllocatePagesEx (
|
||||
case AllocateAnyPages:
|
||||
RequestedAddress = (UINTN)(-1);
|
||||
case AllocateMaxAddress:
|
||||
if (NeedGuard) {
|
||||
*Memory = InternalAllocMaxAddressWithGuard (
|
||||
&mSmmMemoryMap,
|
||||
NumberOfPages,
|
||||
RequestedAddress,
|
||||
MemoryType
|
||||
);
|
||||
if (*Memory == (UINTN)-1) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
ASSERT (VerifyMemoryGuard (*Memory, NumberOfPages) == TRUE);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
*Memory = InternalAllocMaxAddress (
|
||||
&mSmmMemoryMap,
|
||||
NumberOfPages,
|
||||
@@ -766,6 +788,8 @@ SmmInternalAllocatePagesEx (
|
||||
@param[in] NumberOfPages The number of pages to allocate.
|
||||
@param[out] Memory A pointer to receive the base allocated memory
|
||||
address.
|
||||
@param[in] NeedGuard Flag to indicate Guard page is needed
|
||||
or not
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Parameters violate checking rules defined in spec.
|
||||
@retval EFI_NOT_FOUND Could not allocate pages match the requirement.
|
||||
@@ -779,10 +803,12 @@ SmmInternalAllocatePages (
|
||||
IN EFI_ALLOCATE_TYPE Type,
|
||||
IN EFI_MEMORY_TYPE MemoryType,
|
||||
IN UINTN NumberOfPages,
|
||||
OUT EFI_PHYSICAL_ADDRESS *Memory
|
||||
OUT EFI_PHYSICAL_ADDRESS *Memory,
|
||||
IN BOOLEAN NeedGuard
|
||||
)
|
||||
{
|
||||
return SmmInternalAllocatePagesEx (Type, MemoryType, NumberOfPages, Memory, FALSE);
|
||||
return SmmInternalAllocatePagesEx (Type, MemoryType, NumberOfPages, Memory,
|
||||
FALSE, NeedGuard);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -811,8 +837,11 @@ SmmAllocatePages (
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN NeedGuard;
|
||||
|
||||
Status = SmmInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory);
|
||||
NeedGuard = IsPageTypeToGuard (MemoryType, Type);
|
||||
Status = SmmInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory,
|
||||
NeedGuard);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
SmmCoreUpdateProfile (
|
||||
(EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),
|
||||
@@ -931,6 +960,7 @@ SmmInternalFreePagesEx (
|
||||
|
||||
@param[in] Memory Base address of memory being freed.
|
||||
@param[in] NumberOfPages The number of pages to free.
|
||||
@param[in] IsGuarded Is the memory to free guarded or not.
|
||||
|
||||
@retval EFI_NOT_FOUND Could not find the entry that covers the range.
|
||||
@retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
|
||||
@@ -941,9 +971,13 @@ EFI_STATUS
|
||||
EFIAPI
|
||||
SmmInternalFreePages (
|
||||
IN EFI_PHYSICAL_ADDRESS Memory,
|
||||
IN UINTN NumberOfPages
|
||||
IN UINTN NumberOfPages,
|
||||
IN BOOLEAN IsGuarded
|
||||
)
|
||||
{
|
||||
if (IsGuarded) {
|
||||
return SmmInternalFreePagesExWithGuard (Memory, NumberOfPages, FALSE);
|
||||
}
|
||||
return SmmInternalFreePagesEx (Memory, NumberOfPages, FALSE);
|
||||
}
|
||||
|
||||
@@ -966,8 +1000,10 @@ SmmFreePages (
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN IsGuarded;
|
||||
|
||||
Status = SmmInternalFreePages (Memory, NumberOfPages);
|
||||
IsGuarded = IsHeapGuardEnabled () && IsMemoryGuarded (Memory);
|
||||
Status = SmmInternalFreePages (Memory, NumberOfPages, IsGuarded);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
SmmCoreUpdateProfile (
|
||||
(EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),
|
||||
|
Reference in New Issue
Block a user