MIPS64/BFD: Fix a crash with invalid `r_sym' in relocation
authorMaciej W. Rozycki <macro@mips.com>
Mon, 9 Apr 2018 12:42:00 +0000 (13:42 +0100)
committerMaciej W. Rozycki <macro@mips.com>
Mon, 9 Apr 2018 12:42:00 +0000 (13:42 +0100)
Prevent an out-of-range access and a possible segmentation fault in
`mips_elf64_slurp_one_reloc_table':

Program received signal SIGSEGV, Segmentation fault.
mips_elf64_slurp_one_reloc_table (abfd=0x71bd90, asect=0x71cf70,
    rel_hdr=<value optimized out>, reloc_count=1,
    relents=<value optimized out>, symbols=0x7218c0, dynamic=0)
    at .../bfd/elf64-mips.c:3758
3757       ps = symbols + rela.r_sym - 1;
3758       s = *ps;

in the MIPS64 (n64 MIPS) ELF backend whenever an invalid symbol index is
retrieved from the `r_sym' field of a relocation seen in input while
running `objcopy' or `strip'.  Issue an error instead, like the generic
ELF backend does, taking code from `elf_slurp_reloc_table_from_section',
except for relocation types that do not refer to a symbol.

This complements commit 1f70368c21a8 ("Stop objdump crash on corrupt
reloc table"), <https://sourceware.org/ml/binutils/2002-09/msg00332.html>,
and commit 05a487dc8c39 ("make check fails on i686-linux-gnu"),
<https://sourceware.org/ml/binutils/2002-09/msg00340.html>, where the
generic ELF backend code comes from.

bfd/
* elf64-mips.c (mips_elf64_slurp_one_reloc_table): Issue an
error for out-of-range `r_sym' values.

bfd/ChangeLog
bfd/elf64-mips.c

index 8df416ff3cf330e385d44a0df7f2f56d08fd70dc..d65d5a8a92e869ed68313c81c5f2b69e66845f81 100644 (file)
@@ -1,3 +1,8 @@
+2018-04-09  Maciej W. Rozycki  <macro@mips.com>
+
+       * elf64-mips.c (mips_elf64_slurp_one_reloc_table): Issue an
+       error for out-of-range `r_sym' values.
+
 2018-04-09  Alan Modra  <amodra@gmail.com>
 
        * elf64-ppc.c (struct _ppc64_elf_section_data): Add has_pltcall field.
index 115047f32c08d2a20bf21b3d5c7e1939944f1cd4..86e55897cfe8f5d2f177ce6c08ee4fb6d7e76a13 100644 (file)
@@ -3669,6 +3669,7 @@ mips_elf64_slurp_one_reloc_table (bfd *abfd, asection *asect,
 {
   void *allocated;
   bfd_byte *native_relocs;
+  unsigned int symcount;
   arelent *relent;
   bfd_vma i;
   int entsize;
@@ -3694,6 +3695,11 @@ mips_elf64_slurp_one_reloc_table (bfd *abfd, asection *asect,
   else
     rela_p = TRUE;
 
+  if (dynamic)
+    symcount = bfd_get_dynamic_symcount (abfd);
+  else
+    symcount = bfd_get_symcount (abfd);
+
   for (i = 0, relent = relents;
        i < reloc_count;
        i++, native_relocs += entsize)
@@ -3750,6 +3756,17 @@ mips_elf64_slurp_one_reloc_table (bfd *abfd, asection *asect,
                {
                  if (rela.r_sym == STN_UNDEF)
                    relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+                 else if (rela.r_sym > symcount)
+                   {
+                     _bfd_error_handler
+                       /* xgettext:c-format */
+                       (_("%pB(%pA): relocation %" PRIu64
+                          " has invalid symbol index %ld"),
+                        abfd, asect, (uint64_t) i, rela.r_sym);
+                     bfd_set_error (bfd_error_bad_value);
+                     relent->sym_ptr_ptr
+                       = bfd_abs_section_ptr->symbol_ptr_ptr;
+                   }
                  else
                    {
                      asymbol **ps, *s;