mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-25 22:54:51 +02:00
UefiCpuPkg/PiSmmCpuDxeSmm: Avoid setting non-present range to RO/NX
In PiSmmCpuDxeSmm code, SetMemMapAttributes() marks memory ranges in SmmMemoryAttributesTable to RO/NX. There may exist non-present range in these memory ranges. Set other attributes for a non-present range is not permitted in CpuPageTableMapLib. So add code to handle this case. Only map the present ranges in SmmMemoryAttributesTable to RO or NX. Signed-off-by: Dun Tan <dun.tan@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Cc: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
6585ced558
commit
f51967280b
@ -918,6 +918,70 @@ PatchGdtIdtMap (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function set [Base, Limit] to the input MemoryAttribute.
|
||||||
|
|
||||||
|
@param Base Start address of range.
|
||||||
|
@param Limit Limit address of range.
|
||||||
|
@param Attribute The bit mask of attributes to modify for the memory region.
|
||||||
|
@param Map Pointer to the array of Cr3 IA32_MAP_ENTRY.
|
||||||
|
@param Count Count of IA32_MAP_ENTRY in Map.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SetMemMapWithNonPresentRange (
|
||||||
|
UINT64 Base,
|
||||||
|
UINT64 Limit,
|
||||||
|
UINT64 Attribute,
|
||||||
|
IA32_MAP_ENTRY *Map,
|
||||||
|
UINTN Count
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
UINT64 NonPresentRangeStart;
|
||||||
|
|
||||||
|
NonPresentRangeStart = 0;
|
||||||
|
for (Index = 0; Index < Count; Index++) {
|
||||||
|
if ((Map[Index].LinearAddress > NonPresentRangeStart) &&
|
||||||
|
(Base < Map[Index].LinearAddress) && (Limit > NonPresentRangeStart))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// We should NOT set attributes for non-present ragne.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// There is a non-present ( [NonPresentStart, Map[Index].LinearAddress] ) range before current Map[Index]
|
||||||
|
// and it is overlapped with [Base, Limit].
|
||||||
|
//
|
||||||
|
if (Base < NonPresentRangeStart) {
|
||||||
|
SmmSetMemoryAttributes (
|
||||||
|
Base,
|
||||||
|
NonPresentRangeStart - Base,
|
||||||
|
Attribute
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Base = Map[Index].LinearAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
NonPresentRangeStart = Map[Index].LinearAddress + Map[Index].Length;
|
||||||
|
if (NonPresentRangeStart >= Limit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Limit = MIN (NonPresentRangeStart, Limit);
|
||||||
|
|
||||||
|
if (Base < Limit) {
|
||||||
|
//
|
||||||
|
// There is no non-present range in current [Base, Limit] anymore.
|
||||||
|
//
|
||||||
|
SmmSetMemoryAttributes (
|
||||||
|
Base,
|
||||||
|
Limit - Base,
|
||||||
|
Attribute
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This function sets memory attribute according to MemoryAttributesTable.
|
This function sets memory attribute according to MemoryAttributesTable.
|
||||||
**/
|
**/
|
||||||
@ -932,6 +996,11 @@ SetMemMapAttributes (
|
|||||||
UINTN DescriptorSize;
|
UINTN DescriptorSize;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;
|
EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;
|
||||||
|
UINTN PageTable;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
IA32_MAP_ENTRY *Map;
|
||||||
|
UINTN Count;
|
||||||
|
UINT64 MemoryAttribute;
|
||||||
|
|
||||||
SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable);
|
SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable);
|
||||||
if (MemoryAttributesTable == NULL) {
|
if (MemoryAttributesTable == NULL) {
|
||||||
@ -960,36 +1029,52 @@ SetMemMapAttributes (
|
|||||||
MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);
|
MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Count = 0;
|
||||||
|
Map = NULL;
|
||||||
|
PageTable = AsmReadCr3 ();
|
||||||
|
Status = PageTableParse (PageTable, mPagingMode, NULL, &Count);
|
||||||
|
while (Status == RETURN_BUFFER_TOO_SMALL) {
|
||||||
|
if (Map != NULL) {
|
||||||
|
FreePool (Map);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map = AllocatePool (Count * sizeof (IA32_MAP_ENTRY));
|
||||||
|
ASSERT (Map != NULL);
|
||||||
|
Status = PageTableParse (PageTable, mPagingMode, Map, &Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_RETURN_ERROR (Status);
|
||||||
|
|
||||||
MemoryMap = MemoryMapStart;
|
MemoryMap = MemoryMapStart;
|
||||||
for (Index = 0; Index < MemoryMapEntryCount; Index++) {
|
for (Index = 0; Index < MemoryMapEntryCount; Index++) {
|
||||||
DEBUG ((DEBUG_VERBOSE, "SetAttribute: Memory Entry - 0x%lx, 0x%x\n", MemoryMap->PhysicalStart, MemoryMap->NumberOfPages));
|
DEBUG ((DEBUG_VERBOSE, "SetAttribute: Memory Entry - 0x%lx, 0x%x\n", MemoryMap->PhysicalStart, MemoryMap->NumberOfPages));
|
||||||
switch (MemoryMap->Type) {
|
if (MemoryMap->Type == EfiRuntimeServicesCode) {
|
||||||
case EfiRuntimeServicesCode:
|
MemoryAttribute = EFI_MEMORY_RO;
|
||||||
SmmSetMemoryAttributes (
|
} else {
|
||||||
MemoryMap->PhysicalStart,
|
ASSERT ((MemoryMap->Type == EfiRuntimeServicesData) || (MemoryMap->Type == EfiConventionalMemory));
|
||||||
EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages),
|
//
|
||||||
EFI_MEMORY_RO
|
// Set other type memory as NX.
|
||||||
);
|
//
|
||||||
break;
|
MemoryAttribute = EFI_MEMORY_XP;
|
||||||
case EfiRuntimeServicesData:
|
|
||||||
SmmSetMemoryAttributes (
|
|
||||||
MemoryMap->PhysicalStart,
|
|
||||||
EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages),
|
|
||||||
EFI_MEMORY_XP
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
SmmSetMemoryAttributes (
|
|
||||||
MemoryMap->PhysicalStart,
|
|
||||||
EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages),
|
|
||||||
EFI_MEMORY_XP
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// There may exist non-present range overlaps with the MemoryMap range.
|
||||||
|
// Do not change other attributes of non-present range while still remaining it as non-present
|
||||||
|
//
|
||||||
|
SetMemMapWithNonPresentRange (
|
||||||
|
MemoryMap->PhysicalStart,
|
||||||
|
MemoryMap->PhysicalStart + EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages),
|
||||||
|
MemoryAttribute,
|
||||||
|
Map,
|
||||||
|
Count
|
||||||
|
);
|
||||||
|
|
||||||
MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);
|
MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FreePool (Map);
|
||||||
|
|
||||||
PatchSmmSaveStateMap ();
|
PatchSmmSaveStateMap ();
|
||||||
PatchGdtIdtMap ();
|
PatchGdtIdtMap ();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user