VariableServiceSetVariable() should also check authenticate data to avoid buffer overflow,\r
integer overflow. It should also check attribute to avoid authentication bypass.\r
\r
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
(C) Copyright 2015-2018 Hewlett Packard Enterprise Development LP<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
UINT8 *CurrBuffer;\r
EFI_LBA LbaNumber;\r
UINTN Size;\r
- EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
VARIABLE_STORE_HEADER *VolatileBase;\r
EFI_PHYSICAL_ADDRESS FvVolHdr;\r
EFI_PHYSICAL_ADDRESS DataPtr;\r
EFI_STATUS Status;\r
\r
- FwVolHeader = NULL;\r
+ FvVolHdr = 0;\r
DataPtr = DataPtrIndex;\r
\r
//\r
Status = Fvb->GetPhysicalAddress(Fvb, &FvVolHdr);\r
ASSERT_EFI_ERROR (Status);\r
\r
- FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr);\r
//\r
// Data Pointer should point to the actual Address where data is to be\r
// written.\r
DataPtr += mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;\r
}\r
\r
- if ((DataPtr + DataSize) > ((EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) FwVolHeader + FwVolHeader->FvLength))) {\r
+ if ((DataPtr + DataSize) > (FvVolHdr + mNvFvHeaderCache->FvLength)) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
} else {\r
//\r
// If we are here we are dealing with Non-Volatile Variables.\r
//\r
- LinearOffset = (UINTN) FwVolHeader;\r
+ LinearOffset = (UINTN) FvVolHdr;\r
CurrWritePtr = (UINTN) DataPtr;\r
CurrWriteSize = DataSize;\r
CurrBuffer = Buffer;\r
)\r
{\r
//\r
- // The end of variable store.\r
+ // The start of variable store.\r
//\r
return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);\r
}\r
if (Variable->CurrPtr != NULL) {\r
if (VariableCompareTimeStampInternal (&(((AUTHENTICATED_VARIABLE_HEADER *) CacheVariable->CurrPtr)->TimeStamp), TimeStamp)) {\r
CopyMem (&AuthVariable->TimeStamp, TimeStamp, sizeof (EFI_TIME));\r
+ } else {\r
+ CopyMem (&AuthVariable->TimeStamp, &(((AUTHENTICATED_VARIABLE_HEADER *) CacheVariable->CurrPtr)->TimeStamp), sizeof (EFI_TIME));\r
}\r
}\r
}\r
}\r
}\r
\r
- State = Variable->CurrPtr->State;\r
+ State = CacheVariable->CurrPtr->State;\r
State &= VAR_DELETED;\r
\r
Status = UpdateVariableStore (\r
((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->AuthInfo.Hdr.dwLength < OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) {\r
return EFI_SECURITY_VIOLATION;\r
}\r
+ //\r
+ // The VariableSpeculationBarrier() call here is to ensure the above sanity\r
+ // check for the EFI_VARIABLE_AUTHENTICATION_2 descriptor has been completed\r
+ // before the execution of subsequent codes.\r
+ //\r
+ VariableSpeculationBarrier ();\r
PayloadSize = DataSize - AUTHINFO2_SIZE (Data);\r
} else {\r
PayloadSize = DataSize;\r
//\r
if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {\r
if (StrSize (VariableName) + PayloadSize > mVariableModuleGlobal->MaxAuthVariableSize - GetVariableHeaderSize ()) {\r
+ DEBUG ((DEBUG_ERROR,\r
+ "%a: Failed to set variable '%s' with Guid %g\n",\r
+ __FUNCTION__, VariableName, VendorGuid));\r
+ DEBUG ((DEBUG_ERROR,\r
+ "NameSize(0x%x) + PayloadSize(0x%x) > "\r
+ "MaxAuthVariableSize(0x%x) - HeaderSize(0x%x)\n",\r
+ StrSize (VariableName), PayloadSize,\r
+ mVariableModuleGlobal->MaxAuthVariableSize,\r
+ GetVariableHeaderSize ()\r
+ ));\r
return EFI_INVALID_PARAMETER;\r
}\r
} else if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {\r
if (StrSize (VariableName) + PayloadSize > mVariableModuleGlobal->MaxVariableSize - GetVariableHeaderSize ()) {\r
+ DEBUG ((DEBUG_ERROR,\r
+ "%a: Failed to set variable '%s' with Guid %g\n",\r
+ __FUNCTION__, VariableName, VendorGuid));\r
+ DEBUG ((DEBUG_ERROR,\r
+ "NameSize(0x%x) + PayloadSize(0x%x) > "\r
+ "MaxVariableSize(0x%x) - HeaderSize(0x%x)\n",\r
+ StrSize (VariableName), PayloadSize,\r
+ mVariableModuleGlobal->MaxVariableSize,\r
+ GetVariableHeaderSize ()\r
+ ));\r
return EFI_INVALID_PARAMETER;\r
}\r
} else {\r
if (StrSize (VariableName) + PayloadSize > mVariableModuleGlobal->MaxVolatileVariableSize - GetVariableHeaderSize ()) {\r
+ DEBUG ((DEBUG_ERROR,\r
+ "%a: Failed to set variable '%s' with Guid %g\n",\r
+ __FUNCTION__, VariableName, VendorGuid));\r
+ DEBUG ((DEBUG_ERROR,\r
+ "NameSize(0x%x) + PayloadSize(0x%x) > "\r
+ "MaxVolatileVariableSize(0x%x) - HeaderSize(0x%x)\n",\r
+ StrSize (VariableName), PayloadSize,\r
+ mVariableModuleGlobal->MaxVolatileVariableSize,\r
+ GetVariableHeaderSize ()\r
+ ));\r
return EFI_INVALID_PARAMETER;\r
}\r
}\r
}\r
\r
/**\r
- Init non-volatile variable store.\r
+ Init real non-volatile variable store.\r
\r
- @param[out] NvFvHeader Output pointer to non-volatile FV header address.\r
+ @param[out] VariableStoreBase Output pointer to real non-volatile variable store base.\r
\r
@retval EFI_SUCCESS Function successfully executed.\r
@retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.\r
\r
**/\r
EFI_STATUS\r
-InitNonVolatileVariableStore (\r
- OUT EFI_FIRMWARE_VOLUME_HEADER **NvFvHeader\r
+InitRealNonVolatileVariableStore (\r
+ OUT EFI_PHYSICAL_ADDRESS *VariableStoreBase\r
)\r
{\r
EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
- VARIABLE_HEADER *Variable;\r
- VARIABLE_HEADER *NextVariable;\r
- EFI_PHYSICAL_ADDRESS VariableStoreBase;\r
- UINT64 VariableStoreLength;\r
- UINTN VariableSize;\r
+ VARIABLE_STORE_HEADER *VariableStore;\r
+ UINT32 VariableStoreLength;\r
EFI_HOB_GUID_TYPE *GuidHob;\r
EFI_PHYSICAL_ADDRESS NvStorageBase;\r
UINT8 *NvStorageData;\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
- if (NvStorageBase == 0) {\r
- NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
- }\r
+ NvStorageBase = NV_STORAGE_VARIABLE_BASE;\r
+ ASSERT (NvStorageBase != 0);\r
+\r
//\r
// Copy NV storage data to the memory buffer.\r
//\r
return EFI_VOLUME_CORRUPTED;\r
}\r
\r
- VariableStoreBase = (UINTN) FvHeader + FvHeader->HeaderLength;\r
+ VariableStore = (VARIABLE_STORE_HEADER *) ((UINTN) FvHeader + FvHeader->HeaderLength);\r
VariableStoreLength = NvStorageSize - FvHeader->HeaderLength;\r
+ ASSERT (sizeof (VARIABLE_STORE_HEADER) <= VariableStoreLength);\r
+ ASSERT (VariableStore->Size == VariableStoreLength);\r
\r
- mNvFvHeaderCache = FvHeader;\r
- mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
- mNvVariableCache = (VARIABLE_STORE_HEADER *) (UINTN) VariableStoreBase;\r
- if (GetVariableStoreStatus (mNvVariableCache) != EfiValid) {\r
+ //\r
+ // Check if the Variable Store header is not corrupted\r
+ //\r
+ if (GetVariableStoreStatus (VariableStore) != EfiValid) {\r
FreePool (NvStorageData);\r
- mNvFvHeaderCache = NULL;\r
- mNvVariableCache = NULL;\r
DEBUG((EFI_D_ERROR, "Variable Store header is corrupted\n"));\r
return EFI_VOLUME_CORRUPTED;\r
}\r
- ASSERT(mNvVariableCache->Size == VariableStoreLength);\r
\r
- ASSERT (sizeof (VARIABLE_STORE_HEADER) <= VariableStoreLength);\r
+ mNvFvHeaderCache = FvHeader;\r
\r
- mVariableModuleGlobal->VariableGlobal.AuthFormat = (BOOLEAN)(CompareGuid (&mNvVariableCache->Signature, &gEfiAuthenticatedVariableGuid));\r
+ *VariableStoreBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore;\r
\r
HwErrStorageSize = PcdGet32 (PcdHwErrStorageSize);\r
MaxUserNvVariableSpaceSize = PcdGet32 (PcdMaxUserNvVariableSpaceSize);\r
//\r
ASSERT (GetNonVolatileMaxVariableSize () < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)));\r
\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Init non-volatile variable store.\r
+\r
+ @retval EFI_SUCCESS Function successfully executed.\r
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.\r
+ @retval EFI_VOLUME_CORRUPTED Variable Store or Firmware Volume for Variable Store is corrupted.\r
+\r
+**/\r
+EFI_STATUS\r
+InitNonVolatileVariableStore (\r
+ VOID\r
+ )\r
+{\r
+ VARIABLE_HEADER *Variable;\r
+ VARIABLE_HEADER *NextVariable;\r
+ EFI_PHYSICAL_ADDRESS VariableStoreBase;\r
+ UINTN VariableSize;\r
+ EFI_STATUS Status;\r
+\r
+ Status = InitRealNonVolatileVariableStore (&VariableStoreBase);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
+ mNvVariableCache = (VARIABLE_STORE_HEADER *) (UINTN) VariableStoreBase;\r
+ mVariableModuleGlobal->VariableGlobal.AuthFormat = (BOOLEAN)(CompareGuid (&mNvVariableCache->Signature, &gEfiAuthenticatedVariableGuid));\r
+\r
mVariableModuleGlobal->MaxVariableSize = PcdGet32 (PcdMaxVariableSize);\r
mVariableModuleGlobal->MaxAuthVariableSize = ((PcdGet32 (PcdMaxAuthVariableSize) != 0) ? PcdGet32 (PcdMaxAuthVariableSize) : mVariableModuleGlobal->MaxVariableSize);\r
\r
//\r
// Parse non-volatile variable data and get last variable offset.\r
//\r
- Variable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);\r
- while (IsValidVariableHeader (Variable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase))) {\r
+ Variable = GetStartPointer (mNvVariableCache);\r
+ while (IsValidVariableHeader (Variable, GetEndPointer (mNvVariableCache))) {\r
NextVariable = GetNextVariablePtr (Variable);\r
VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
if ((Variable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
\r
Variable = NextVariable;\r
}\r
- mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) Variable - (UINTN) VariableStoreBase;\r
+ mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) Variable - (UINTN) mNvVariableCache;\r
\r
- *NvFvHeader = FvHeader;\r
return EFI_SUCCESS;\r
}\r
\r
}\r
\r
/**\r
- Initializes variable write service after FTW was ready.\r
+ Initializes variable write service.\r
\r
@retval EFI_SUCCESS Function successfully executed.\r
@retval Others Fail to initialize the variable service.\r
EFI_STATUS Status;\r
UINTN Index;\r
UINT8 Data;\r
- EFI_PHYSICAL_ADDRESS VariableStoreBase;\r
- EFI_PHYSICAL_ADDRESS NvStorageBase;\r
VARIABLE_ENTRY_PROPERTY *VariableEntry;\r
\r
AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
\r
- NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
- if (NvStorageBase == 0) {\r
- NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
- }\r
- VariableStoreBase = NvStorageBase + (mNvFvHeaderCache->HeaderLength);\r
-\r
- //\r
- // Let NonVolatileVariableBase point to flash variable store base directly after FTW ready.\r
- //\r
- mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
-\r
//\r
// Check if the free area is really free.\r
//\r
/**\r
Get HOB variable store.\r
\r
- @param[out] VariableGuid NV variable store signature.\r
+ @param[in] VariableGuid NV variable store signature.\r
\r
@retval EFI_SUCCESS Function successfully executed.\r
@retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.\r
EFI_HOB_GUID_TYPE *GuidHob;\r
BOOLEAN NeedConvertNormalToAuth;\r
\r
+ //\r
+ // Make sure there is no more than one Variable HOB.\r
+ //\r
+ DEBUG_CODE (\r
+ GuidHob = GetFirstGuidHob (&gEfiAuthenticatedVariableGuid);\r
+ if (GuidHob != NULL) {\r
+ if ((GetNextGuidHob (&gEfiAuthenticatedVariableGuid, GET_NEXT_HOB (GuidHob)) != NULL)) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR: Found two Auth Variable HOBs\n"));\r
+ ASSERT (FALSE);\r
+ } else if (GetFirstGuidHob (&gEfiVariableGuid) != NULL) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR: Found one Auth + one Normal Variable HOBs\n"));\r
+ ASSERT (FALSE);\r
+ }\r
+ } else {\r
+ GuidHob = GetFirstGuidHob (&gEfiVariableGuid);\r
+ if (GuidHob != NULL) {\r
+ if ((GetNextGuidHob (&gEfiVariableGuid, GET_NEXT_HOB (GuidHob)) != NULL)) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR: Found two Normal Variable HOBs\n"));\r
+ ASSERT (FALSE);\r
+ }\r
+ }\r
+ }\r
+ );\r
+\r
//\r
// Combinations supported:\r
// 1. Normal NV variable store +\r
VARIABLE_STORE_HEADER *VolatileVariableStore;\r
UINTN ScratchSize;\r
EFI_GUID *VariableGuid;\r
- EFI_FIRMWARE_VOLUME_HEADER *NvFvHeader;\r
\r
//\r
// Allocate runtime memory for variable driver global structure.\r
//\r
// Init non-volatile variable store.\r
//\r
- NvFvHeader = NULL;\r
- Status = InitNonVolatileVariableStore (&NvFvHeader);\r
+ Status = InitNonVolatileVariableStore ();\r
if (EFI_ERROR (Status)) {\r
FreePool (mVariableModuleGlobal);\r
return Status;\r
//\r
Status = GetHobVariableStore (VariableGuid);\r
if (EFI_ERROR (Status)) {\r
- FreePool (NvFvHeader);\r
+ if (mNvFvHeaderCache != NULL) {\r
+ FreePool (mNvFvHeaderCache);\r
+ }\r
FreePool (mVariableModuleGlobal);\r
return Status;\r
}\r
if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {\r
FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase);\r
}\r
- FreePool (NvFvHeader);\r
+ if (mNvFvHeaderCache != NULL) {\r
+ FreePool (mNvFvHeaderCache);\r
+ }\r
FreePool (mVariableModuleGlobal);\r
return EFI_OUT_OF_RESOURCES;\r
}\r