Shadow stack will stop update after CET disable (DisableCet in
DisableReadOnlyPageWriteProtect), but normal smi stack will be
continue updated with the function return and enter
(DisableReadOnlyPageWriteProtect & EnableReadOnlyPageWriteProtect),
thus leading stack mismatch after CET re-enabled (EnableCet in
EnableReadOnlyPageWriteProtect).

Normal smi stack and shadow stack must be matched when CET enable,
otherwise CP Exception will happen, which is caused by a near RET
instruction (See SDM Vol 3, 6.15-Control Protection Exception).

With above requirement, CET feature enable & disable must be in the
same function to avoid stack mismatch issue.

Cc: Eric Dong <eric.d...@intel.com>
Cc: Ray Ni <ray...@intel.com>
Cc: Zeng Star <star.z...@intel.com>
Cc: Gerd Hoffmann <kra...@redhat.com>
Cc: Rahul Kumar <rahul1.ku...@intel.com>
Signed-off-by: Jiaxin Wu <jiaxin...@intel.com>
---
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h         |  10 +-
 UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | 104 ++++++++++++++-------
 UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c             |  19 +++-
 3 files changed, 91 insertions(+), 42 deletions(-)

diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h 
b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
index 654935dc76..daa843b057 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
@@ -1554,26 +1554,24 @@ SmmWaitForApArrival (
 
 /**
   Disable Write Protect on pages marked as read-only if Cr0.Bits.WP is 1.
 
   @param[out]  WpEnabled      If Cr0.WP is enabled.
-  @param[out]  CetEnabled     If CET is enabled.
+
 **/
 VOID
 DisableReadOnlyPageWriteProtect (
-  OUT BOOLEAN  *WpEnabled,
-  OUT BOOLEAN  *CetEnabled
+  OUT BOOLEAN  *WpEnabled
   );
 
 /**
   Enable Write Protect on pages marked as read-only.
 
   @param[out]  WpEnabled      If Cr0.WP should be enabled.
-  @param[out]  CetEnabled     If CET should be enabled.
+
 **/
 VOID
 EnableReadOnlyPageWriteProtect (
-  BOOLEAN  WpEnabled,
-  BOOLEAN  CetEnabled
+  BOOLEAN  WpEnabled
   );
 
 #endif
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c 
b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
index 6f49866615..2c198a161a 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
@@ -42,61 +42,44 @@ BOOLEAN  mIsReadOnlyPageTable = FALSE;
 
 /**
   Disable Write Protect on pages marked as read-only if Cr0.Bits.WP is 1.
 
   @param[out]  WpEnabled      If Cr0.WP is enabled.
-  @param[out]  CetEnabled     If CET is enabled.
+
 **/
 VOID
 DisableReadOnlyPageWriteProtect (
-  OUT BOOLEAN  *WpEnabled,
-  OUT BOOLEAN  *CetEnabled
+  OUT BOOLEAN  *WpEnabled
   )
 {
   IA32_CR0  Cr0;
 
-  *CetEnabled = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0) ? TRUE : FALSE;
-  Cr0.UintN   = AsmReadCr0 ();
-  *WpEnabled  = (Cr0.Bits.WP != 0) ? TRUE : FALSE;
+  Cr0.UintN  = AsmReadCr0 ();
+  *WpEnabled = (Cr0.Bits.WP != 0) ? TRUE : FALSE;
   if (*WpEnabled) {
-    if (*CetEnabled) {
-      //
-      // CET must be disabled if WP is disabled. Disable CET before clearing 
CR0.WP.
-      //
-      DisableCet ();
-    }
-
     Cr0.Bits.WP = 0;
     AsmWriteCr0 (Cr0.UintN);
   }
 }
 
 /**
   Enable Write Protect on pages marked as read-only.
 
   @param[out]  WpEnabled      If Cr0.WP should be enabled.
-  @param[out]  CetEnabled     If CET should be enabled.
+
 **/
 VOID
 EnableReadOnlyPageWriteProtect (
-  BOOLEAN  WpEnabled,
-  BOOLEAN  CetEnabled
+  BOOLEAN  WpEnabled
   )
 {
   IA32_CR0  Cr0;
 
   if (WpEnabled) {
     Cr0.UintN   = AsmReadCr0 ();
     Cr0.Bits.WP = 1;
     AsmWriteCr0 (Cr0.UintN);
-
-    if (CetEnabled) {
-      //
-      // re-enable CET.
-      //
-      EnableCet ();
-    }
   }
 }
 
 /**
   Initialize a buffer pool for page table use only.
@@ -157,13 +140,29 @@ InitializePageTablePool (
 
   //
   // If page table memory has been marked as RO, mark the new pool pages as 
read-only.
   //
   if (mIsReadOnlyPageTable) {
-    DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
+    //
+    // CET must be disabled if WP is disabled.
+    //
+    CetEnabled = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0) ? TRUE : FALSE;
+    if (CetEnabled) {
+      DisableCet ();
+    }
+
+    DisableReadOnlyPageWriteProtect (&WpEnabled);
+
     SmmSetMemoryAttributes ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, 
EFI_PAGES_TO_SIZE (PoolPages), EFI_MEMORY_RO);
-    EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
+
+    //
+    // Enable the WP and restore CET to enable
+    //
+    EnableReadOnlyPageWriteProtect (WpEnabled);
+    if (CetEnabled) {
+      EnableCet ();
+    }
   }
 
   return TRUE;
 }
 
@@ -1055,11 +1054,19 @@ SetMemMapAttributes (
     Status = PageTableParse (PageTable, mPagingMode, Map, &Count);
   }
 
   ASSERT_RETURN_ERROR (Status);
 
-  DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
+  //
+  // CET must be disabled if WP is disabled.
+  //
+  CetEnabled = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0) ? TRUE : FALSE;
+  if (CetEnabled) {
+    DisableCet ();
+  }
+
+  DisableReadOnlyPageWriteProtect (&WpEnabled);
 
   MemoryMap = MemoryMapStart;
   for (Index = 0; Index < MemoryMapEntryCount; Index++) {
     DEBUG ((DEBUG_VERBOSE, "SetAttribute: Memory Entry - 0x%lx, 0x%x\n", 
MemoryMap->PhysicalStart, MemoryMap->NumberOfPages));
     if (MemoryMap->Type == EfiRuntimeServicesCode) {
@@ -1085,11 +1092,18 @@ SetMemMapAttributes (
       );
 
     MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);
   }
 
-  EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
+  //
+  // Enable the WP and restore CET to enable
+  //
+  EnableReadOnlyPageWriteProtect (WpEnabled);
+  if (CetEnabled) {
+    EnableCet ();
+  }
+
   FreePool (Map);
 
   PatchSmmSaveStateMap ();
   PatchGdtIdtMap ();
 
@@ -1399,11 +1413,19 @@ SetUefiMemMapAttributes (
 
   PERF_FUNCTION_BEGIN ();
 
   DEBUG ((DEBUG_INFO, "SetUefiMemMapAttributes\n"));
 
-  DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
+  //
+  // CET must be disabled if WP is disabled.
+  //
+  CetEnabled = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0) ? TRUE : FALSE;
+  if (CetEnabled) {
+    DisableCet ();
+  }
+
+  DisableReadOnlyPageWriteProtect (&WpEnabled);
 
   if (mUefiMemoryMap != NULL) {
     MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;
     MemoryMap           = mUefiMemoryMap;
     for (Index = 0; Index < MemoryMapEntryCount; Index++) {
@@ -1479,11 +1501,17 @@ SetUefiMemMapAttributes (
 
       Entry = NEXT_MEMORY_DESCRIPTOR (Entry, 
mUefiMemoryAttributesTable->DescriptorSize);
     }
   }
 
-  EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
+  //
+  // Enable the WP and restore CET to enable
+  //
+  EnableReadOnlyPageWriteProtect (WpEnabled);
+  if (CetEnabled) {
+    EnableCet ();
+  }
 
   //
   // Do not free mUefiMemoryAttributesTable, it will be checked in 
IsSmmCommBufferForbiddenAddress().
   //
 
@@ -1881,23 +1909,31 @@ SetPageTableAttributes (
 
   PERF_FUNCTION_BEGIN ();
   DEBUG ((DEBUG_INFO, "SetPageTableAttributes\n"));
 
   //
-  // Disable write protection, because we need mark page table to be write 
protected.
-  // We need *write* page table memory, to mark itself to be *read only*.
+  // CET must be disabled if WP is disabled.
   //
-  DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
+  CetEnabled = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0) ? TRUE : FALSE;
+  if (CetEnabled) {
+    DisableCet ();
+  }
+
+  DisableReadOnlyPageWriteProtect (&WpEnabled);
 
   // Set memory used by page table as Read Only.
   DEBUG ((DEBUG_INFO, "Start...\n"));
   EnablePageTableProtection ();
 
   //
-  // Enable write protection, after page table attribute updated.
+  // Enable the WP and restore CET to enable
   //
-  EnableReadOnlyPageWriteProtect (TRUE, CetEnabled);
+  EnableReadOnlyPageWriteProtect (WpEnabled);
+  if (CetEnabled) {
+    EnableCet ();
+  }
+
   mIsReadOnlyPageTable = TRUE;
 
   //
   // Flush TLB after mark all page table pool as read only.
   //
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c 
b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
index 7ac3c66f91..71fdf5f34a 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
@@ -604,11 +604,20 @@ InitPaging (
     Limit = BASE_4GB;
   } else {
     Limit = (IsRestrictedMemoryAccess ()) ? LShiftU64 (1, 
mPhysicalAddressBits) : BASE_4GB;
   }
 
-  DisableReadOnlyPageWriteProtect (&WpEnabled, &CetEnabled);
+  //
+  // CET must be disabled if WP is disabled.
+  //
+  CetEnabled = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0) ? TRUE : FALSE;
+  if (CetEnabled) {
+    DisableCet ();
+  }
+
+  DisableReadOnlyPageWriteProtect (&WpEnabled);
+
   //
   // [0, 4k] may be non-present.
   //
   PreviousAddress = ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 
0) ? BASE_4KB : 0;
 
@@ -670,11 +679,17 @@ InitPaging (
     //
     Status = ConvertMemoryPageAttributes (PageTable, mPagingMode, 
PreviousAddress, Limit - PreviousAddress, MemoryAttrMask, TRUE, NULL);
     ASSERT_RETURN_ERROR (Status);
   }
 
-  EnableReadOnlyPageWriteProtect (WpEnabled, CetEnabled);
+  //
+  // Enable the WP and restore CET to enable
+  //
+  EnableReadOnlyPageWriteProtect (WpEnabled);
+  if (CetEnabled) {
+    EnableCet ();
+  }
 
   //
   // Flush TLB
   //
   CpuFlushTlb ();
-- 
2.16.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#110619): https://edk2.groups.io/g/devel/message/110619
Mute This Topic: https://groups.io/mt/102362300/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to