There's a small window between

- AllocFwCfgDmaAccessBuffer() mapping the new FW_CFG_DMA_ACCESS object for
  common buffer operation (i.e., decrypting it), and

- InternalQemuFwCfgDmaBytes() setting the fields of the object.

In this window, earlier garbage in the object is "leaked" to the
hypervisor. So zero the object before we decrypt it.

(This commit message references AMD SEV directly, because QemuFwCfgDxeLib
is not *generally* enabled for IOMMU operation just yet, unlike our goal
for the virtio infrastructure. Instead, QemuFwCfgDxeLib uses
MemEncryptSevLib explicitly to detect SEV, and then relies on IOMMU
protocol behavior that is specific to SEV. At this point, this is by
design.)

Cc: Brijesh Singh <[email protected]>
Cc: Jordan Justen <[email protected]>
Cc: Tom Lendacky <[email protected]>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <[email protected]>
---
 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c 
b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
index 8b98208591e6..22077851a40c 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
@@ -1,29 +1,30 @@
 /** @file
 
   Stateful and implicitly initialized fw_cfg library implementation.
 
   Copyright (C) 2013, Red Hat, Inc.
   Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
   Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
   distribution.  The full text of the license may be found at
   http://opensource.org/licenses/bsd-license.php
 
   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
   WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/
 
 #include <Uefi.h>
 
 #include <Protocol/IoMmu.h>
 
 #include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
 #include <Library/IoLib.h>
 #include <Library/DebugLib.h>
 #include <Library/QemuFwCfgLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Library/MemEncryptSevLib.h>
 
 #include "QemuFwCfgLibInternal.h"
@@ -155,75 +156,81 @@ VOID
 AllocFwCfgDmaAccessBuffer (
   OUT   VOID     **Access,
   OUT   VOID     **MapInfo
   )
 {
   UINTN                 Size;
   UINTN                 NumPages;
   EFI_STATUS            Status;
   VOID                  *HostAddress;
   EFI_PHYSICAL_ADDRESS  DmaAddress;
   VOID                  *Mapping;
 
   Size = sizeof (FW_CFG_DMA_ACCESS);
   NumPages = EFI_SIZE_TO_PAGES (Size);
 
   //
   // As per UEFI spec, in order to map a host address with
   // BusMasterCommomBuffer64, the buffer must be allocated using the IOMMU
   // AllocateBuffer()
   //
   Status = mIoMmuProtocol->AllocateBuffer (
                              mIoMmuProtocol,
                              AllocateAnyPages,
                              EfiBootServicesData,
                              NumPages,
                              &HostAddress,
                              EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE
                              );
   if (EFI_ERROR (Status)) {
     DEBUG ((DEBUG_ERROR,
       "%a:%a failed to allocate FW_CFG_DMA_ACCESS\n", gEfiCallerBaseName,
       __FUNCTION__));
     ASSERT (FALSE);
     CpuDeadLoop ();
   }
 
+  //
+  // Avoid exposing stale data even temporarily: zero the area before mapping
+  // it.
+  //
+  ZeroMem (HostAddress, Size);
+
   //
   // Map the host buffer with BusMasterCommonBuffer64
   //
   Status = mIoMmuProtocol->Map (
                              mIoMmuProtocol,
                              EdkiiIoMmuOperationBusMasterCommonBuffer64,
                              HostAddress,
                              &Size,
                              &DmaAddress,
                              &Mapping
                              );
   if (EFI_ERROR (Status)) {
     mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, HostAddress);
     DEBUG ((DEBUG_ERROR,
       "%a:%a failed to Map() FW_CFG_DMA_ACCESS\n", gEfiCallerBaseName,
       __FUNCTION__));
     ASSERT (FALSE);
     CpuDeadLoop ();
   }
 
   if (Size < sizeof (FW_CFG_DMA_ACCESS)) {
     mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping);
     mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, HostAddress);
     DEBUG ((DEBUG_ERROR,
       "%a:%a failed to Map() - requested 0x%Lx got 0x%Lx\n", 
gEfiCallerBaseName,
       __FUNCTION__, (UINT64)sizeof (FW_CFG_DMA_ACCESS), (UINT64)Size));
     ASSERT (FALSE);
     CpuDeadLoop ();
   }
 
   *Access = HostAddress;
   *MapInfo = Mapping;
 }
 
 /**
   Function is to used for freeing the Access buffer allocated using
   AllocFwCfgDmaAccessBuffer()
 
 **/
-- 
2.14.1.3.gb7cf6e02401b

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to