PR30326, uninitialised value in objdump compare_relocs
authorAlan Modra <amodra@gmail.com>
Wed, 12 Apr 2023 01:30:42 +0000 (11:00 +0930)
committerAlan Modra <amodra@gmail.com>
Wed, 12 Apr 2023 04:43:46 +0000 (14:13 +0930)
This is a fuzzing PR, with a testcase involving a SHF_ALLOC and
SHF_COMPRESSED SHT_RELA section, ie. a compressed dynamic reloc
section.  BFD doesn't handle compressed relocation sections, with most
of the code reading relocs using sh_size (often no bfd section is
created) but in the case of SHF_ALLOC dynamic relocs we had some code
using the bfd section size.  This led to a mismatch, sh_size is
compressed, size is uncompressed, and from that some uninitialised
memory.  Consistently using sh_size is enough to fix this PR, but I've
also added tests to exclude SHF_COMPRESSED reloc sections from
consideration.

PR 30362
* elf.c (bfd_section_from_shdr): Exclude reloc sections with
SHF_COMPRESSED flag from normal reloc processing.
(_bfd_elf_get_dynamic_reloc_upper_bound): Similarly exclude
SHF_COMPRESSED sections from consideration.  Use sh_size when
sizing to match slurp_relocs.
(_bfd_elf_canonicalize_dynamic_reloc): Likewise.
(_bfd_elf_get_synthetic_symtab): Use NUM_SHDR_ENTRIES to size
plt relocs.
* elf32-arm.c (elf32_arm_get_synthetic_symtab): Likewise.
* elf32-ppc.c (ppc_elf_get_synthetic_symtab): Likewise.
* elf64-ppc.c (ppc64_elf_get_synthetic_symtab): Likewise.
* elfxx-mips.c (_bfd_mips_elf_get_synthetic_symtab): Likewise.

bfd/elf.c
bfd/elf32-arm.c
bfd/elf32-ppc.c
bfd/elf64-ppc.c
bfd/elfxx-mips.c

index 0e2ae6dae1cccd2506d770203513dd7426b1d040..fa7c25ad9dc98dc6322934e3a86735bc24fecef7 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2381,6 +2381,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
           its sh_link points to the null section.  */
        if (((abfd->flags & (DYNAMIC | EXEC_P)) != 0
             && (hdr->sh_flags & SHF_ALLOC) != 0)
+           || (hdr->sh_flags & SHF_COMPRESSED) != 0
            || hdr->sh_type == SHT_RELR
            || hdr->sh_link == SHN_UNDEF
            || hdr->sh_link != elf_onesymtab (abfd)
@@ -8728,15 +8729,16 @@ _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
   for (s = abfd->sections; s != NULL; s = s->next)
     if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
        && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
-           || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
+           || elf_section_data (s)->this_hdr.sh_type == SHT_RELA)
+       && (elf_section_data (s)->this_hdr.sh_flags & SHF_COMPRESSED) == 0)
       {
-       ext_rel_size += s->size;
-       if (ext_rel_size < s->size)
+       ext_rel_size += elf_section_data (s)->this_hdr.sh_size;
+       if (ext_rel_size < elf_section_data (s)->this_hdr.sh_size)
          {
            bfd_set_error (bfd_error_file_truncated);
            return -1;
          }
-       count += s->size / elf_section_data (s)->this_hdr.sh_entsize;
+       count += NUM_SHDR_ENTRIES (&elf_section_data (s)->this_hdr);
        if (count > LONG_MAX / sizeof (arelent *))
          {
            bfd_set_error (bfd_error_file_too_big);
@@ -8785,14 +8787,15 @@ _bfd_elf_canonicalize_dynamic_reloc (bfd *abfd,
     {
       if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
          && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
-             || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
+             || elf_section_data (s)->this_hdr.sh_type == SHT_RELA)
+         && (elf_section_data (s)->this_hdr.sh_flags & SHF_COMPRESSED) == 0)
        {
          arelent *p;
          long count, i;
 
          if (! (*slurp_relocs) (abfd, s, syms, true))
            return -1;
-         count = s->size / elf_section_data (s)->this_hdr.sh_entsize;
+         count = NUM_SHDR_ENTRIES (&elf_section_data (s)->this_hdr);
          p = s->relocation;
          for (i = 0; i < count; i++)
            *storage++ = p++;
@@ -12936,7 +12939,7 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd,
   if (! (*slurp_relocs) (abfd, relplt, dynsyms, true))
     return -1;
 
-  count = relplt->size / hdr->sh_entsize;
+  count = NUM_SHDR_ENTRIES (hdr);
   size = count * sizeof (asymbol);
   p = relplt->relocation;
   for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel)
index e07e12226a56d492d45cc65d735ef6fabd69efc3..70413668e5a5ec3d451eca075329b39a8d8d9a7f 100644 (file)
@@ -20067,7 +20067,7 @@ elf32_arm_get_synthetic_symtab (bfd *abfd,
       plt->flags |= SEC_IN_MEMORY;
     }
 
-  count = relplt->size / hdr->sh_entsize;
+  count = NUM_SHDR_ENTRIES (hdr);
   size = count * sizeof (asymbol);
   p = relplt->relocation;
   for (i = 0; i < count; i++, p += elf32_arm_size_info.int_rels_per_ext_rel)
index bb77ba2d5c7269e69f77f6d2386364d8eedd4267..2cff158a5f546bd20ce6ff0a74ab9d61d628c5b7 100644 (file)
@@ -1920,7 +1920,7 @@ ppc_elf_get_synthetic_symtab (bfd *abfd, long symcount, asymbol **syms,
            }
     }
 
-  count = relplt->size / sizeof (Elf32_External_Rela);
+  count = NUM_SHDR_ENTRIES (&elf_section_data (relplt)->this_hdr);
   /* If the stubs are those for -shared/-pie then we might have
      multiple stubs for each plt entry.  If that is the case then
      there is no way to associate stubs with their plt entries short
index 069bd758aec1e30b5b22c02ec504960fa8f66afc..daa6deef7289c13879e8bc5a554eba21b137b6d3 100644 (file)
@@ -2576,7 +2576,7 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
              if (!(*slurp_relocs) (abfd, relplt, dyn_syms, true))
                goto free_contents_and_exit_err;
 
-             plt_count = relplt->size / sizeof (Elf64_External_Rela);
+             plt_count = NUM_SHDR_ENTRIES (&elf_section_data (relplt)->this_hdr);
              size += plt_count * sizeof (asymbol);
 
              p = relplt->relocation;
index d34a755807b28eb4f68bb4ec7a357451fa3da56e..751deede8870b2f269af6af91a782bb75593bcf0 100644 (file)
@@ -16595,7 +16595,7 @@ _bfd_mips_elf_get_synthetic_symtab (bfd *abfd,
   /* Calculating the exact amount of space required for symbols would
      require two passes over the PLT, so just pessimise assuming two
      PLT slots per relocation.  */
-  count = relplt->size / hdr->sh_entsize;
+  count = NUM_SHDR_ENTRIES (hdr);
   counti = count * bed->s->int_rels_per_ext_rel;
   size = 2 * count * sizeof (asymbol);
   size += count * (sizeof (mipssuffix) +