On 09/07/15 01:55, Jordan Justen wrote: > On 2015-07-24 16:00:12, Laszlo Ersek wrote: >> 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. > > I definitely don't think this is the best we could do here. We > dicussed this a bit in irc back on April 23rd, and I was grasping for > some alternative implementations. :) Unfortuntately, none of the ideas > I had were nearly as easy as this, and thus this seems like a > reasonable next step.
Duly noted. Thank you for your flexibility. :) > >> 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 <ler...@redhat.com> >> --- >> OvmfPkg/PlatformPei/PlatformPei.inf | 4 +++ >> OvmfPkg/Sec/SecMain.inf | 3 +++ >> OvmfPkg/PlatformPei/Fv.c | 27 +++++++++++++++++++- >> OvmfPkg/PlatformPei/MemDetect.c | 11 +++++++- >> OvmfPkg/Sec/SecMain.c | 18 ++++++++++--- >> 5 files changed, 58 insertions(+), 5 deletions(-) >> >> diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf >> b/OvmfPkg/PlatformPei/PlatformPei.inf >> index cb7d7dd..b9b0b20 100644 >> --- a/OvmfPkg/PlatformPei/PlatformPei.inf >> +++ b/OvmfPkg/PlatformPei/PlatformPei.inf >> @@ -75,6 +75,7 @@ [Pcd] >> gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize >> gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize >> gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId >> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecomprScratchEnd >> gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdS3AcpiReservedMemorySize >> gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress >> gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize >> @@ -87,6 +88,9 @@ [Pcd] >> gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable >> gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress >> >> +[FeaturePcd] >> + gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire >> + >> [Ppis] >> gEfiPeiMasterBootModePpiGuid >> >> diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf >> index 0bd9f83..c66c7fc 100644 >> --- a/OvmfPkg/Sec/SecMain.inf >> +++ b/OvmfPkg/Sec/SecMain.inf >> @@ -68,3 +68,6 @@ [Pcd] >> gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase >> gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize >> gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecomprScratchEnd >> + >> +[FeaturePcd] >> + gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire >> diff --git a/OvmfPkg/PlatformPei/Fv.c b/OvmfPkg/PlatformPei/Fv.c >> index 3ed775c..7a89acd 100644 >> --- a/OvmfPkg/PlatformPei/Fv.c >> +++ b/OvmfPkg/PlatformPei/Fv.c >> @@ -32,6 +32,8 @@ PeiFvInitialization ( >> VOID >> ) >> { >> + BOOLEAN SecureS3Needed; >> + >> DEBUG ((EFI_D_INFO, "Platform PEI Firmware Volume Initialization\n")); >> >> // >> @@ -50,16 +52,39 @@ PeiFvInitialization ( >> // >> BuildFvHob (PcdGet32 (PcdOvmfDxeMemFvBase), PcdGet32 >> (PcdOvmfDxeMemFvSize)); >> >> + SecureS3Needed = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire); >> + >> // >> // Create a memory allocation HOB for the DXE FV. >> // >> + // If "secure" S3 is needed, then SEC will decompress both PEI and DXE >> + // firmware volumes at S3 resume too, hence we need to keep away the OS >> from >> + // DXEFV as well. Otherwise we only need to keep away DXE itself from the >> + // DXEFV area. >> + // >> BuildMemoryAllocationHob ( >> PcdGet32 (PcdOvmfDxeMemFvBase), >> PcdGet32 (PcdOvmfDxeMemFvSize), >> - EfiBootServicesData >> + SecureS3Needed ? EfiACPIMemoryNVS : EfiBootServicesData >> ); >> >> // >> + // Additionally, said decompression will use temporary memory above the >> end >> + // of DXEFV, so let's keep away the OS from there too. >> + // >> + if (SecureS3Needed) { >> + UINT32 DxeMemFvEnd; >> + >> + DxeMemFvEnd = PcdGet32 (PcdOvmfDxeMemFvBase) + >> + PcdGet32 (PcdOvmfDxeMemFvSize); >> + BuildMemoryAllocationHob ( >> + DxeMemFvEnd, >> + PcdGet32 (PcdOvmfDecomprScratchEnd) - DxeMemFvEnd, >> + EfiACPIMemoryNVS >> + ); >> + } >> + >> + // >> // Let PEI know about the DXE FV so it can find the DXE Core >> // >> PeiServicesInstallFvInfoPpi ( >> diff --git a/OvmfPkg/PlatformPei/MemDetect.c >> b/OvmfPkg/PlatformPei/MemDetect.c >> index 612bb4a..649b484 100644 >> --- a/OvmfPkg/PlatformPei/MemDetect.c >> +++ b/OvmfPkg/PlatformPei/MemDetect.c >> @@ -222,7 +222,16 @@ PublishPeiMemory ( >> // >> // Determine the range of memory to use during PEI >> // >> - MemoryBase = PcdGet32 (PcdOvmfDxeMemFvBase) + PcdGet32 >> (PcdOvmfDxeMemFvSize); >> + // Technically we could lay the permanent PEI RAM over SEC's temporary >> + // decompression and scratch buffer even if "secure S3" is needed, since >> + // their lifetimes don't overlap. However, PeiFvInitialization() will >> cover >> + // RAM up to PcdOvmfDecomprScratchEnd with an EfiACPIMemoryNVS memory >> + // allocation HOB, and other allocations served from the permanent PEI >> RAM >> + // shouldn't overlap with that HOB. >> + // >> + MemoryBase = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire) ? >> + PcdGet32 (PcdOvmfDecomprScratchEnd) : >> + PcdGet32 (PcdOvmfDxeMemFvBase) + PcdGet32 (PcdOvmfDxeMemFvSize); >> MemorySize = LowerMemorySize - MemoryBase; >> if (MemorySize > PeiMemoryCap) { >> MemoryBase = LowerMemorySize - PeiMemoryCap; >> diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c >> index 348d2b3..99dd6db 100644 >> --- a/OvmfPkg/Sec/SecMain.c >> +++ b/OvmfPkg/Sec/SecMain.c >> @@ -538,13 +538,25 @@ FindPeiCoreImageBase ( >> OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase >> ) >> { >> + BOOLEAN S3Resume; >> + >> *PeiCoreImageBase = 0; >> >> - if (IsS3Resume ()) { >> - DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume\n")); >> + S3Resume = IsS3Resume (); >> + if (S3Resume && !FeaturePcdGet (PcdSmmSmramRequire)) { >> + // >> + // A malicious runtime OS may have injected something into our >> previously >> + // decoded PEI FV, but we don't care about that unless SMM/SMRAM is >> required. >> + // >> + DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume (insecure)\n")); > > How about instead: > DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume\n")); > and > DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume (with PEI decompression)\n")); I agree. The "insecure" word looks needlessly alarming, and the "hopefully secure" statement is a bit fishy too. Let's stick with the facts. :) I'll update these. > Reviewed-by: Jordan Justen <jordan.l.jus...@intel.com> Thank you! Laszlo > >> GetS3ResumePeiFv (BootFv); >> } else { >> - DEBUG ((EFI_D_VERBOSE, "SEC: Normal boot\n")); >> + // >> + // We're either not resuming, or resuming "securely" -- we'll decompress >> + // both PEI FV and DXE FV from pristine flash. >> + // >> + DEBUG ((EFI_D_VERBOSE, "SEC: %a\n", >> + S3Resume ? "S3 resume (hopefully secure)" : "Normal boot")); >> FindMainFv (BootFv); >> >> DecompressMemFvs (BootFv); >> -- >> 1.8.3.1 >> >> >> _______________________________________________ >> edk2-devel mailing list >> edk2-devel@lists.01.org >> https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel