OvmfPkg/SerializeVariablesLib: ignore secure variable restore errors

OvmfPkg's file-based NvVar storage is read back as follows at boot (all
paths under OvmfPkg/Library/):

PlatformBdsPolicyBehavior() [PlatformBdsLib/BdsPlatform.c]
  PlatformBdsRestoreNvVarsFromHardDisk()
    VisitAllInstancesOfProtocol
      for each simple file system:
        VisitingFileSystemInstance()
          ConnectNvVarsToFileSystem() [NvVarsFileLib/NvVarsFileLib.c]
            LoadNvVarsFromFs() [NvVarsFileLib/FsAccess.c]
              ReadNvVarsFile()
+-------------> SerializeVariablesSetSerializedVariables() [SerializeVariablesLib/SerializeVariablesLib.c]
|                 SerializeVariablesIterateInstanceVariables()
|   +-------------> IterateVariablesInBuffer()
|   |                 for each loaded / deserialized variable:
| +-|-----------------> IterateVariablesCallbackSetSystemVariable()
| | |                     gRT->SetVariable()
| | |
| | IterateVariablesInBuffer() stops processing variables as soon as the
| | first error is encountered from the callback function.
| |
| | In this case the callback function is
| IterateVariablesCallbackSetSystemVariable(), selected by
SerializeVariablesSetSerializedVariables().

The result is that no NvVar is restored from the file after the first
gRT->SetVariable() failure.

On my system such a failure
- never happens in an OVMF build with secure boot disabled,
- happens *immediately* with SECURE_BOOT_ENABLE, because the first
  variable to restore is "AuthVarKeyDatabase".

"AuthVarKeyDatabase" has the EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
attribute set. Since the loop tries to restore it before any keys (PK, KEK
etc) are enrolled, gRT->SetVariable() rejects it with
EFI_SECURITY_VIOLATION. Consequently the NvVar restore loop terminates
immediately, and we never reach non-authenticated variables such as
Boot#### and BootOrder.

Until work on KVM-compatible flash emulation converges between qemu and
OvmfPkg, improve the SECURE_BOOT_ENABLE boot experience by masking
EFI_SECURITY_VIOLATION in the callback:
- authenticated variables continue to be rejected same as before, but
- at least we allow the loop to progress and restore non-authenticated
  variables, for example boot options.

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://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14390 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
jljusten 2013-05-28 17:21:37 +00:00
parent 61f1b7c51e
commit e678f9db89
1 changed files with 20 additions and 7 deletions

View File

@ -284,13 +284,26 @@ IterateVariablesCallbackSetSystemVariable (
IN VOID *Data
)
{
return gRT->SetVariable (
VariableName,
VendorGuid,
Attributes,
DataSize,
Data
);
EFI_STATUS Status;
STATIC CONST UINT32 AuthMask =
EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
Status = gRT->SetVariable (
VariableName,
VendorGuid,
Attributes,
DataSize,
Data
);
if (Status == EFI_SECURITY_VIOLATION && (Attributes & AuthMask) != 0) {
DEBUG ((DEBUG_WARN, "%a: setting authenticated variable \"%s\" "
"failed with EFI_SECURITY_VIOLATION, ignoring\n", __FUNCTION__,
VariableName));
Status = EFI_SUCCESS;
}
return Status;
}