]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/Common/FvLib.c
BaseTools/GenSec: Fix potential null pointer dereference
[mirror_edk2.git] / BaseTools / Source / C / Common / FvLib.c
index dc50e877e64e3417c01b6665ac5bc06562300010..f97a7f21ce63875d612c4100a7043ee2e0adfab6 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
+These functions assist in parsing and manipulating a Firmware Volume.\r
 \r
-Copyright (c) 2004 - 2008, Intel Corporation                                                         \r
-All rights reserved. This program and the accompanying materials                          \r
+Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials                          \r
 are licensed and made available under the terms and conditions of the BSD License         \r
 which accompanies this distribution.  The full text of the license may be found at        \r
 http://opensource.org/licenses/bsd-license.php                                            \r
@@ -9,14 +10,6 @@ http://opensource.org/licenses/bsd-license.php
 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
 \r
-Module Name:\r
-\r
-  FvLib.c\r
-\r
-Abstract:\r
-\r
-  These functions assist in parsing and manipulating a Firmware Volume.\r
-\r
 **/\r
 \r
 //\r
@@ -110,6 +103,7 @@ Returns:
   }\r
 \r
   *FvHeader = mFvHeader;\r
+  *FvLength = mFvLength;\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -180,7 +174,7 @@ Returns:
       //\r
       // Verify file is in this FV.\r
       //\r
-      if ((UINTN) CurrentFile + GetLength (CurrentFile->Size) > (UINTN) mFvHeader + mFvLength) {\r
+      if ((UINTN) CurrentFile + GetFfsFileLength(CurrentFile) > (UINTN) mFvHeader + mFvLength) {\r
         *NextFile = NULL;\r
         return EFI_SUCCESS;\r
       }\r
@@ -193,20 +187,20 @@ Returns:
   // Verify current file is in range\r
   //\r
   if (((UINTN) CurrentFile < (UINTN) mFvHeader + mFvHeader->HeaderLength) ||\r
-      ((UINTN) CurrentFile + GetLength (CurrentFile->Size) > (UINTN) mFvHeader + mFvLength)\r
+      ((UINTN) CurrentFile + GetFfsFileLength(CurrentFile) > (UINTN) mFvHeader + mFvLength)\r
      ) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   //\r
   // Get next file, compensate for 8 byte alignment if necessary.\r
   //\r
-  *NextFile = (EFI_FFS_FILE_HEADER *) (((UINTN) CurrentFile + GetLength (CurrentFile->Size) + 0x07) & (-1 << 3));\r
+  *NextFile = (EFI_FFS_FILE_HEADER *) ((((UINTN) CurrentFile - (UINTN) mFvHeader + GetFfsFileLength(CurrentFile) + 0x07) & (~(UINTN) 7)) + (UINT8 *) mFvHeader);\r
 \r
   //\r
   // Verify file is in this FV.\r
   //\r
-  if (((UINTN) *NextFile + sizeof (EFI_FFS_FILE_HEADER) >= (UINTN) mFvHeader + mFvLength) ||\r
-      ((UINTN) *NextFile + GetLength ((*NextFile)->Size) > (UINTN) mFvHeader + mFvLength)\r
+  if (((UINTN) *NextFile + GetFfsHeaderLength(*NextFile) >= (UINTN) mFvHeader + mFvLength) ||\r
+      ((UINTN) *NextFile + GetFfsFileLength (*NextFile) > (UINTN) mFvHeader + mFvLength)\r
      ) {\r
     *NextFile = NULL;\r
     return EFI_SUCCESS;\r
@@ -433,7 +427,11 @@ Returns:
   EFI_FILE_SECTION_POINTER  InnerSection;\r
   EFI_STATUS                Status;\r
   UINTN                     SectionSize;\r
+  UINT16                    GuidSecAttr;\r
+  UINT16                    GuidDataOffset;\r
 \r
+  GuidSecAttr = 0;\r
+  GuidDataOffset = 0;\r
   CurrentSection = FirstSection;\r
 \r
   while ((UINTN) CurrentSection.CommonHeader < (UINTN) SearchEnd) {\r
@@ -451,14 +449,21 @@ Returns:
     // special processing, go ahead to search the requesting\r
     // section inside the GUID-defined section.\r
     //\r
+    if (CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED) {\r
+      if (GetLength(CurrentSection.CommonHeader->Size) == 0xffffff) {\r
+        GuidSecAttr = CurrentSection.GuidDefinedSection2->Attributes;\r
+        GuidDataOffset = CurrentSection.GuidDefinedSection2->DataOffset;\r
+      } else {\r
+        GuidSecAttr = CurrentSection.GuidDefinedSection->Attributes;\r
+        GuidDataOffset = CurrentSection.GuidDefinedSection->DataOffset;\r
+      }\r
+    }\r
     if (SectionType != EFI_SECTION_GUID_DEFINED &&\r
         CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED &&\r
-        !(CurrentSection.GuidDefinedSection->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED)) {\r
+        !(GuidSecAttr & EFI_GUIDED_SECTION_PROCESSING_REQUIRED)) {\r
       InnerSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *)\r
-        ((UINTN) CurrentSection.CommonHeader + CurrentSection.GuidDefinedSection->DataOffset);\r
-      SectionSize = CurrentSection.CommonHeader->Size[0] +\r
-        (CurrentSection.CommonHeader->Size[1] << 8) + \r
-        (CurrentSection.CommonHeader->Size[2] << 16);\r
+        ((UINTN) CurrentSection.CommonHeader + GuidDataOffset);\r
+      SectionSize = GetSectionFileLength(CurrentSection.CommonHeader);\r
       Status = SearchSectionByType (\r
                  InnerSection,\r
                  (UINT8 *) ((UINTN) CurrentSection.CommonHeader + SectionSize),\r
@@ -474,7 +479,7 @@ Returns:
     //\r
     // Find next section (including compensating for alignment issues.\r
     //\r
-    CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetLength (CurrentSection.CommonHeader->Size) + 0x03) & (-1 << 2));\r
+    CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetSectionFileLength(CurrentSection.CommonHeader) + 0x03) & (~(UINTN) 3));\r
   }\r
 \r
   return EFI_NOT_FOUND;\r
