]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: decompress FVs on S3 resume if SMM_REQUIRE is set
authorLaszlo Ersek <lersek@redhat.com>
Mon, 30 Nov 2015 18:41:24 +0000 (18:41 +0000)
committerlersek <lersek@Edk2>
Mon, 30 Nov 2015 18:41:24 +0000 (18:41 +0000)
If OVMF was built with -D SMM_REQUIRE, that implies that the runtime OS is
not trusted and we should defend against it tampering with the firmware's
data.

One such datum is the PEI firmware volume (PEIFV). Normally PEIFV is
decompressed on the first boot by SEC, then the OS preserves it across S3
suspend-resume cycles; at S3 resume SEC just reuses the originally
decompressed PEIFV.

However, if we don't trust the OS, then SEC must decompress PEIFV from the
pristine flash every time, lest we execute OS-injected code or work with
OS-injected data.

Due to how FVMAIN_COMPACT is organized, we can't decompress just PEIFV;
the decompression brings DXEFV with itself, plus it uses a temporary
output buffer and a scratch buffer too, which even reach above the end of
the finally installed DXEFV. For this reason we must keep away a
non-malicious OS from DXEFV too, plus the memory up to
PcdOvmfDecomprScratchEnd.

The delay introduced by the LZMA decompression on S3 resume is negligible.

If -D SMM_REQUIRE is not specified, then PcdSmmSmramRequire remains FALSE
(from the DEC file), and then this patch has no effect (not counting some
changed debug messages).

If QEMU doesn't support S3 (or the user disabled it on the QEMU command
line), then this patch has no effect also.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19037 6f19259b-4bc3-4df7-8a09-765794883524

OvmfPkg/PlatformPei/Fv.c
OvmfPkg/PlatformPei/MemDetect.c
OvmfPkg/PlatformPei/PlatformPei.inf
OvmfPkg/Sec/SecMain.c
OvmfPkg/Sec/SecMain.inf

