Reviewed-by: Liming Gao <[email protected]>

>-----Original Message-----
>From: Bi, Dandan
>Sent: Monday, January 14, 2019 11:02 PM
>To: [email protected]
>Cc: Kinney, Michael D <[email protected]>; Gao, Liming
><[email protected]>
>Subject: [patch v2] MdePkg/BasePeCoffLib: Add more check for relocation
>data
>
>REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1426
>
>V2:
>(1) Add NULL pointer check for the input parameters
>(2) Add check for the "Adjust" value before applying fix ups.
>
>In function PeCoffLoaderRelocateImageForRuntime, it doesn't
>do much check when do relocation. For API level consideration,
>it's not safe enough.
>So this patch is to replace the same code logic with function
>PeCoffLoaderImageAddress which will cover more validation.
>
>Cc: Michael D Kinney <[email protected]>
>Cc: Liming Gao <[email protected]>
>Contributed-under: TianoCore Contribution Agreement 1.1
>Signed-off-by: Dandan Bi <[email protected]>
>---
> MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 165 +++++++++++++---------
> 1 file changed, 95 insertions(+), 70 deletions(-)
>
>diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
>b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
>index c57816a808..d9c94b89bd 100644
>--- a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
>+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
>@@ -13,11 +13,11 @@
>   This library will also do some additional check for PE header fields.
>
>   PeCoffLoaderGetPeHeader() routine will do basic check for PE/COFF header.
>   PeCoffLoaderGetImageInfo() routine will do basic check for whole PE/COFF
>image.
>
>-  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
>+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
>   Portions copyright (c) 2008 - 2009, Apple Inc. 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
>   http://opensource.org/licenses/bsd-license.php.
>@@ -1669,25 +1669,34 @@ PeCoffLoaderRelocateImageForRuntime (
>   UINT32                              NumberOfRvaAndSizes;
>   EFI_IMAGE_DATA_DIRECTORY            *DataDirectory;
>   EFI_IMAGE_DATA_DIRECTORY            *RelocDir;
>   EFI_IMAGE_BASE_RELOCATION           *RelocBase;
>   EFI_IMAGE_BASE_RELOCATION           *RelocBaseEnd;
>+  EFI_IMAGE_BASE_RELOCATION           *RelocBaseOrig;
>   UINT16                              *Reloc;
>   UINT16                              *RelocEnd;
>   CHAR8                               *Fixup;
>   CHAR8                               *FixupBase;
>   UINT16                              *Fixup16;
>   UINT32                              *Fixup32;
>   UINT64                              *Fixup64;
>   CHAR8                               *FixupData;
>   UINTN                               Adjust;
>   RETURN_STATUS                       Status;
>+  PE_COFF_LOADER_IMAGE_CONTEXT        ImageContext;
>+
>+  if (RelocationData == NULL || ImageBase == 0x0 || VirtImageBase == 0x0) {
>+    return;
>+  }
>
>   OldBase = (CHAR8 *)((UINTN)ImageBase);
>   NewBase = (CHAR8 *)((UINTN)VirtImageBase);
>   Adjust = (UINTN) NewBase - (UINTN) OldBase;
>
>+  ImageContext.ImageAddress = ImageBase;
>+  ImageContext.ImageSize = ImageSize;
>+
>   //
>   // Find the image's relocate dir info
>   //
>   DosHdr = (EFI_IMAGE_DOS_HEADER *)OldBase;
>   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
>@@ -1730,12 +1739,15 @@ PeCoffLoaderRelocateImageForRuntime (
>   // is present in the image. You have to check the NumberOfRvaAndSizes in
>   // the optional header to verify a desired directory entry is there.
>   //
>   if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
>     RelocDir      = DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC;
>-    RelocBase     = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(ImageBase +
>RelocDir->VirtualAddress);
>-    RelocBaseEnd  = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(ImageBase +
>RelocDir->VirtualAddress + RelocDir->Size);
>+    RelocBase     = (EFI_IMAGE_BASE_RELOCATION *)
>PeCoffLoaderImageAddress (&ImageContext, RelocDir->VirtualAddress, 0);
>+    RelocBaseEnd  = (EFI_IMAGE_BASE_RELOCATION *)
>PeCoffLoaderImageAddress (&ImageContext,
>+                                                                            
>RelocDir->VirtualAddress + RelocDir-
>>Size,
>+                                                                            0
>+                                                                            );
>   } else {
>     //
>     // Cannot find relocations, cannot continue to relocate the image, ASSERT
>for this invalid image.
>     //
>     ASSERT (FALSE);
>@@ -1745,100 +1757,113 @@ PeCoffLoaderRelocateImageForRuntime (
>   //
>   // ASSERT for the invalid image when RelocBase and RelocBaseEnd are both
>NULL.
>   //
>   ASSERT (RelocBase != NULL && RelocBaseEnd != NULL);
>
>-  //
>-  // Run the whole relocation block. And re-fixup data that has not been
>-  // modified. The FixupData is used to see if the image has been modified
>-  // since it was relocated. This is so data sections that have been updated
>-  // by code will not be fixed up, since that would set them back to
>-  // defaults.
>-  //
>-  FixupData = RelocationData;
>-  while (RelocBase < RelocBaseEnd) {
>+  if (Adjust != 0) {
>     //
>-    // Add check for RelocBase->SizeOfBlock field.
>+    // Run the whole relocation block. And re-fixup data that has not been
>+    // modified. The FixupData is used to see if the image has been modified
>+    // since it was relocated. This is so data sections that have been updated
>+    // by code will not be fixed up, since that would set them back to
>+    // defaults.
>     //
>-    if ((RelocBase->SizeOfBlock == 0) || (RelocBase->SizeOfBlock > RelocDir-
>>Size)) {
>+    FixupData = RelocationData;
>+    RelocBaseOrig = RelocBase;
>+    while (RelocBase < RelocBaseEnd) {
>       //
>-      // Data invalid, cannot continue to relocate the image, just return.
>+      // Add check for RelocBase->SizeOfBlock field.
>       //
>-      return;
>-    }
>-
>-    Reloc     = (UINT16 *) ((UINT8 *) RelocBase + sizeof
>(EFI_IMAGE_BASE_RELOCATION));
>-    RelocEnd  = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);
>-    FixupBase = (CHAR8 *) ((UINTN)ImageBase) + RelocBase->VirtualAddress;
>+      if ((RelocBase->SizeOfBlock == 0) || (RelocBase->SizeOfBlock > RelocDir-
>>Size)) {
>+        //
>+        // Data invalid, cannot continue to relocate the image, just return.
>+        //
>+        return;
>+      }
>
>-    //
>-    // Run this relocation record
>-    //
>-    while (Reloc < RelocEnd) {
>+      Reloc     = (UINT16 *) ((UINT8 *) RelocBase + sizeof
>(EFI_IMAGE_BASE_RELOCATION));
>+      RelocEnd  = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);
>+      if ((UINTN)RelocEnd > (UINTN)RelocBaseOrig + RelocDir->Size) {
>+        return;
>+      }
>
>-      Fixup = FixupBase + (*Reloc & 0xFFF);
>-      switch ((*Reloc) >> 12) {
>+      FixupBase = PeCoffLoaderImageAddress (&ImageContext, RelocBase-
>>VirtualAddress, 0);
>+      if (FixupBase == NULL) {
>+        return;
>+      }
>
>-      case EFI_IMAGE_REL_BASED_ABSOLUTE:
>-        break;
>+      //
>+      // Run this relocation record
>+      //
>+      while (Reloc < RelocEnd) {
>
>-      case EFI_IMAGE_REL_BASED_HIGH:
>-        Fixup16 = (UINT16 *) Fixup;
>-        if (*(UINT16 *) FixupData == *Fixup16) {
>-          *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));
>+        Fixup = PeCoffLoaderImageAddress (&ImageContext, RelocBase-
>>VirtualAddress + (*Reloc & 0xFFF), 0);
>+        if (Fixup == NULL) {
>+          return;
>         }
>+        switch ((*Reloc) >> 12) {
>
>-        FixupData = FixupData + sizeof (UINT16);
>-        break;
>+        case EFI_IMAGE_REL_BASED_ABSOLUTE:
>+          break;
>
>-      case EFI_IMAGE_REL_BASED_LOW:
>-        Fixup16 = (UINT16 *) Fixup;
>-        if (*(UINT16 *) FixupData == *Fixup16) {
>-          *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) Adjust & 0xffff));
>-        }
>+        case EFI_IMAGE_REL_BASED_HIGH:
>+          Fixup16 = (UINT16 *) Fixup;
>+          if (*(UINT16 *) FixupData == *Fixup16) {
>+            *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 
>16)));
>+          }
>
>-        FixupData = FixupData + sizeof (UINT16);
>-        break;
>+          FixupData = FixupData + sizeof (UINT16);
>+          break;
>
>-      case EFI_IMAGE_REL_BASED_HIGHLOW:
>-        Fixup32       = (UINT32 *) Fixup;
>-        FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
>-        if (*(UINT32 *) FixupData == *Fixup32) {
>-          *Fixup32 = *Fixup32 + (UINT32) Adjust;
>-        }
>+        case EFI_IMAGE_REL_BASED_LOW:
>+          Fixup16 = (UINT16 *) Fixup;
>+          if (*(UINT16 *) FixupData == *Fixup16) {
>+            *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) Adjust & 0xffff));
>+          }
>
>-        FixupData = FixupData + sizeof (UINT32);
>-        break;
>+          FixupData = FixupData + sizeof (UINT16);
>+          break;
>
>-      case EFI_IMAGE_REL_BASED_DIR64:
>-        Fixup64       = (UINT64 *)Fixup;
>-        FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64));
>-        if (*(UINT64 *) FixupData == *Fixup64) {
>-          *Fixup64 = *Fixup64 + (UINT64)Adjust;
>-        }
>+        case EFI_IMAGE_REL_BASED_HIGHLOW:
>+          Fixup32       = (UINT32 *) Fixup;
>+          FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
>+          if (*(UINT32 *) FixupData == *Fixup32) {
>+            *Fixup32 = *Fixup32 + (UINT32) Adjust;
>+          }
>
>-        FixupData = FixupData + sizeof (UINT64);
>-        break;
>+          FixupData = FixupData + sizeof (UINT32);
>+          break;
>
>-      default:
>+        case EFI_IMAGE_REL_BASED_DIR64:
>+          Fixup64       = (UINT64 *)Fixup;
>+          FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64));
>+          if (*(UINT64 *) FixupData == *Fixup64) {
>+            *Fixup64 = *Fixup64 + (UINT64)Adjust;
>+          }
>+
>+          FixupData = FixupData + sizeof (UINT64);
>+          break;
>+
>+        default:
>+          //
>+          // Only Itanium requires ConvertPeImage_Ex
>+          //
>+          Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);
>+          if (RETURN_ERROR (Status)) {
>+            return ;
>+          }
>+        }
>         //
>-        // Only Itanium requires ConvertPeImage_Ex
>+        // Next relocation record
>         //
>-        Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);
>-        if (RETURN_ERROR (Status)) {
>-          return ;
>-        }
>+        Reloc += 1;
>       }
>       //
>-      // Next relocation record
>+      // next reloc block
>       //
>-      Reloc += 1;
>+      RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
>     }
>-    //
>-    // next reloc block
>-    //
>-    RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
>   }
> }
>
>
> /**
>--
>2.18.0.windows.1

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to