Don't use bfd_get_file_size in objdump

Compressed debug sections can have uncompressed sizes that exceed the
original file size, so we can't use bfd_get_file_size.  objdump also
used bfd_get_file_size to limit reloc section size, but I believe the
underlying bug causing the PR22508 out of bounds buffer access was
that we had an integer overflow when calculating the reloc buffer
size.  I've fixed that instead in most of the backends, som and
vms-alpha being the exceptions.  SOM and vmd-alpha have rather more
serious bugs in their slurp_relocs routines that would need fixing
first if we want to fuss about making them safe against fuzzed object
files.

The patch also fixes a number of other potential overflows by using
the bfd_alloc2/malloc2/zalloc2 memory allocation functions.

bfd/
	* coffcode.h (buy_and_read): Delete unnecessary forward decl.  Add
	nmemb parameter.  Use bfd_alloc2.
	(coff_slurp_line_table): Use bfd_alloc2.  Update buy_and_read calls.
	Delete assertion.
	(coff_slurp_symbol_table): Use bfd_alloc2 and bfd_zalloc2.
	(coff_slurp_reloc_table): Use bfd_alloc2.  Update buy_and_read calls.
	* coffgen.c (coff_get_reloc_upper_bound): Ensure size calculation
	doesn't overflow.
	* elf.c (bfd_section_from_shdr): Use bfd_zalloc2.  Style fix.
	(assign_section_numbers): Style fix.
	(swap_out_syms): Use bfd_malloc2.
	(_bfd_elf_get_reloc_upper_bound): Ensure size calculation doesn't
	overflow.
	(_bfd_elf_make_empty_symbol): Style fix.
	(elfobj_grok_stapsdt_note_1): Formatting.
	* elfcode.h (elf_object_p): Use bfd_alloc2.
	(elf_write_relocs, elf_write_shdrs_and_ehdr): Likewise.
	(elf_slurp_symbol_table): Use bfd_zalloc2.
	(elf_slurp_reloc_table): Use bfd_alloc2.
	(_bfd_elf_bfd_from_remote_memory): Use bfd_malloc2.
	* elf64-sparc (elf64_sparc_get_reloc_upper_bound): Ensure
	size calculation doesn't overflow.
	(elf64_sparc_get_dynamic_reloc_upper_bound): Likewise.
	* mach-o.c (bfd_mach_o_get_reloc_upper_bound): Likewise.
	* pdp11.c (get_reloc_upper_bound): Copy aoutx.h version.
binutils/
	* objdump.c (load_specific_debug_section): Don't compare section
	size against file size.
	(dump_relocs_in_section): Don't compare reloc size against file size.
	Print "failed to read relocs" on bfd_get_reloc_upper_bound error.
This commit is contained in:
Alan Modra
2019-03-12 16:19:25 +10:30
parent 0919bfe915
commit 7a6e0d89bb
10 changed files with 180 additions and 107 deletions

View File