@@ -537,14 +542,14 @@ Returns:
   //\r
   // Get the first section\r
   //\r
-  CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + sizeof (EFI_FFS_FILE_HEADER));\r
+  CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + GetFfsHeaderLength(File));\r
   \r
   //\r
   // Depth-first manner to find section file.\r
   //\r
   Status = SearchSectionByType (\r
              CurrentSection,\r
-             (UINT8 *) ((UINTN) File + GetLength (File->Size)),\r
+             (UINT8 *) ((UINTN) File + GetFfsFileLength (File)),\r
              SectionType,\r
              &SectionCount,\r
              Instance,\r
@@ -638,12 +643,14 @@ Returns:
 {\r
   BOOLEAN             ErasePolarity;\r
   EFI_STATUS          Status;\r
-  EFI_FFS_FILE_HEADER BlankHeader;\r
+  EFI_FFS_FILE_HEADER2 BlankHeader;\r
   UINT8               Checksum;\r
   UINT32              FileLength;\r
   UINT8               SavedChecksum;\r
   UINT8               SavedState;\r
   UINT8               FileGuidString[80];\r
+  UINT32              FfsHeaderSize;\r
+\r
   //\r
   // Verify library has been initialized.\r
   //\r
@@ -664,16 +671,18 @@ Returns:
   if (EFI_ERROR (Status)) {\r
     return EFI_ABORTED;\r
   }\r
+\r
+  FfsHeaderSize = GetFfsHeaderLength(FfsHeader);\r
   //\r
   // Check if we have free space\r
   //\r
   if (ErasePolarity) {\r
-    memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER));\r
+    memset (&BlankHeader, -1, FfsHeaderSize);\r
   } else {\r
-    memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER));\r
+    memset (&BlankHeader, 0, FfsHeaderSize);\r
   }\r
 \r
