[edk2-devel] [Patch V4 08/15] UefiCpuPkg/PiSmmCpuDxeSmm: Clear CR0.WP before modify page table

duntan posted 15 patches 1 year, 3 months ago
There is a newer version of this series
[edk2-devel] [Patch V4 08/15] UefiCpuPkg/PiSmmCpuDxeSmm: Clear CR0.WP before modify page table
Posted by duntan 1 year, 3 months ago
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>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
---
 UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | 11 +++++++++++
 UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c             |  5 +++++
 2 files changed, 16 insertions(+)

diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
index 4b512edf68..ef0ba9a355 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
@@ -1036,6 +1036,8 @@ SetMemMapAttributes (
   IA32_MAP_ENTRY                        *Map;
   UINTN                                 Count;
   UINT64                                MemoryAttribute;
+  BOOLEAN                               WpEnabled;
+  BOOLEAN                               CetEnabled;
 
   SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable);
   if (MemoryAttributesTable == NULL) {
@@ -1078,6 +1080,8 @@ SetMemMapAttributes (
 
   ASSERT_RETURN_ERROR (Status);
 
+  DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
+
   MemoryMap = MemoryMapStart;
   for (Index = 0; Index < MemoryMapEntryCount; Index++) {
     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);
   }
 
+  EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
   FreePool (Map);
 
   PatchSmmSaveStateMap ();
@@ -1411,9 +1416,13 @@ SetUefiMemMapAttributes (
   UINTN                  MemoryMapEntryCount;
   UINTN                  Index;
   EFI_MEMORY_DESCRIPTOR  *Entry;
+  BOOLEAN                WpEnabled;
+  BOOLEAN                CetEnabled;
 
   DEBUG ((DEBUG_INFO, "SetUefiMemMapAttributes\n"));
 
+  DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
+
   if (mUefiMemoryMap != NULL) {
     MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;
     MemoryMap           = mUefiMemoryMap;
@@ -1492,6 +1501,8 @@ SetUefiMemMapAttributes (
     }
   }
 
+  EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
+
   //
   // Do not free mUefiMemoryAttributesTable, it will be checked in IsSmmCommBufferForbiddenAddress().
   //
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
index 1b0b6673e1..5625ba0cac 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
@@ -574,6 +574,8 @@ InitPaging (
   BOOLEAN   Nx;
   IA32_CR4  Cr4;
   BOOLEAN   Enable5LevelPaging;
+  BOOLEAN   WpEnabled;
+  BOOLEAN   CetEnabled;
 
   Cr4.UintN          = AsmReadCr4 ();
   Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1);
@@ -620,6 +622,7 @@ InitPaging (
     NumberOfPdptEntries = 4;
   }
 
+  DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
   //
   // Go through page table and change 2MB-page into 4KB-page.
   //
@@ -800,6 +803,8 @@ InitPaging (
     } // end for PML4
   } // end for PML5
 
+  EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
+
   //
   // Flush TLB
   //
-- 
2.31.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#104928): https://edk2.groups.io/g/devel/message/104928
Mute This Topic: https://groups.io/mt/98922934/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [Patch V4 08/15] UefiCpuPkg/PiSmmCpuDxeSmm: Clear CR0.WP before modify page table
Posted by Ni, Ray 1 year, 3 months ago
Reviewed-by: Ray Ni <ray.ni@intel.com>

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of duntan
> Sent: Tuesday, May 16, 2023 5:59 PM
> To: devel@edk2.groups.io
> Cc: Dong, Eric <eric.dong@intel.com>; Ni, Ray <ray.ni@intel.com>; Kumar, Rahul
> R <rahul.r.kumar@intel.com>; Gerd Hoffmann <kraxel@redhat.com>
> Subject: [edk2-devel] [Patch V4 08/15] 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>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Rahul Kumar <rahul1.kumar@intel.com>
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | 11
> +++++++++++
>  UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c             |  5 +++++
>  2 files changed, 16 insertions(+)
> 
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
> b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
> index 4b512edf68..ef0ba9a355 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
> @@ -1036,6 +1036,8 @@ SetMemMapAttributes (
>    IA32_MAP_ENTRY                        *Map;
>    UINTN                                 Count;
>    UINT64                                MemoryAttribute;
> +  BOOLEAN                               WpEnabled;
> +  BOOLEAN                               CetEnabled;
> 
>    SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid,
> (VOID **)&MemoryAttributesTable);
>    if (MemoryAttributesTable == NULL) {
> @@ -1078,6 +1080,8 @@ SetMemMapAttributes (
> 
>    ASSERT_RETURN_ERROR (Status);
> 
> +  DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
> +
>    MemoryMap = MemoryMapStart;
>    for (Index = 0; Index < MemoryMapEntryCount; Index++) {
>      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);
>    }
> 
> +  EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
>    FreePool (Map);
> 
>    PatchSmmSaveStateMap ();
> @@ -1411,9 +1416,13 @@ SetUefiMemMapAttributes (
>    UINTN                  MemoryMapEntryCount;
>    UINTN                  Index;
>    EFI_MEMORY_DESCRIPTOR  *Entry;
> +  BOOLEAN                WpEnabled;
> +  BOOLEAN                CetEnabled;
> 
>    DEBUG ((DEBUG_INFO, "SetUefiMemMapAttributes\n"));
> 
> +  DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
> +
>    if (mUefiMemoryMap != NULL) {
>      MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;
>      MemoryMap           = mUefiMemoryMap;
> @@ -1492,6 +1501,8 @@ SetUefiMemMapAttributes (
>      }
>    }
> 
> +  EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
> +
>    //
>    // Do not free mUefiMemoryAttributesTable, it will be checked in
> IsSmmCommBufferForbiddenAddress().
>    //
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
> b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
> index 1b0b6673e1..5625ba0cac 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
> @@ -574,6 +574,8 @@ InitPaging (
>    BOOLEAN   Nx;
>    IA32_CR4  Cr4;
>    BOOLEAN   Enable5LevelPaging;
> +  BOOLEAN   WpEnabled;
> +  BOOLEAN   CetEnabled;
> 
>    Cr4.UintN          = AsmReadCr4 ();
>    Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1);
> @@ -620,6 +622,7 @@ InitPaging (
>      NumberOfPdptEntries = 4;
>    }
> 
> +  DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
>    //
>    // Go through page table and change 2MB-page into 4KB-page.
>    //
> @@ -800,6 +803,8 @@ InitPaging (
>      } // end for PML4
>    } // end for PML5
> 
> +  EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
> +
>    //
>    // Flush TLB
>    //
> --
> 2.31.1.windows.1
> 
> 
> 
> 
> 



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#105619): https://edk2.groups.io/g/devel/message/105619
Mute This Topic: https://groups.io/mt/98922934/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/3901457/1787277/102458076/xyzzy [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-