From: ydong10 Date: Thu, 12 Jan 2012 05:32:59 +0000 (+0000) Subject: Add check when get boot option variable to avoid system hang. X-Git-Tag: edk2-stable201903~13700 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=b16cc38bf3d74e7b781022aad96f28b3f8507fdd Add check when get boot option variable to avoid system hang. Signed-off-by: ydong10 Reviewed-by: niruiyu git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12927 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c index 68ddfc334f..881f4dc002 100644 --- a/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c +++ b/IntelFrameworkModulePkg/Library/GenericBdsLib/BdsMisc.c @@ -390,6 +390,95 @@ BdsLibRegisterNewOption ( return Status; } +/** + Returns the size of a device path in bytes. + + This function returns the size, in bytes, of the device path data structure + specified by DevicePath including the end of device path node. If DevicePath + is NULL, then 0 is returned. If the length of the device path is bigger than + MaxSize, also return 0 to indicate this is an invalidate device path. + + @param DevicePath A pointer to a device path data structure. + @param MaxSize Max valid device path size. If big than this size, + return error. + + @retval 0 An invalid device path. + @retval Others The size of a device path in bytes. + +**/ +UINTN +GetDevicePathSizeEx ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN UINTN MaxSize + ) +{ + UINTN Size; + UINTN NodeSize; + + if (DevicePath == NULL) { + return 0; + } + + // + // Search for the end of the device path structure + // + Size = 0; + while (!IsDevicePathEnd (DevicePath)) { + NodeSize = DevicePathNodeLength (DevicePath); + if (NodeSize == 0) { + return 0; + } + Size += NodeSize; + if (Size > MaxSize) { + return 0; + } + DevicePath = NextDevicePathNode (DevicePath); + } + Size += DevicePathNodeLength (DevicePath); + if (Size > MaxSize) { + return 0; + } + + return Size; +} + +/** + Returns the length of a Null-terminated Unicode string. If the length is + bigger than MaxStringLen, return length 0 to indicate that this is an + invalidate string. + + This function returns the number of Unicode characters in the Null-terminated + Unicode string specified by String. + + If String is NULL, then ASSERT(). + If String is not aligned on a 16-bit boundary, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + @param MaxStringLen Max string len in this string. + + @retval 0 An invalid string. + @retval Others The length of String. + +**/ +UINTN +StrSizeEx ( + IN CONST CHAR16 *String, + IN UINTN MaxStringLen + ) +{ + UINTN Length; + + ASSERT (String != NULL && MaxStringLen != 0); + ASSERT (((UINTN) String & BIT0) == 0); + + for (Length = 0; *String != L'\0' && MaxStringLen != Length; String++, Length++); + + if (*String != L'\0' && MaxStringLen == Length) { + return 0; + } + + return (Length + 1) * sizeof (*String); +} /** Build the boot#### or driver#### option from the VariableName, the @@ -417,11 +506,13 @@ BdsLibVariableToOption ( UINT8 *TempPtr; UINTN VariableSize; EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempPath; BDS_COMMON_OPTION *Option; VOID *LoadOptions; UINT32 LoadOptionsSize; CHAR16 *Description; UINT8 NumOff; + UINTN TempSize; // // Read the variable. We will never free this data. // @@ -458,7 +549,11 @@ BdsLibVariableToOption ( // // Get the option's description string size // - TempPtr += StrSize ((CHAR16 *) TempPtr); + TempSize = StrSizeEx ((CHAR16 *) TempPtr, VariableSize); + if (TempSize == 0) { + return NULL; + } + TempPtr += TempSize; // // Get the option's device path @@ -466,7 +561,26 @@ BdsLibVariableToOption ( DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr; TempPtr += FilePathSize; + // + // Validation device path. + // + TempPath = DevicePath; + while (FilePathSize > 0) { + TempSize = GetDevicePathSizeEx (TempPath, FilePathSize); + if (TempSize == 0) { + return NULL; + } + FilePathSize = (UINT16) (FilePathSize - TempSize); + TempPath += TempSize; + } + + // + // Get load opion data. + // LoadOptions = TempPtr; + if (VariableSize < (UINTN)(TempPtr - Variable)) { + return NULL; + } LoadOptionsSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable)); //