]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: improve SMM comms security with adaptive MemoryTypeInformation
authorLaszlo Ersek <lersek@redhat.com>
Tue, 10 Mar 2020 22:27:39 +0000 (23:27 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Thu, 12 Mar 2020 21:14:46 +0000 (21:14 +0000)
* In the Intel whitepaper:

--v--
A Tour Beyond BIOS -- Secure SMM Communication

https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Security-White-Papers
https://github.com/tianocore-docs/Docs/raw/master/White_Papers/A_Tour_Beyond_BIOS_Secure_SMM_Communication.pdf
--^--

bullet#3 in section "Assumption and Recommendation", and bullet#4 in "Call
for action", recommend enabling the (adaptive) Memory Type Information
feature.

* In the Intel whitepaper:

--v--
A Tour Beyond BIOS -- Memory Map and Practices in UEFI BIOS

https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-white-papers
https://github.com/tianocore-docs/Docs/raw/master/White_Papers/A_Tour_Beyond_BIOS_Memory_Map_And_Practices_in_UEFI_BIOS_V2.pdf
--^--

figure#6 describes the Memory Type Information feature in detail; namely
as a feedback loop between the Platform PEIM, the DXE IPL PEIM, the DXE
Core, and BDS.

Implement the missing PlatformPei functionality in OvmfPkg, for fulfilling
the Secure SMM Communication recommendation.

In the longer term, OVMF should install the WSMT ACPI table, and this
patch contributes to that.

Notes:

- the step in figure#6 where the UEFI variable is copied into the HOB is
  covered by the DXE IPL PEIM, in the DxeLoadCore() function,

- "PcdResetOnMemoryTypeInformationChange" must be reverted to the DEC
  default TRUE value, because both whitepapers indicate that BDS needs to
  reset the system if the Memory Type Information changes.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=386
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20200310222739.26717-6-lersek@redhat.com>
Acked-by: Leif Lindholm <leif@nuviainc.com>
OvmfPkg/OvmfPkgIa32.dsc
OvmfPkg/OvmfPkgIa32X64.dsc
OvmfPkg/OvmfPkgX64.dsc
OvmfPkg/PlatformPei/MemTypeInfo.c [new file with mode: 0644]
OvmfPkg/PlatformPei/Platform.c
OvmfPkg/PlatformPei/Platform.h
OvmfPkg/PlatformPei/PlatformPei.inf

index 4c9ff419c462db4e3a3827931db8fe2fd5875a61..02ca17db8b2a8f2a908bc5d35da2b23d43e5f3e4 100644 (file)
 \r
 [PcdsFixedAtBuild]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1\r
+!if $(SMM_REQUIRE) == FALSE\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE\r
+!endif\r
   gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10\r
 !if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000\r
index 56681e9e45802e07110ee27da726281d849c9edb..d08cf558c6aa63e28783d32a39a5f66af561f41a 100644 (file)
 \r
 [PcdsFixedAtBuild]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1\r
+!if $(SMM_REQUIRE) == FALSE\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE\r
+!endif\r
   gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10\r
 !if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000\r
index 0e74b6f4d26c19ab14090dd5e23b907564d9f8b9..b2dccc40a865de137a8d15b0ecdfec627c75150c 100644 (file)
 \r
 [PcdsFixedAtBuild]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1\r
+!if $(SMM_REQUIRE) == FALSE\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE\r
+!endif\r
   gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10\r
 !if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000\r
diff --git a/OvmfPkg/PlatformPei/MemTypeInfo.c b/OvmfPkg/PlatformPei/MemTypeInfo.c
new file mode 100644 (file)
index 0000000..c709236
--- /dev/null
@@ -0,0 +1,147 @@
+/** @file\r
+  Produce a default memory type information HOB unless we can determine, from\r
+  the existence of the "MemoryTypeInformation" variable, that the DXE IPL PEIM\r
+  will produce the HOB.\r
+\r
+  Copyright (C) 2017-2020, Red Hat, Inc.\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#include <Guid/MemoryTypeInformation.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Ppi/ReadOnlyVariable2.h>\r
+#include <Uefi/UefiMultiPhase.h>\r
+\r
+#include "Platform.h"\r
+\r
+STATIC EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {\r
+  { EfiACPIMemoryNVS,       0x004 },\r
+  { EfiACPIReclaimMemory,   0x008 },\r
+  { EfiReservedMemoryType,  0x004 },\r
+  { EfiRuntimeServicesData, 0x024 },\r
+  { EfiRuntimeServicesCode, 0x030 },\r
+  { EfiBootServicesCode,    0x180 },\r
+  { EfiBootServicesData,    0xF00 },\r
+  { EfiMaxMemoryType,       0x000 }\r
+};\r
+\r
+STATIC\r
+VOID\r
+BuildMemTypeInfoHob (\r
+  VOID\r
+  )\r
+{\r
+  BuildGuidDataHob (\r
+    &gEfiMemoryTypeInformationGuid,\r
+    mDefaultMemoryTypeInformation,\r
+    sizeof mDefaultMemoryTypeInformation\r
+    );\r
+  DEBUG ((DEBUG_INFO, "%a: default memory type information HOB built\n",\r
+    __FUNCTION__));\r
+}\r
+\r
+/**\r
+  Notification function called when EFI_PEI_READ_ONLY_VARIABLE2_PPI becomes\r
+  available.\r
+\r
+  @param[in] PeiServices      Indirect reference to the PEI Services Table.\r
+  @param[in] NotifyDescriptor Address of the notification descriptor data\r
+                              structure.\r
+  @param[in] Ppi              Address of the PPI that was installed.\r
+\r
+  @return  Status of the notification. The status code returned from this\r
+           function is ignored.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+OnReadOnlyVariable2Available (\r
+  IN EFI_PEI_SERVICES           **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,\r
+  IN VOID                       *Ppi\r
+  )\r
+{\r
+  EFI_PEI_READ_ONLY_VARIABLE2_PPI *ReadOnlyVariable2;\r
+  UINTN                           DataSize;\r
+  EFI_STATUS                      Status;\r
+\r
+  DEBUG ((DEBUG_VERBOSE, "%a\n", __FUNCTION__));\r
+\r
+  //\r
+  // Check if the "MemoryTypeInformation" variable exists, in the\r
+  // gEfiMemoryTypeInformationGuid namespace.\r
+  //\r
+  ReadOnlyVariable2 = Ppi;\r
+  DataSize = 0;\r
+  Status = ReadOnlyVariable2->GetVariable (\r
+                                ReadOnlyVariable2,\r
+                                EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
+                                &gEfiMemoryTypeInformationGuid,\r
+                                NULL,\r
+                                &DataSize,\r
+                                NULL\r
+                                );\r
+  switch (Status) {\r
+  case EFI_BUFFER_TOO_SMALL:\r
+    //\r
+    // The variable exists; the DXE IPL PEIM will build the HOB from it.\r
+    //\r
+    break;\r
+  case EFI_NOT_FOUND:\r
+    //\r
+    // The variable does not exist; install the default memory type information\r
+    // HOB.\r
+    //\r
+    BuildMemTypeInfoHob ();\r
+    break;\r
+  default:\r
+    DEBUG ((DEBUG_ERROR, "%a: unexpected: GetVariable(): %r\n", __FUNCTION__,\r
+      Status));\r
+    ASSERT (FALSE);\r
+    CpuDeadLoop ();\r
+    break;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// Notification object for registering the callback, for when\r
+// EFI_PEI_READ_ONLY_VARIABLE2_PPI becomes available.\r
+//\r
+STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mReadOnlyVariable2Notify = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH |\r
+   EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),  // Flags\r
+  &gEfiPeiReadOnlyVariable2PpiGuid,         // Guid\r
+  OnReadOnlyVariable2Available              // Notify\r
+};\r
+\r
+VOID\r
+MemTypeInfoInitialization (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+\r
+  if (!FeaturePcdGet (PcdSmmSmramRequire)) {\r
+    //\r
+    // EFI_PEI_READ_ONLY_VARIABLE2_PPI will never be available; install\r
+    // the default memory type information HOB right away.\r
+    //\r
+    BuildMemTypeInfoHob ();\r
+    return;\r
+  }\r
+\r
+  Status = PeiServicesNotifyPpi (&mReadOnlyVariable2Notify);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "%a: failed to set up R/O Variable 2 callback: %r\n",\r
+      __FUNCTION__, Status));\r
+    ASSERT (FALSE);\r
+    CpuDeadLoop ();\r
+  }\r
+}\r
index 473af102783a291245951c4c87969c2a77c7521e..587ca68fc2104e49dc4a10646292b836fa790318 100644 (file)
@@ -28,7 +28,6 @@
 #include <Library/QemuFwCfgLib.h>\r
 #include <Library/QemuFwCfgS3Lib.h>\r
 #include <Library/ResourcePublicationLib.h>\r
-#include <Guid/MemoryTypeInformation.h>\r
 #include <Ppi/MasterBootMode.h>\r
 #include <IndustryStandard/I440FxPiix4.h>\r
 #include <IndustryStandard/Pci22.h>\r
 #include "Platform.h"\r
 #include "Cmos.h"\r
 \r
-EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {\r
-  { EfiACPIMemoryNVS,       0x004 },\r
-  { EfiACPIReclaimMemory,   0x008 },\r
-  { EfiReservedMemoryType,  0x004 },\r
-  { EfiRuntimeServicesData, 0x024 },\r
-  { EfiRuntimeServicesCode, 0x030 },\r
-  { EfiBootServicesCode,    0x180 },\r
-  { EfiBootServicesData,    0xF00 },\r
-  { EfiMaxMemoryType,       0x000 }\r
-};\r
-\r
-\r
 EFI_PEI_PPI_DESCRIPTOR   mPpiBootMode[] = {\r
   {\r
     EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
@@ -162,15 +149,6 @@ MemMapInitialization (
   PciIoBase = 0xC000;\r
   PciIoSize = 0x4000;\r
 \r
-  //\r
-  // Create Memory Type Information HOB\r
-  //\r
-  BuildGuidDataHob (\r
-    &gEfiMemoryTypeInformationGuid,\r
-    mDefaultMemoryTypeInformation,\r
-    sizeof(mDefaultMemoryTypeInformation)\r
-    );\r
-\r
   //\r
   // Video memory + Legacy BIOS region\r
   //\r
@@ -811,6 +789,7 @@ InitializePlatform (
       ReserveEmuVariableNvStore ();\r
     }\r
     PeiFvInitialization ();\r
+    MemTypeInfoInitialization ();\r
     MemMapInitialization ();\r
     NoexecDxeInitialization ();\r
   }\r
index 43f20f067f226f08ae5802320f0a87c4d4e5670d..0484ec9e6b4cf6adc347934e7769a5a17d943399 100644 (file)
@@ -82,6 +82,11 @@ PeiFvInitialization (
   VOID\r
   );\r
 \r
+VOID\r
+MemTypeInfoInitialization (\r
+  VOID\r
+  );\r
+\r
 VOID\r
 InstallFeatureControlCallback (\r
   VOID\r
index c51a6176aa2e3693b8d6a42cb8852f08187f2505..8531c63995c13ddc929fdd355ff5676eee695144 100644 (file)
@@ -30,6 +30,7 @@
   FeatureControl.c\r
   Fv.c\r
   MemDetect.c\r
+  MemTypeInfo.c\r
   Platform.c\r
   Platform.h\r
   Xen.c\r
 [Ppis]\r
   gEfiPeiMasterBootModePpiGuid\r
   gEfiPeiMpServicesPpiGuid\r
+  gEfiPeiReadOnlyVariable2PpiGuid\r
 \r
 [Depex]\r
   TRUE\r