UefiCpuPkg/PiSmmCpuDxeSmm: Fix memory protection crash
authorStar Zeng <star.zeng@intel.com>
Thu, 24 Aug 2017 02:59:14 +0000 (10:59 +0800)
committerStar Zeng <star.zeng@intel.com>
Mon, 28 Aug 2017 01:35:16 +0000 (09:35 +0800)
https://bugzilla.tianocore.org/show_bug.cgi?id=624 reports
memory protection crash in PiSmmCpuDxeSmm, Ia32 build with
RAM above 4GB (of which 2GB are placed in 64-bit address).
It is because UEFI builds identity mapping page tables,
>4G address is not supported at Ia32 build.

This patch is to get the PhysicalAddressBits that is used
to build in PageTbl.c(Ia32/X64), and use it to check whether
the address is supported or not in ConvertMemoryPageAttributes().

With this patch, the debug messages will be like below.
UefiMemory protection: 0x0 - 0x9F000 Success
UefiMemory protection: 0x100000 - 0x807000 Success
UefiMemory protection: 0x808000 - 0x810000 Success
UefiMemory protection: 0x818000 - 0x820000 Success
UefiMemory protection: 0x1510000 - 0x7B798000 Success
UefiMemory protection: 0x7B79B000 - 0x7E538000 Success
UefiMemory protection: 0x7E539000 - 0x7E545000 Success
UefiMemory protection: 0x7E55A000 - 0x7E61F000 Success
UefiMemory protection: 0x7E62B000 - 0x7F6AB000 Success
UefiMemory protection: 0x7F703000 - 0x7F70B000 Success
UefiMemory protection: 0x7F70F000 - 0x7F778000 Success
UefiMemory protection: 0x100000000 - 0x180000000 Unsupported

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Eric Dong <eric.dong@intel.com>
Originally-suggested-by: Jiewen Yao <jiewen.yao@intel.com>
Reported-by: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c

index 32ce5958c59c364f6077bcc41078f052155ab121..e88b42d73343d7316b236cf582c4465a984d6461 100644 (file)
@@ -16,6 +16,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "PiSmmCpuDxeSmm.h"\r
 \r
 \r
 #include "PiSmmCpuDxeSmm.h"\r
 \r
