public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 1/1] MdeModulePkg/VariableRuntimeDxe: avoid double VA conversion of FVB protocol
@ 2021-03-12 23:05 Ard Biesheuvel
  2021-03-13 11:32 ` Jon Nettleton
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2021-03-12 23:05 UTC (permalink / raw)
  To: devel; +Cc: lersek, liming.gao, jon, leif, Ard Biesheuvel

For historical reasons, the VariableRuntimeDxe performs virtual address
conversion on the FVB protocol member pointers of the protocol instance
that backs the EFI variable store. However, the driver that produces the
actual instance should be doing this, as it is the owner, and provides
the actual implementation of those methods.

Unfortunately, we cannot simply change this: existing drivers may rely
on this behavior, and so the variable driver should take care to only
convert the pointers when necessary, but leave them alone when the owner
is taking care of this.

The virtual address switch event can be delivered in arbitrary order, and
so we should take care of this in a way that does not rely on whether this
driver converts its pointers either before or after the owner of the FVB
protocol receives the event.

So let's not convert the pointers at all when the event is delivered, but
record the converted addresses in a shadow FVB protocol. This way, we can
check when the variable driver is invoked at runtime whether the switch
has occurred or not, and perform the switch if it hasn't.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
Build tested only.

 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c | 50 +++++++++++++++++---
 1 file changed, 43 insertions(+), 7 deletions(-)

diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
index 0fca0bb2a9b5..3d83ac4452ee 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
@@ -37,6 +37,8 @@ EDKII_VAR_CHECK_PROTOCOL            mVarCheck                  = { VarCheckRegis
                                                                     VarCheckVariablePropertySet,
                                                                     VarCheckVariablePropertyGet };
 
+STATIC EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL mFvbProtocolShadow;
+
 /**
   Some Secure Boot Policy Variable may update following other variable changes(SecureBoot follows PK change, etc).
   Record their initial State when variable write service is ready.
@@ -105,8 +107,26 @@ AcquireLockOnlyAtBootTime (
   IN EFI_LOCK                             *Lock
   )
 {
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *FvbInstance;
+
   if (!AtRuntime ()) {
     EfiAcquireLock (Lock);
+  } else {
+    //
+    // Check whether we need to swap in the converted pointer values for the
+    // FVB protocol methods
+    //
+    FvbInstance = mVariableModuleGlobal->FvbInstance;
+    if (FvbInstance != NULL &&
+        FvbInstance->GetBlockSize != mFvbProtocolShadow.GetBlockSize) {
+      FvbInstance->GetBlockSize       = mFvbProtocolShadow.GetBlockSize;
+      FvbInstance->GetPhysicalAddress = mFvbProtocolShadow.GetPhysicalAddress;
+      FvbInstance->GetAttributes      = mFvbProtocolShadow.GetAttributes;
+      FvbInstance->SetAttributes      = mFvbProtocolShadow.SetAttributes;
+      FvbInstance->Read               = mFvbProtocolShadow.Read;
+      FvbInstance->Write              = mFvbProtocolShadow.Write;
+      FvbInstance->EraseBlocks        = mFvbProtocolShadow.EraseBlocks;
+    }
   }
 }
 
@@ -247,13 +267,22 @@ VariableClassAddressChangeEvent (
   UINTN          Index;
 
   if (mVariableModuleGlobal->FvbInstance != NULL) {
-    EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetBlockSize);
-    EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetPhysicalAddress);
-    EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetAttributes);
-    EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->SetAttributes);
-    EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Read);
-    EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Write);
-    EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->EraseBlocks);
+    //
+    // This module did not produce the FVB protocol instance that provides the
+    // variable store, so it should not be the one performing the pointer
+    // conversion on its members. However, some FVB protocol implementations
+    // may rely on this behavior, which was present in older versions of this
+    // driver, so we need to perform the conversion if the protocol producer
+    // fails to do so. So let's record the converted values now, and swap them
+    // in later if they haven't changed values.
+    //
+    EfiConvertPointer (0x0, (VOID **)&mFvbProtocolShadow.GetBlockSize);
+    EfiConvertPointer (0x0, (VOID **)&mFvbProtocolShadow.GetPhysicalAddress);
+    EfiConvertPointer (0x0, (VOID **)&mFvbProtocolShadow.GetAttributes);
+    EfiConvertPointer (0x0, (VOID **)&mFvbProtocolShadow.SetAttributes);
+    EfiConvertPointer (0x0, (VOID **)&mFvbProtocolShadow.Read);
+    EfiConvertPointer (0x0, (VOID **)&mFvbProtocolShadow.Write);
+    EfiConvertPointer (0x0, (VOID **)&mFvbProtocolShadow.EraseBlocks);
     EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance);
   }
   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);
@@ -454,6 +483,13 @@ FtwNotificationEvent (
   }
   mVariableModuleGlobal->FvbInstance = FvbProtocol;
 
+  //
+  // Store the boot time values of the function pointers so we can compare
+  // them later. This is needed to avoid double conversion during the call
+  // to SetVirtualAddressMap.
+  //
+  CopyMem (&mFvbProtocolShadow, FvbProtocol, sizeof mFvbProtocolShadow);
+
   //
   // Mark the variable storage region of the FLASH as RUNTIME.
   //
-- 
2.30.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2022-03-16  1:01 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-03-12 23:05 [PATCH 1/1] MdeModulePkg/VariableRuntimeDxe: avoid double VA conversion of FVB protocol Ard Biesheuvel
2021-03-13 11:32 ` Jon Nettleton
2021-03-15  2:40 ` 回复: [edk2-devel] " gaoliming
2021-03-15  5:56   ` Wu, Hao A
2021-03-16 15:58 ` Laszlo Ersek
2021-03-16 19:19   ` [edk2-devel] " Samer El-Haj-Mahmoud
2021-03-17  3:20   ` 回复: " gaoliming
2022-03-16  1:01     ` Marcin Wojtas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox