From 8c08a567c64814f36f7261ca5652ef0350ca660e Mon Sep 17 00:00:00 2001 From: ydong10 Date: Thu, 19 Apr 2012 09:57:11 +0000 Subject: [PATCH] Add code to check boot option variable before use it Signed-off-by: Eric Dong Reviewed-by: Ni Ruiyu git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13203 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Library/GenericBdsLib/BdsBoot.c | 50 +++++++---- .../Library/GenericBdsLib/BdsMisc.c | 88 ++++++++++++++++++- .../Library/GenericBdsLib/InternalBdsLib.h | 16 ++++ 3 files changed, 136 insertions(+), 18 deletions(-) diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c index 6f06ac9a85..c9c694e648 100644 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c +++ b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c @@ -1238,6 +1238,13 @@ BdsLibDeleteOptionFromHandle ( return EFI_OUT_OF_RESOURCES; } + if (!ValidateOption(BootOptionVar, BootOptionSize)) { + BdsDeleteBootOption (BootOrder[Index], BootOrder, &BootOrderSize); + FreePool (BootOptionVar); + Index++; + continue; + } + TempPtr = BootOptionVar; TempPtr += sizeof (UINT32) + sizeof (UINT16); TempPtr += StrSize ((CHAR16 *) TempPtr); @@ -1300,10 +1307,14 @@ BdsDeleteAllInvalidEfiBootOption ( EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath; UINT8 *TempPtr; CHAR16 *Description; + BOOLEAN Corrupted; - Status = EFI_SUCCESS; - BootOrder = NULL; - BootOrderSize = 0; + Status = EFI_SUCCESS; + BootOrder = NULL; + Description = NULL; + OptionDevicePath = NULL; + BootOrderSize = 0; + Corrupted = FALSE; // // Check "BootOrder" variable firstly, this variable hold the number of boot options @@ -1330,23 +1341,27 @@ BdsDeleteAllInvalidEfiBootOption ( return EFI_OUT_OF_RESOURCES; } - TempPtr = BootOptionVar; - TempPtr += sizeof (UINT32) + sizeof (UINT16); - Description = (CHAR16 *) TempPtr; - TempPtr += StrSize ((CHAR16 *) TempPtr); - OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr; + if (!ValidateOption(BootOptionVar, BootOptionSize)) { + Corrupted = TRUE; + } else { + TempPtr = BootOptionVar; + TempPtr += sizeof (UINT32) + sizeof (UINT16); + Description = (CHAR16 *) TempPtr; + TempPtr += StrSize ((CHAR16 *) TempPtr); + OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr; - // - // Skip legacy boot option (BBS boot device) - // - if ((DevicePathType (OptionDevicePath) == BBS_DEVICE_PATH) && - (DevicePathSubType (OptionDevicePath) == BBS_BBS_DP)) { - FreePool (BootOptionVar); - Index++; - continue; + // + // Skip legacy boot option (BBS boot device) + // + if ((DevicePathType (OptionDevicePath) == BBS_DEVICE_PATH) && + (DevicePathSubType (OptionDevicePath) == BBS_BBS_DP)) { + FreePool (BootOptionVar); + Index++; + continue; + } } - if (!BdsLibIsValidEFIBootOptDevicePathExt (OptionDevicePath, FALSE, Description)) { + if (Corrupted || !BdsLibIsValidEFIBootOptDevicePathExt (OptionDevicePath, FALSE, Description)) { // // Delete this invalid boot option "Boot####" // @@ -1361,6 +1376,7 @@ BdsDeleteAllInvalidEfiBootOption ( // Mark this boot option in boot order as deleted // BootOrder[Index] = 0xffff; + Corrupted = FALSE; } FreePool (BootOptionVar); diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c index 15a47e1917..9993e4b19d 100644 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c +++ b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c @@ -257,6 +257,14 @@ BdsLibRegisterNewOption ( if (OptionPtr == NULL) { continue; } + + // + // Validate the variable. + // + if (!ValidateOption(OptionPtr, OptionSize)) { + continue; + } + TempPtr = OptionPtr; TempPtr += sizeof (UINT32) + sizeof (UINT16); Description = (CHAR16 *) TempPtr; @@ -425,7 +433,7 @@ GetDevicePathSizeEx ( Size = 0; while (!IsDevicePathEnd (DevicePath)) { NodeSize = DevicePathNodeLength (DevicePath); - if (NodeSize == 0) { + if (NodeSize < END_DEVICE_PATH_LENGTH) { return 0; } Size += NodeSize; @@ -480,6 +488,76 @@ StrSizeEx ( return (Length + 1) * sizeof (*String); } +/** + Validate the EFI Boot#### variable (VendorGuid/Name) + + @param Variable Boot#### variable data. + @param VariableSize Returns the size of the EFI variable that was read + + @retval TRUE The variable data is correct. + @retval FALSE The variable data is corrupted. + +**/ +BOOLEAN +ValidateOption ( + UINT8 *Variable, + UINTN VariableSize + ) +{ + UINT16 FilePathSize; + UINT8 *TempPtr; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempPath; + UINTN TempSize; + + // + // Skip the option attribute + // + TempPtr = Variable; + TempPtr += sizeof (UINT32); + + // + // Get the option's device path size + // + FilePathSize = *(UINT16 *) TempPtr; + TempPtr += sizeof (UINT16); + + // + // Get the option's description string size + // + TempSize = StrSizeEx ((CHAR16 *) TempPtr, VariableSize); + TempPtr += TempSize; + + // + // Get the option's device path + // + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr; + TempPtr += FilePathSize; + + // + // Validation boot option variable. + // + if ((FilePathSize == 0) || (TempSize == 0)) { + return FALSE; + } + + if (TempSize + FilePathSize + sizeof (UINT16) + sizeof (UINT16) > VariableSize) { + return FALSE; + } + + TempPath = DevicePath; + while (FilePathSize > 0) { + TempSize = GetDevicePathSizeEx (TempPath, FilePathSize); + if (TempSize == 0) { + return FALSE; + } + FilePathSize = (UINT16) (FilePathSize - TempSize); + TempPath += TempSize; + } + + return TRUE; +} + /** Convert a single character to number. It assumes the input Char is in the scope of L'0' ~ L'9' and L'A' ~ L'F' @@ -548,6 +626,14 @@ BdsLibVariableToOption ( if (Variable == NULL) { return NULL; } + + // + // Validate Boot#### variable data. + // + if (!ValidateOption(Variable, VariableSize)) { + return NULL; + } + // // Notes: careful defined the variable of Boot#### or // Driver####, consider use some macro to abstract the code diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h b/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h index 28a6649347..039747df0f 100644 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h +++ b/IntelFrameworkModulePkg/Library/GenericBdsLib/InternalBdsLib.h @@ -126,4 +126,20 @@ BdsSetMemoryTypeInformationVariable ( VOID ); +/** + Validate the EFI Boot#### or Driver#### variable (VendorGuid/Name) + + @param Variable Boot#### variable data. + @param VariableSize Returns the size of the EFI variable that was read + + @retval TRUE The variable data is correct. + @retval FALSE The variable data is corrupted. + +**/ +BOOLEAN +ValidateOption ( + UINT8 *Variable, + UINTN VariableSize + ); + #endif // _BDS_LIB_H_ -- 2.39.2