From 9ccfa98b4cbc86ac34734ecf9d35466461c7e34c Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 9 Apr 2018 13:42:00 +0100 Subject: [PATCH] MIPS64/BFD: Fix a crash with invalid `r_sym' in relocation 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=, reloc_count=1, relents=, 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"), , and commit 05a487dc8c39 ("make check fails on i686-linux-gnu"), , 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 | 5 +++++ bfd/elf64-mips.c | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 8df416ff3c..d65d5a8a92 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2018-04-09 Maciej W. Rozycki + + * elf64-mips.c (mips_elf64_slurp_one_reloc_table): Issue an + error for out-of-range `r_sym' values. + 2018-04-09 Alan Modra * elf64-ppc.c (struct _ppc64_elf_section_data): Add has_pltcall field. diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c index 115047f32c..86e55897cf 100644 --- a/bfd/elf64-mips.c +++ b/bfd/elf64-mips.c @@ -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;