-  if (memcmp (&BlankHeader, FfsHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) {\r
+  if (memcmp (&BlankHeader, FfsHeader, FfsHeaderSize) == 0) {\r
     return EFI_NOT_FOUND;\r
   }\r
   //\r
@@ -688,7 +697,7 @@ Returns:
   FfsHeader->State = 0;\r
   SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File;\r
   FfsHeader->IntegrityCheck.Checksum.File = 0;\r
-  Checksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER));\r
+  Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FfsHeaderSize);\r
   FfsHeader->State = SavedState;\r
   FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum;\r
   if (Checksum != 0) {\r
@@ -702,8 +711,8 @@ Returns:
     //\r
     // Verify file data checksum\r
     //\r
-    FileLength          = GetLength (FfsHeader->Size);\r
-    Checksum            = CalculateSum8 ((UINT8 *) (FfsHeader + 1), FileLength - sizeof (EFI_FFS_FILE_HEADER));\r
+    FileLength          = GetFfsFileLength (FfsHeader);\r
+    Checksum            = CalculateSum8 ((UINT8 *) ((UINT8 *)FfsHeader + FfsHeaderSize), FileLength - FfsHeaderSize);\r
     Checksum            = Checksum + FfsHeader->IntegrityCheck.Checksum.File;\r
     if (Checksum != 0) {\r
       Error (NULL, 0, 0006, "invalid FFS file checksum", "Ffs file with Guid %s", FileGuidString);\r
@@ -723,6 +732,80 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
+UINT32\r
+GetFfsHeaderLength(\r
+   IN EFI_FFS_FILE_HEADER *FfsHeader\r
+   )\r
+{\r
+  if (FfsHeader == NULL) {\r
+    return 0;\r
+  }\r
+  if (FfsHeader->Attributes & FFS_ATTRIB_LARGE_FILE) {\r
+    return sizeof(EFI_FFS_FILE_HEADER2);\r
+  }\r
+  return sizeof(EFI_FFS_FILE_HEADER);\r
+}\r
+\r
+UINT32\r
+GetSectionHeaderLength(\r
+   IN EFI_COMMON_SECTION_HEADER *SectionHeader\r
+   )\r
+{\r
+  if (SectionHeader == NULL) {\r
+    return 0;\r
+  }\r
+  if (GetLength(SectionHeader->Size) == 0xffffff) {\r
+    return sizeof(EFI_COMMON_SECTION_HEADER2);\r
+  }\r
+  return sizeof(EFI_COMMON_SECTION_HEADER);\r
+}\r
+\r
+UINT32\r
+GetFfsFileLength (\r
+  EFI_FFS_FILE_HEADER *FfsHeader\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Get FFS file length including FFS header.\r
+\r
+Arguments:\r
+\r
+  FfsHeader   Pointer to EFI_FFS_FILE_HEADER.\r
+\r
+Returns:\r
+\r
+  UINT32      Length of FFS file header.\r
+\r
+--*/\r
+{\r
+  if (FfsHeader == NULL) {\r
+    return 0;\r
+  }\r
+  if (FfsHeader->Attributes & FFS_ATTRIB_LARGE_FILE) {\r
+    return (UINT32) ((EFI_FFS_FILE_HEADER2 *)FfsHeader)->ExtendedSize;\r
+  } else {\r
+    return GetLength(FfsHeader->Size);\r
+  }\r
+}\r
+\r
+UINT32\r
+GetSectionFileLength (\r
+  EFI_COMMON_SECTION_HEADER *SectionHeader\r
+  )\r
+{\r
+  UINT32 Length;\r
+  if (SectionHeader == NULL) {\r
+    return 0;\r
+  }\r
+  Length = GetLength(SectionHeader->Size);\r
+  if (Length == 0xffffff) {\r
+    Length = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;\r
+  }\r
+  return Length;\r
+}\r
+\r
 UINT32\r
 GetLength (\r
   UINT8     *ThreeByteLength\r