]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Prevent illegal memory access when checking relocs in a corrupt ELF binary.
authorNick Clifton <nickc@redhat.com>
Wed, 5 Feb 2025 14:31:10 +0000 (14:31 +0000)
committerNick Clifton <nickc@redhat.com>
Wed, 5 Feb 2025 14:31:10 +0000 (14:31 +0000)
PR 32641

bfd/elf-bfd.h
bfd/elf64-x86-64.c
bfd/elflink.c
bfd/elfxx-x86.c

index 785a37dd7fdf7f48e51b6033a4f3fc8680da4d82..d2bf8e5cbaef9809df98256ef856d469111381e6 100644 (file)
@@ -3153,6 +3153,9 @@ extern bool _bfd_elf_link_mmap_section_contents
 extern void _bfd_elf_link_munmap_section_contents
   (asection *);
 
+extern struct elf_link_hash_entry * _bfd_elf_get_link_hash_entry
+  (struct elf_link_hash_entry **, unsigned int, Elf_Internal_Shdr *);
+
 /* Large common section.  */
 extern asection _bfd_elf_large_com_section;
 
index 32db254ba6cd2e6bd669776b14c5353a4518f100..2d82c6583c398c096f4e0235ff7d0756f2fcc488 100644 (file)
@@ -1784,7 +1784,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
   bool to_reloc_pc32;
   bool abs_symbol;
   bool local_ref;
-  asection *tsec;
+  asection *tsec = NULL;
   bfd_signed_vma raddend;
   unsigned int opcode;
   unsigned int modrm;
@@ -1999,6 +1999,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
        return true;
     }
 
+  if (tsec == NULL)
+    return false;
+
   /* Don't convert GOTPCREL relocation against large section.  */
   if (elf_section_data (tsec) !=  NULL
       && (elf_section_flags (tsec) & SHF_X86_64_LARGE) != 0)
@@ -2408,10 +2411,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
       else
        {
          isym = NULL;
-         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-         while (h->root.type == bfd_link_hash_indirect
-                || h->root.type == bfd_link_hash_warning)
-           h = (struct elf_link_hash_entry *) h->root.u.i.link;
+         h = _bfd_elf_get_link_hash_entry (sym_hashes, r_symndx, symtab_hdr);
        }
 
       /* Check invalid x32 relocations.  */
index 1f1263007c0e44ea029fc5abc1c55be00ae497c2..eafbd133ff54c93855f5286254e82db66a5c1eca 100644 (file)
@@ -96,6 +96,27 @@ _bfd_elf_link_keep_memory (struct bfd_link_info *info)
   return true;
 }
 
+struct elf_link_hash_entry *
+_bfd_elf_get_link_hash_entry (struct elf_link_hash_entry **  sym_hashes,
+                             unsigned int                   symndx,
+                             Elf_Internal_Shdr *            symtab_hdr)
+{
+  if (symndx < symtab_hdr->sh_info)
+    return NULL;
+
+  struct elf_link_hash_entry *h = sym_hashes[symndx - symtab_hdr->sh_info];
+
+  /* The hash might be empty.  See PR 32641 for an example of this.  */
+  if (h == NULL)
+    return NULL;
+
+  while (h->root.type == bfd_link_hash_indirect
+        || h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  return h;
+}
+
 static struct elf_link_hash_entry *
 get_ext_sym_hash (struct elf_reloc_cookie *cookie, unsigned long r_symndx)
 {
@@ -108,6 +129,9 @@ get_ext_sym_hash (struct elf_reloc_cookie *cookie, unsigned long r_symndx)
     {
       h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
 
+      if (h == NULL)
+       return NULL;
+
       while (h->root.type == bfd_link_hash_indirect
             || h->root.type == bfd_link_hash_warning)
        h = (struct elf_link_hash_entry *) h->root.u.i.link;
index 8e5a005fd36ed12318a49d9ece7840692126e060..832a5495eb1f4f4952814f950795b576ad13fc7c 100644 (file)
@@ -973,15 +973,7 @@ _bfd_x86_elf_check_relocs (bfd *abfd,
          goto error_return;
        }
 
-      if (r_symndx < symtab_hdr->sh_info)
-       h = NULL;
-      else
-       {
-         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-         while (h->root.type == bfd_link_hash_indirect
-                || h->root.type == bfd_link_hash_warning)
-           h = (struct elf_link_hash_entry *) h->root.u.i.link;
-       }
+      h = _bfd_elf_get_link_hash_entry (sym_hashes, r_symndx, symtab_hdr);
 
       if (X86_NEED_DYNAMIC_RELOC_TYPE_P (is_x86_64, r_type)
          && NEED_DYNAMIC_RELOCATION_P (is_x86_64, info, true, h, sec,
@@ -1209,10 +1201,12 @@ _bfd_x86_elf_link_relax_section (bfd *abfd ATTRIBUTE_UNUSED,
       else
        {
          /* Get H and SEC for GENERATE_DYNAMIC_RELOCATION_P below.  */
-         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-         while (h->root.type == bfd_link_hash_indirect
-                || h->root.type == bfd_link_hash_warning)
-           h = (struct elf_link_hash_entry *) h->root.u.i.link;
+         h = _bfd_elf_get_link_hash_entry (sym_hashes, r_symndx, symtab_hdr);
+         if (h == NULL)
+           {
+             /* FIXMEL: Issue an error message ?  */
+             continue;
+           }
 
          if (h->root.type == bfd_link_hash_defined
              || h->root.type == bfd_link_hash_defweak)