@@ -503,7 +503,6 @@ elf_object_p (bfd *abfd)
unsigned int shindex;
const struct elf_backend_data *ebd;
asection *s;
bfd_size_type amt;
const bfd_target *target;
/* Read in the ELF header in external format. */
@@ -688,14 +687,14 @@ elf_object_p (bfd *abfd)
if (i_ehdrp->e_shnum > ((bfd_size_type) -1) / sizeof (*i_shdrp))
goto got_wrong_format_error;
#endif
amt = sizeof (*i_shdrp) * (bfd_size_type) i_ehdrp->e_shnum;
i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
i_shdrp = (Elf_Internal_Shdr *) bfd_alloc2 (abfd, i_ehdrp->e_shnum,
sizeof (*i_shdrp));
if (!i_shdrp)
goto got_no_match;
num_sec = i_ehdrp->e_shnum;
elf_numsections (abfd) = num_sec;
amt = sizeof (i_shdrp) * num_sec;
elf_elfsections (abfd) = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt);
elf_elfsections (abfd)
= (Elf_Internal_Shdr **) bfd_alloc2 (abfd, num_sec, sizeof (i_shdrp));
if (!elf_elfsections (abfd))
goto got_no_match;
@@ -789,8 +788,9 @@ elf_object_p (bfd *abfd)
if (bfd_get_file_size (abfd) > 0
&& i_ehdrp->e_phnum > bfd_get_file_size (abfd))
goto got_no_match;
amt = (bfd_size_type) i_ehdrp->e_phnum * sizeof (*i_phdr);
elf_tdata (abfd)->phdr = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt);
elf_tdata (abfd)->phdr
= (Elf_Internal_Phdr *) bfd_alloc2 (abfd, i_ehdrp->e_phnum,
sizeof (*i_phdr));
if (elf_tdata (abfd)->phdr == NULL)
goto got_no_match;
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
@@ -903,7 +903,8 @@ elf_write_relocs (bfd *abfd, asection *sec, void *data)
rela_hdr = elf_section_data (sec)->rel.hdr;
rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count;
rela_hdr->contents = (unsigned char *) bfd_alloc (abfd, rela_hdr->sh_size);
rela_hdr->contents = (unsigned char *) bfd_alloc2 (abfd, sec->reloc_count,
rela_hdr->sh_entsize);
if (rela_hdr->contents == NULL)
{
*failedp = TRUE;
@@ -1040,9 +1041,8 @@ elf_write_shdrs_and_ehdr (bfd *abfd)
i_shdrp[0]->sh_link = i_ehdrp->e_shstrndx;
/* at this point we've concocted all the ELF sections... */
amt = i_ehdrp->e_shnum;
amt *= sizeof (*x_shdrp);
x_shdrp = (Elf_External_Shdr *) bfd_alloc (abfd, amt);
x_shdrp = (Elf_External_Shdr *) bfd_alloc2 (abfd, i_ehdrp->e_shnum,
sizeof (*x_shdrp));
if (!x_shdrp)
return FALSE;
@@ -1053,6 +1053,7 @@ elf_write_shdrs_and_ehdr (bfd *abfd)
#endif
elf_swap_shdr_out (abfd, *i_shdrp, x_shdrp + count);
}
amt = (bfd_size_type) i_ehdrp->e_shnum * sizeof (*x_shdrp);
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0
|| bfd_bwrite (x_shdrp, amt, abfd) != amt)
return FALSE;
@@ -1152,7 +1153,6 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
Elf_External_Versym *xver;
Elf_External_Versym *xverbuf = NULL;
const struct elf_backend_data *ebd;
bfd_size_type amt;
/* Read each raw ELF symbol, converting from external ELF form to
internal ELF form, and then using the information to create a
@@ -1197,9 +1197,8 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
if (isymbuf == NULL)
return -1;
amt = symcount;
amt *= sizeof (elf_symbol_type);
symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt);
symbase = (elf_symbol_type *) bfd_zalloc2 (abfd, symcount,
sizeof (elf_symbol_type));
if (symbase == (elf_symbol_type *) NULL)
goto error_return;
@@ -1519,7 +1518,6 @@ elf_slurp_reloc_table (bfd *abfd,
bfd_size_type reloc_count;
bfd_size_type reloc_count2;
arelent *relents;
bfd_size_type amt;
if (asect->relocation != NULL)
return TRUE;
@@ -1557,8 +1555,8 @@ elf_slurp_reloc_table (bfd *abfd,
reloc_count2 = 0;
}
amt = (reloc_count + reloc_count2) * sizeof (arelent);
relents = (arelent *) bfd_alloc (abfd, amt);
relents = (arelent *) bfd_alloc2 (abfd, reloc_count + reloc_count2,
sizeof (arelent));
if (relents == NULL)
return FALSE;
@@ -1713,8 +1711,9 @@ NAME(_bfd_elf,bfd_from_remote_memory)
return NULL;
}
x_phdrs = (Elf_External_Phdr *)
bfd_malloc (i_ehdr.e_phnum * (sizeof *x_phdrs + sizeof *i_phdrs));
x_phdrs
= (Elf_External_Phdr *) bfd_malloc2 (i_ehdr.e_phnum,
sizeof (*x_phdrs) + sizeof (*i_phdrs));
if (x_phdrs == NULL)
return NULL;
err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs,