UefiCpuPkg/PiSmmCpuDxeSmm: Clear CR0.WP before modify page table

Clear CR0.WP before modify smm page table. Currently, there is
an assumption that smm pagetable is always RW before ReadyToLock.
However, when AMD SEV is enabled, FvbServicesSmm driver calls
MemEncryptSevClearMmioPageEncMask to clear AddressEncMask bit
in smm page table for this range:
[PcdOvmfFdBaseAddress,PcdOvmfFdBaseAddress+PcdOvmfFirmwareFdSize]
If page slpit happens in this process, new memory for smm page
table is allocated. Then the newly allocated page table memory
is marked as RO in smm page table in this FvbServicesSmm driver,
which may lead to PF if smm code doesn't clear CR0.WP before
modify smm page table when ReadyToLock.

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:
Dun Tan 2023-04-20 16:09:15 +08:00 committed by Ray Ni
parent 7b6e7d0098
commit ef64ae06f8
2 changed files with 16 additions and 0 deletions

View File

@ -1033,6 +1033,8 @@ SetMemMapAttributes (
IA32_MAP_ENTRY *Map; IA32_MAP_ENTRY *Map;
UINTN Count; UINTN Count;
UINT64 MemoryAttribute; UINT64 MemoryAttribute;
BOOLEAN WpEnabled;
BOOLEAN CetEnabled;
SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable); SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable);
if (MemoryAttributesTable == NULL) { if (MemoryAttributesTable == NULL) {
@ -1077,6 +1079,8 @@ SetMemMapAttributes (
ASSERT_RETURN_ERROR (Status); ASSERT_RETURN_ERROR (Status);
DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
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));
@ -1105,6 +1109,7 @@ SetMemMapAttributes (
MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize); MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);
} }
EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
FreePool (Map); FreePool (Map);
PatchSmmSaveStateMap (); PatchSmmSaveStateMap ();
@ -1411,11 +1416,15 @@ SetUefiMemMapAttributes (
UINTN MemoryMapEntryCount; UINTN MemoryMapEntryCount;
UINTN Index; UINTN Index;
EFI_MEMORY_DESCRIPTOR *Entry; EFI_MEMORY_DESCRIPTOR *Entry;
BOOLEAN WpEnabled;
BOOLEAN CetEnabled;
PERF_FUNCTION_BEGIN (); PERF_FUNCTION_BEGIN ();
DEBUG ((DEBUG_INFO, "SetUefiMemMapAttributes\n")); DEBUG ((DEBUG_INFO, "SetUefiMemMapAttributes\n"));
DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
if (mUefiMemoryMap != NULL) { if (mUefiMemoryMap != NULL) {
MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize; MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;
MemoryMap = mUefiMemoryMap; MemoryMap = mUefiMemoryMap;
@ -1494,6 +1503,8 @@ SetUefiMemMapAttributes (
} }
} }
EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
// //
// Do not free mUefiMemoryAttributesTable, it will be checked in IsSmmCommBufferForbiddenAddress(). // Do not free mUefiMemoryAttributesTable, it will be checked in IsSmmCommBufferForbiddenAddress().
// //

View File

@ -574,6 +574,8 @@ InitPaging (
BOOLEAN Nx; BOOLEAN Nx;
IA32_CR4 Cr4; IA32_CR4 Cr4;
BOOLEAN Enable5LevelPaging; BOOLEAN Enable5LevelPaging;
BOOLEAN WpEnabled;
BOOLEAN CetEnabled;
PERF_FUNCTION_BEGIN (); PERF_FUNCTION_BEGIN ();
@ -622,6 +624,7 @@ InitPaging (
NumberOfPdptEntries = 4; NumberOfPdptEntries = 4;
} }
DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
// //
// Go through page table and change 2MB-page into 4KB-page. // Go through page table and change 2MB-page into 4KB-page.
// //
@ -802,6 +805,8 @@ InitPaging (
} // end for PML4 } // end for PML4
} // end for PML5 } // end for PML5
EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
// //
// Flush TLB // Flush TLB
// //