index 3ed775c850832f472df524cf8f0522662ec5dae5..248c58508558a2741848073776a8db3d4a17193e 100644 (file)
@@ -32,6 +32,8 @@ PeiFvInitialization (
   VOID\r
   )\r
 {\r
+  BOOLEAN SecureS3Needed;\r
+\r
   DEBUG ((EFI_D_INFO, "Platform PEI Firmware Volume Initialization\n"));\r
 \r
   //\r
@@ -50,15 +52,38 @@ PeiFvInitialization (
   //\r
   BuildFvHob (PcdGet32 (PcdOvmfDxeMemFvBase), PcdGet32 (PcdOvmfDxeMemFvSize));\r
 \r
+  SecureS3Needed = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire);\r
+\r
   //\r
   // Create a memory allocation HOB for the DXE FV.\r
   //\r
+  // If "secure" S3 is needed, then SEC will decompress both PEI and DXE\r
+  // firmware volumes at S3 resume too, hence we need to keep away the OS from\r
+  // DXEFV as well. Otherwise we only need to keep away DXE itself from the\r
+  // DXEFV area.\r
+  //\r
   BuildMemoryAllocationHob (\r
     PcdGet32 (PcdOvmfDxeMemFvBase),\r
     PcdGet32 (PcdOvmfDxeMemFvSize),\r
-    EfiBootServicesData\r
+    SecureS3Needed ? EfiACPIMemoryNVS : EfiBootServicesData\r
     );\r
 \r
+  //\r
+  // Additionally, said decompression will use temporary memory above the end\r
+  // of DXEFV, so let's keep away the OS from there too.\r
+  //\r
+  if (SecureS3Needed) {\r
+    UINT32 DxeMemFvEnd;\r
+\r
+    DxeMemFvEnd = PcdGet32 (PcdOvmfDxeMemFvBase) +\r
+                  PcdGet32 (PcdOvmfDxeMemFvSize);\r
+    BuildMemoryAllocationHob (\r
+      DxeMemFvEnd,\r
+      PcdGet32 (PcdOvmfDecompressionScratchEnd) - DxeMemFvEnd,\r
+      EfiACPIMemoryNVS\r
+      );\r
+  }\r
+\r
   //\r
   // Let PEI know about the DXE FV so it can find the DXE Core\r
   //\r
index 612bb4a3ef3fd2039f3326ae112089c0dc5e560e..5fe8b282c09f76a2ba337278fd92648f01c708d1 100644 (file)
@@ -222,7 +222,16 @@ PublishPeiMemory (
     //\r
     // Determine the range of memory to use during PEI\r
     //\r
-    MemoryBase = PcdGet32 (PcdOvmfDxeMemFvBase) + PcdGet32 (PcdOvmfDxeMemFvSize);\r
+    // Technically we could lay the permanent PEI RAM over SEC's temporary\r
+    // decompression and scratch buffer even if "secure S3" is needed, since\r
+    // their lifetimes don't overlap. However, PeiFvInitialization() will cover\r
+    // RAM up to PcdOvmfDecompressionScratchEnd with an EfiACPIMemoryNVS memory\r
+    // allocation HOB, and other allocations served from the permanent PEI RAM\r
+    // shouldn't overlap with that HOB.\r
+    //\r
+    MemoryBase = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire) ?\r
+      PcdGet32 (PcdOvmfDecompressionScratchEnd) :\r
+      PcdGet32 (PcdOvmfDxeMemFvBase) + PcdGet32 (PcdOvmfDxeMemFvSize);\r
     MemorySize = LowerMemorySize - MemoryBase;\r
     if (MemorySize > PeiMemoryCap) {\r
       MemoryBase = LowerMemorySize - PeiMemoryCap;\r
index c2c7da94c40dffac1f5caa554b0e7b42c6b19876..4b1e68de43ac7a0c0283d591d2a5cb1d5bf7c049 100644 (file)
@@ -74,6 +74,7 @@
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize\r
   gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize\r
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd\r
   gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize\r
   gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize\r
@@ -87,6 +88,9 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdPropertiesTableEnable\r
   gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress\r
 \r
+[FeaturePcd]\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire\r
+\r
 [Ppis]\r
   gEfiPeiMasterBootModePpiGuid\r
 \r
index 93e3594e29aa6d0c39eefea3165b38c698e2ca65..a12e6768ae26c28447a5c80e314e7c76fffa6b64 100644 (file)
@@ -539,13 +539,25 @@ FindPeiCoreImageBase (
      OUT  EFI_PHYSICAL_ADDRESS             *PeiCoreImageBase\r
   )\r
 {\r
+  BOOLEAN S3Resume;\r
+\r
   *PeiCoreImageBase = 0;\r
 \r
-  if (IsS3Resume ()) {\r
+  S3Resume = IsS3Resume ();\r
+  if (S3Resume && !FeaturePcdGet (PcdSmmSmramRequire)) {\r
+    //\r
+    // A malicious runtime OS may have injected something into our previously\r
+    // decoded PEI FV, but we don't care about that unless SMM/SMRAM is required.\r
+    //\r
     DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume\n"));\r
     GetS3ResumePeiFv (BootFv);\r
   } else {\r
-    DEBUG ((EFI_D_VERBOSE, "SEC: Normal boot\n"));\r
+    //\r
+    // We're either not resuming, or resuming "securely" -- we'll decompress\r
+    // both PEI FV and DXE FV from pristine flash.\r
+    //\r
+    DEBUG ((EFI_D_VERBOSE, "SEC: %a\n",\r
+      S3Resume ? "S3 resume (with PEI decompression)" : "Normal boot"));\r
     FindMainFv (BootFv);\r
 \r
     DecompressMemFvs (BootFv);\r
index 9e8571dddd7f46998af2205121ba46e2c153f8de..711b5953090748a21fb16032b39bbdad97677e67 100644 (file)
@@ -71,3 +71,6 @@
   gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress\r
   gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize\r
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd\r
+\r
+[FeaturePcd]\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire\r