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.
This commit is contained in:
Nick Clifton
2020-03-18 12:12:07 +00:00
parent 53215f214c
commit ac4bf06ca2
2 changed files with 99 additions and 42 deletions

View File

@ -1,3 +1,9 @@
2020-03-18 Nick Clifton <nickc@redhat.com>
PR 25673
* elf.c (_bfd_elf_write_secondary_reloc_section): Fix illegal
memory access when processing a corrupt secondary reloc section.
2020-03-18 Christophe Lyon <christophe.lyon@linaro.org> 2020-03-18 Christophe Lyon <christophe.lyon@linaro.org>
* elf32-arm.c (arm_build_one_stub): Emit a fatal error message * elf32-arm.c (arm_build_one_stub): Emit a fatal error message

109
bfd/elf.c
View File

@ -12637,6 +12637,10 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec)
bfd_vma addr_offset; bfd_vma addr_offset;
asection * relsec; asection * relsec;
bfd_vma (*r_info) (bfd_vma, bfd_vma); 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_DEFAULT_TARGET_SIZE > 32
if (bfd_arch_bits_per_address (abfd) != 32) if (bfd_arch_bits_per_address (abfd) != 32)
@ -12645,9 +12649,6 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec)
#endif #endif
r_info = elf32_r_info; r_info = elf32_r_info;
if (sec == NULL)
return FALSE;
/* The address of an ELF reloc is section relative for an object /* The address of an ELF reloc is section relative for an object
file, and absolute for an executable file or shared library. file, and absolute for an executable file or shared library.
The address of a BFD reloc is always section relative. */ 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; arelent * src_irel;
bfd_byte * dst_rela; 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; 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); hdr->contents = bfd_alloc (abfd, hdr->sh_size);
if (hdr->contents == NULL) if (hdr->contents == NULL)
@ -12689,7 +12708,16 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec)
last_sym_idx = 0; last_sym_idx = 0;
dst_rela = hdr->contents; dst_rela = hdr->contents;
src_irel = (arelent *) esd->sec_info; 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) for (idx = 0; idx < reloc_count; idx++, dst_rela += hdr->sh_entsize)
{ {
@ -12699,49 +12727,72 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec)
int n; int n;
ptr = src_irel + idx; ptr = src_irel + idx;
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 (ptr->sym_ptr_ptr == NULL)
{
/* FIXME: Is this an error ? */
n = 0;
}
else
{
sym = *ptr->sym_ptr_ptr; sym = *ptr->sym_ptr_ptr;
if (sym == last_sym) if (sym == last_sym)
n = last_sym_idx; n = last_sym_idx;
else else
{ {
last_sym = sym;
n = _bfd_elf_symbol_from_bfd_symbol (abfd, & sym); n = _bfd_elf_symbol_from_bfd_symbol (abfd, & sym);
if (n < 0) if (n < 0)
{ {
#if DEBUG_SECONDARY_RELOCS _bfd_error_handler
fprintf (stderr, "failed to find symbol %s whilst rewriting relocs\n", /* xgettext:c-format */
sym->name); (_("%pB(%pA): error: secondary reloc %u references a missing symbol"),
#endif abfd, relsec, idx);
/* FIXME: Signal failure somehow. */ bfd_set_error (bfd_error_bad_value);
result = FALSE;
n = 0; n = 0;
} }
last_sym = sym;
last_sym_idx = n; last_sym_idx = n;
} }
if ((*ptr->sym_ptr_ptr)->the_bfd != NULL if (sym->the_bfd != NULL
&& (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec && sym->the_bfd->xvec != abfd->xvec
&& ! _bfd_elf_validate_reloc (abfd, ptr)) && ! _bfd_elf_validate_reloc (abfd, ptr))
{ {
#if DEBUG_SECONDARY_RELOCS _bfd_error_handler
fprintf (stderr, "symbol %s is not in the output bfd\n", /* xgettext:c-format */
sym->name); (_("%pB(%pA): error: secondary reloc %u references a deleted symbol"),
#endif abfd, relsec, idx);
/* FIXME: Signal failure somehow. */ bfd_set_error (bfd_error_bad_value);
result = FALSE;
n = 0; n = 0;
} }
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;
} }
src_rela.r_offset = ptr->address + addr_offset; src_rela.r_offset = ptr->address + addr_offset;
if (ptr->howto == NULL)
{
_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);
}
else
src_rela.r_info = r_info (n, ptr->howto->type); src_rela.r_info = r_info (n, ptr->howto->type);
src_rela.r_addend = ptr->addend; src_rela.r_addend = ptr->addend;
ebd->s->swap_reloca_out (abfd, &src_rela, dst_rela); ebd->s->swap_reloca_out (abfd, &src_rela, dst_rela);
@ -12749,5 +12800,5 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec)
} }
} }
return TRUE; return result;
} }