Fix memory overflow & VariableSize check issue for SetVariable append write.

Signed-off-by: Chao Zhang <chao.b.zhang@intel.com>
Reviewed-by  : Fu Siyuan  <siyuan.fu@intel.com>
Reviewed-by  : Dong Guo   <guo.dong@intel.com>

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14323 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
czhang46 2013-05-02 01:42:39 +00:00
parent 41f3989842
commit 732d199d8f
3 changed files with 73 additions and 30 deletions

View File

@ -192,7 +192,7 @@ AutenticatedVariableServiceInitialize (
//
// Reserved runtime buffer for "Append" operation in virtual mode.
//
mStorageArea = AllocateRuntimePool (PcdGet32 (PcdMaxVariableSize));
mStorageArea = AllocateRuntimePool (MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)));
if (mStorageArea == NULL) {
return EFI_OUT_OF_RESOURCES;
}
@ -1318,18 +1318,22 @@ ProcessVariable (
@param[in, out] Data Pointer to original EFI_SIGNATURE_LIST.
@param[in] DataSize Size of Data buffer.
@param[in] FreeBufSize Size of free data buffer
@param[in] NewData Pointer to new EFI_SIGNATURE_LIST to be appended.
@param[in] NewDataSize Size of NewData buffer.
@param[out] MergedBufSize Size of the merged buffer
@return Size of the merged buffer.
@return EFI_BUFFER_TOO_SMALL if input Data buffer overflowed
**/
UINTN
EFI_STATUS
AppendSignatureList (
IN OUT VOID *Data,
IN UINTN DataSize,
IN UINTN FreeBufSize,
IN VOID *NewData,
IN UINTN NewDataSize
IN UINTN NewDataSize,
OUT UINTN *MergedBufSize
)
{
EFI_SIGNATURE_LIST *CertList;
@ -1388,15 +1392,25 @@ AppendSignatureList (
// New EFI_SIGNATURE_DATA, append it.
//
if (CopiedCount == 0) {
if (FreeBufSize < sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize) {
return EFI_BUFFER_TOO_SMALL;
}
//
// Copy EFI_SIGNATURE_LIST header for only once.
//
CopyMem (Tail, NewCertList, sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize);
Tail = Tail + sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize;
FreeBufSize -= sizeof (EFI_SIGNATURE_LIST) + NewCertList->SignatureHeaderSize;
}
if (FreeBufSize < NewCertList->SignatureSize) {
return EFI_BUFFER_TOO_SMALL;
}
CopyMem (Tail, NewCert, NewCertList->SignatureSize);
Tail += NewCertList->SignatureSize;
FreeBufSize -= NewCertList->SignatureSize;
CopiedCount++;
}
@ -1416,7 +1430,8 @@ AppendSignatureList (
NewCertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) NewCertList + NewCertList->SignatureListSize);
}
return (Tail - (UINT8 *) Data);
*MergedBufSize = (Tail - (UINT8 *) Data);
return EFI_SUCCESS;
}
/**

View File

@ -2,7 +2,7 @@
The internal header file includes the common header files, defines
internal structure and functions used by AuthService module.
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2013, Intel Corporation. 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
@ -251,18 +251,22 @@ ProcessVarWithKek (
@param[in, out] Data Pointer to original EFI_SIGNATURE_LIST.
@param[in] DataSize Size of Data buffer.
@param[in] FreeBufSize Size of free data buffer
@param[in] NewData Pointer to new EFI_SIGNATURE_LIST to be appended.
@param[in] NewDataSize Size of NewData buffer.
@param[out] MergedBufSize Size of the merged buffer
@return Size of the merged buffer.
@return EFI_BUFFER_TOO_SMALL if input Data buffer overflowed
**/
UINTN
EFI_STATUS
AppendSignatureList (
IN OUT VOID *Data,
IN UINTN DataSize,
IN UINTN FreeBufSize,
IN VOID *NewData,
IN UINTN NewDataSize
IN UINTN NewDataSize,
OUT UINTN *MergedBufSize
);
/**

View File

@ -1649,7 +1649,7 @@ UpdateVariable (
EFI_STATUS Status;
VARIABLE_HEADER *NextVariable;
UINTN ScratchSize;
UINTN ScratchDataSize;
UINTN MaxDataSize;
UINTN NonVolatileVarableStoreSize;
UINTN VarNameOffset;
UINTN VarDataOffset;
@ -1664,7 +1664,6 @@ UpdateVariable (
UINTN CacheOffset;
UINTN BufSize;
UINTN DataOffset;
UINTN RevBufSize;
if (mVariableModuleGlobal->FvbInstance == NULL) {
//
@ -1713,7 +1712,7 @@ UpdateVariable (
//
NextVariable = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase));
ScratchSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));
ScratchDataSize = ScratchSize - sizeof (VARIABLE_HEADER) - StrSize (VariableName) - GET_PAD_SIZE (StrSize (VariableName));
if (Variable->CurrPtr != NULL) {
//
@ -1827,14 +1826,36 @@ UpdateVariable (
DataOffset = sizeof (VARIABLE_HEADER) + Variable->CurrPtr->NameSize + GET_PAD_SIZE (Variable->CurrPtr->NameSize);
CopyMem (mStorageArea, (UINT8*)((UINTN) Variable->CurrPtr + DataOffset), Variable->CurrPtr->DataSize);
//
// Set Max Common Variable Data Size as default MaxDataSize
//
MaxDataSize = PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER) - StrSize (VariableName) - GET_PAD_SIZE (StrSize (VariableName));
if ((CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&
((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) || (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0))) ||
(CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0))) {
//
// For variables with formatted as EFI_SIGNATURE_LIST, the driver shall not perform an append of
// EFI_SIGNATURE_DATA values that are already part of the existing variable value.
//
BufSize = AppendSignatureList (mStorageArea, Variable->CurrPtr->DataSize, Data, DataSize);
Status = AppendSignatureList (
mStorageArea,
Variable->CurrPtr->DataSize,
MaxDataSize - Variable->CurrPtr->DataSize,
Data,
DataSize,
&BufSize
);
if (Status == EFI_BUFFER_TOO_SMALL) {
//
// Signture List is too long, Failed to Append
//
Status = EFI_INVALID_PARAMETER;
goto Done;
}
if (BufSize == Variable->CurrPtr->DataSize) {
if ((TimeStamp == NULL) || CompareTimeStamp (TimeStamp, &Variable->CurrPtr->TimeStamp)) {
//
@ -1849,18 +1870,21 @@ UpdateVariable (
} else {
//
// For other Variables, append the new data to the end of previous data.
// Max Harware error record variable data size is different from common variable
//
CopyMem ((UINT8*)((UINTN) mStorageArea + Variable->CurrPtr->DataSize), Data, DataSize);
BufSize = Variable->CurrPtr->DataSize + DataSize;
if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
MaxDataSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER) - StrSize (VariableName) - GET_PAD_SIZE (StrSize (VariableName));
}
RevBufSize = MIN (PcdGet32 (PcdMaxVariableSize), ScratchDataSize);
if (BufSize > RevBufSize) {
if (Variable->CurrPtr->DataSize + DataSize > MaxDataSize) {
//
// If variable size (previous + current) is bigger than reserved buffer in runtime,
// return EFI_OUT_OF_RESOURCES.
// Exsiting data + Appended data exceed maximum variable size limitation
//
return EFI_OUT_OF_RESOURCES;
Status = EFI_INVALID_PARAMETER;
goto Done;
}
CopyMem ((UINT8*)((UINTN) mStorageArea + Variable->CurrPtr->DataSize), Data, DataSize);
BufSize = Variable->CurrPtr->DataSize + DataSize;
}
//