+UINT8                               mPhysicalAddressBits;\r
+\r
 /**\r
   Create PageTable for SMM use.\r
 \r
 /**\r
   Create PageTable for SMM use.\r
 \r
@@ -36,6 +38,8 @@ SmmInitPageTable (
   //\r
   InitializeSpinLock (mPFLock);\r
 \r
   //\r
   InitializeSpinLock (mPFLock);\r
 \r
+  mPhysicalAddressBits = 32;\r
+\r
   if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {\r
     //\r
     // Set own Page Fault entry instead of the default one, because SMM Profile\r
   if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {\r
     //\r
     // Set own Page Fault entry instead of the default one, because SMM Profile\r
index dbce9ec520fed30e862633979ca0e777ed539a91..1cf85c1481a76e547331d06e2681e02e45365786 100644 (file)
@@ -419,6 +419,7 @@ extern SPIN_LOCK                           *mConfigSmmCodeAccessCheckLock;
 extern SPIN_LOCK                           *mMemoryMappedLock;\r
 extern EFI_SMRAM_DESCRIPTOR                *mSmmCpuSmramRanges;\r
 extern UINTN                               mSmmCpuSmramRangeCount;\r
 extern SPIN_LOCK                           *mMemoryMappedLock;\r
 extern EFI_SMRAM_DESCRIPTOR                *mSmmCpuSmramRanges;\r
 extern UINTN                               mSmmCpuSmramRangeCount;\r
+extern UINT8                               mPhysicalAddressBits;\r
 \r
 //\r
 // Copy of the PcdPteMemoryEncryptionAddressOrMask\r
 \r
 //\r
 // Copy of the PcdPteMemoryEncryptionAddressOrMask\r
index a535389c26cebb6fe2ba068d930a4b671e4204c7..3ad5256f1e03d64b4a93bfe7eee74de80c5173c1 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
 /** @file\r
 \r
-Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -380,6 +380,7 @@ ConvertMemoryPageAttributes (
   PAGE_ATTRIBUTE                    SplitAttribute;\r
   RETURN_STATUS                     Status;\r
   BOOLEAN                           IsEntryModified;\r
   PAGE_ATTRIBUTE                    SplitAttribute;\r
   RETURN_STATUS                     Status;\r
   BOOLEAN                           IsEntryModified;\r
+  EFI_PHYSICAL_ADDRESS              MaximumSupportMemAddress;\r
 \r
   ASSERT (Attributes != 0);\r
   ASSERT ((Attributes & ~(EFI_MEMORY_RP | EFI_MEMORY_RO | EFI_MEMORY_XP)) == 0);\r
 \r
   ASSERT (Attributes != 0);\r
   ASSERT ((Attributes & ~(EFI_MEMORY_RP | EFI_MEMORY_RO | EFI_MEMORY_XP)) == 0);\r
@@ -391,6 +392,17 @@ ConvertMemoryPageAttributes (
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
     return RETURN_INVALID_PARAMETER;\r
   }\r
 \r
+  MaximumSupportMemAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, mPhysicalAddressBits) - 1);\r
+  if (BaseAddress > MaximumSupportMemAddress) {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+  if (Length > MaximumSupportMemAddress) {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+  if ((Length != 0) && (BaseAddress > MaximumSupportMemAddress - (Length - 1))) {\r
+    return RETURN_UNSUPPORTED;\r
+  }\r
+\r
 //  DEBUG ((DEBUG_ERROR, "ConvertMemoryPageAttributes(%x) - %016lx, %016lx, %02lx\n", IsSet, BaseAddress, Length, Attributes));\r
 \r
   if (IsSplitted != NULL) {\r
 //  DEBUG ((DEBUG_ERROR, "ConvertMemoryPageAttributes(%x) - %016lx, %016lx, %02lx\n", IsSet, BaseAddress, Length, Attributes));\r
 \r
   if (IsSplitted != NULL) {\r
@@ -1037,6 +1049,7 @@ SetUefiMemMapAttributes (
   VOID\r
   )\r
 {\r
   VOID\r
   )\r
 {\r
+  EFI_STATUS            Status;\r
   EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
   UINTN                 MemoryMapEntryCount;\r
   UINTN                 Index;\r
   EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
   UINTN                 MemoryMapEntryCount;\r
   UINTN                 Index;\r
@@ -1052,12 +1065,18 @@ SetUefiMemMapAttributes (
   MemoryMap = mUefiMemoryMap;\r
   for (Index = 0; Index < MemoryMapEntryCount; Index++) {\r
     if (IsUefiPageNotPresent(MemoryMap)) {\r
   MemoryMap = mUefiMemoryMap;\r
   for (Index = 0; Index < MemoryMapEntryCount; Index++) {\r
     if (IsUefiPageNotPresent(MemoryMap)) {\r
-      DEBUG ((DEBUG_INFO, "UefiMemory protection: 0x%lx - 0x%lx\n", MemoryMap->PhysicalStart, MemoryMap->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages)));\r
-      SmmSetMemoryAttributes (\r
+      Status = SmmSetMemoryAttributes (\r
+                 MemoryMap->PhysicalStart,\r
+                 EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages),\r
+                 EFI_MEMORY_RP\r
+                 );\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "UefiMemory protection: 0x%lx - 0x%lx %r\n",\r
         MemoryMap->PhysicalStart,\r
         MemoryMap->PhysicalStart,\r
-        EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages),\r
-        EFI_MEMORY_RP\r
-        );\r
+        MemoryMap->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages),\r
+        Status\r
+        ));\r
     }\r
     MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, mUefiDescriptorSize);\r
   }\r
     }\r
     MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, mUefiDescriptorSize);\r
   }\r