diff options
author | Nick Clifton <nickc@redhat.com> | 2020-03-18 12:12:07 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2020-03-18 12:12:07 +0000 |
commit | ac4bf06ca22b641b10fe37763bf57e177ee22864 (patch) | |
tree | 933fb96cda97d524f3f99982803edd1c69cdc26f /bfd/elf.c | |
parent | 53215f214c61b850085196a8d69774eed026ecd9 (diff) | |
download | binutils-gdb-ac4bf06ca22b641b10fe37763bf57e177ee22864.tar.gz |
Fix seg-fault in strip when copying a file containing corrupt secondary relocs.
PR 25673
* elf.c (_bfd_elf_write_secondary_reloc_section): Fix illegal
memory access when processing a corrupt secondary reloc section.
Diffstat (limited to 'bfd/elf.c')
-rw-r--r-- | bfd/elf.c | 131 |
1 files changed, 91 insertions, 40 deletions
diff --git a/bfd/elf.c b/bfd/elf.c index 6aaa96f83f6..d182387ed4b 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -12637,6 +12637,10 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec) bfd_vma addr_offset; asection * relsec; bfd_vma (*r_info) (bfd_vma, bfd_vma); + bfd_boolean result = TRUE; + + if (sec == NULL) + return FALSE; #if BFD_DEFAULT_TARGET_SIZE > 32 if (bfd_arch_bits_per_address (abfd) != 32) @@ -12645,9 +12649,6 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec) #endif r_info = elf32_r_info; - if (sec == NULL) - return FALSE; - /* The address of an ELF reloc is section relative for an object file, and absolute for an executable file or shared library. The address of a BFD reloc is always section relative. */ @@ -12672,10 +12673,28 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec) arelent * src_irel; bfd_byte * dst_rela; - BFD_ASSERT (hdr->contents == NULL); + if (hdr->contents != NULL) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: secondary reloc section processed twice"), + abfd, relsec); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + continue; + } reloc_count = hdr->sh_size / hdr->sh_entsize; - BFD_ASSERT (reloc_count > 0); + if (reloc_count <= 0) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: secondary reloc section is empty!"), + abfd, relsec); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + continue; + } hdr->contents = bfd_alloc (abfd, hdr->sh_size); if (hdr->contents == NULL) @@ -12689,7 +12708,16 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec) last_sym_idx = 0; dst_rela = hdr->contents; src_irel = (arelent *) esd->sec_info; - BFD_ASSERT (src_irel != NULL); + if (src_irel == NULL) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: internal relocs missing for secondary reloc section"), + abfd, relsec); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + continue; + } for (idx = 0; idx < reloc_count; idx++, dst_rela += hdr->sh_entsize) { @@ -12699,55 +12727,78 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec) int n; ptr = src_irel + idx; - sym = *ptr->sym_ptr_ptr; + if (ptr == NULL) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: reloc table entry %u is empty"), + abfd, relsec, idx); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + break; + } - if (sym == last_sym) - n = last_sym_idx; + if (ptr->sym_ptr_ptr == NULL) + { + /* FIXME: Is this an error ? */ + n = 0; + } else { - last_sym = sym; - n = _bfd_elf_symbol_from_bfd_symbol (abfd, & sym); - if (n < 0) + sym = *ptr->sym_ptr_ptr; + + if (sym == last_sym) + n = last_sym_idx; + else { -#if DEBUG_SECONDARY_RELOCS - fprintf (stderr, "failed to find symbol %s whilst rewriting relocs\n", - sym->name); -#endif - /* FIXME: Signal failure somehow. */ - n = 0; + n = _bfd_elf_symbol_from_bfd_symbol (abfd, & sym); + if (n < 0) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: secondary reloc %u references a missing symbol"), + abfd, relsec, idx); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + n = 0; + } + + last_sym = sym; + last_sym_idx = n; } - last_sym_idx = n; - } - if ((*ptr->sym_ptr_ptr)->the_bfd != NULL - && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec - && ! _bfd_elf_validate_reloc (abfd, ptr)) - { -#if DEBUG_SECONDARY_RELOCS - fprintf (stderr, "symbol %s is not in the output bfd\n", - sym->name); -#endif - /* FIXME: Signal failure somehow. */ - n = 0; + if (sym->the_bfd != NULL + && sym->the_bfd->xvec != abfd->xvec + && ! _bfd_elf_validate_reloc (abfd, ptr)) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: secondary reloc %u references a deleted symbol"), + abfd, relsec, idx); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + n = 0; + } } + src_rela.r_offset = ptr->address + addr_offset; if (ptr->howto == NULL) { -#if DEBUG_SECONDARY_RELOCS - fprintf (stderr, "reloc for symbol %s does not have a howto associated with it\n", - sym->name); -#endif - /* FIXME: Signal failure somehow. */ - n = 0; + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB(%pA): error: secondary reloc %u is of an unknown type"), + abfd, relsec, idx); + bfd_set_error (bfd_error_bad_value); + result = FALSE; + src_rela.r_info = r_info (0, 0); } - - src_rela.r_offset = ptr->address + addr_offset; - src_rela.r_info = r_info (n, ptr->howto->type); + else + src_rela.r_info = r_info (n, ptr->howto->type); src_rela.r_addend = ptr->addend; ebd->s->swap_reloca_out (abfd, &src_rela, dst_rela); } } } - return TRUE; + return result; } |