Skip to content

Commit

Permalink
Fix memory access violations triggered by running strip on fuzzed bin…
Browse files Browse the repository at this point in the history
…aries.

	PR binutils/17512
	* coffcode.h (coff_set_arch_mach_hook): Check return value from
	bfd_malloc.
	(coff_slurp_line_table): Return FALSE if the line number
	information was corrupt.
	(coff_slurp_symbol_table): Return FALSE if the symbol information
	was corrupt.
	* mach-o.c (bfd_mach_o_bfd_copy_private_header_data): Always
	initialise the fields of the dyld_info structure.
	(bfd_mach_o_build_exec_seg_command): Replace assertion with an
	error message and a return value.
	(bfd_mach_o_layout_commands): Change the function to boolean.
	Return FALSE if the function fails.
	(bfd_mach_o_build_commands): Fail if bfd_mach_o_layout_commands
	fails.
	(bfd_mach_o_read_command): Fail if an unrecognised command is
	encountered.
	* peXXigen.c (_bfd_XXi_swap_aouthdr_in): Set bfd_error if the
	read fails.
	(slurp_symtab): Check the return from bfd_malloc.
	(_bfd_XX_bfd_copy_private_bfd_data_common): Fail if the copy
	encountered an error.
	(_bfd_XXi_final_link_postscript): Fail if a section could not be
	copied.
	* peicode.h (pe_bfd_object_p): Fail if the header could not be
	swapped in.
	* tekhex.c (first_phase): Fail if the section is too big.
	* versados.c (struct esdid): Add content_size field.
	(process_otr): Use and check the new field.
	(versados_get_section_contents): Check that the section exists and
	that the requested data is available.

	PR binutils/17512
	* addr2line.c (main): Call bfd_set_error_program_name.
	* ar.c (main): Likewise.
	* coffdump.c (main): Likewise.
	* cxxfilt.c (main): Likewise.
	* dlltool.c (main): Likewise.
	* nlmconv.c (main): Likewise.
	* nm.c (main): Likewise.
	* objdump.c (main): Likewise.
	* size.c (main): Likewise.
	* srconv.c (main): Likewise.
	* strings.c (main): Likewise.
	* sysdump.c (main): Likewise.
	* windmc.c (main): Likewise.
	* windres.c (main): Likewise.
	* objcopy.c (main): Likewise.
	(copy_relocations_in_section): Check for relocs without associated
	symbol pointers.
  • Loading branch information
nickclifton committed Jan 21, 2015
1 parent ffbc464 commit 86eafac
Show file tree
Hide file tree
Showing 23 changed files with 185 additions and 38 deletions.
34 changes: 34 additions & 0 deletions bfd/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,37 @@
2015-01-21 Nick Clifton <[email protected]>

PR binutils/17512
* coffcode.h (coff_set_arch_mach_hook): Check return value from
bfd_malloc.
(coff_slurp_line_table): Return FALSE if the line number
information was corrupt.
(coff_slurp_symbol_table): Return FALSE if the symbol information
was corrupt.
* mach-o.c (bfd_mach_o_bfd_copy_private_header_data): Always
initialise the fields of the dyld_info structure.
(bfd_mach_o_build_exec_seg_command): Replace assertion with an
error message and a return value.
(bfd_mach_o_layout_commands): Change the function to boolean.
Return FALSE if the function fails.
(bfd_mach_o_build_commands): Fail if bfd_mach_o_layout_commands
fails.
(bfd_mach_o_read_command): Fail if an unrecognised command is
encountered.
* peXXigen.c (_bfd_XXi_swap_aouthdr_in): Set bfd_error if the
read fails.
(slurp_symtab): Check the return from bfd_malloc.
(_bfd_XX_bfd_copy_private_bfd_data_common): Fail if the copy
encountered an error.
(_bfd_XXi_final_link_postscript): Fail if a section could not be
copied.
* peicode.h (pe_bfd_object_p): Fail if the header could not be
swapped in.
* tekhex.c (first_phase): Fail if the section is too big.
* versados.c (struct esdid): Add content_size field.
(process_otr): Use and check the new field.
(versados_get_section_contents): Check that the section exists and
that the requested data is available.

2015-01-20 Chung-Lin Tang <[email protected]>

* elf32-nios2.c (elf_backend_default_execstack): Define as 0.
Expand Down
38 changes: 30 additions & 8 deletions bfd/coffcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -2073,10 +2073,14 @@ coff_mkobject_hook (bfd * abfd,
#endif

if ((internal_f->f_flags & F_GO32STUB) != 0)
coff->go32stub = (char *) bfd_alloc (abfd, (bfd_size_type) GO32_STUBSIZE);
{
coff->go32stub = (char *) bfd_alloc (abfd, (bfd_size_type) GO32_STUBSIZE);
if (coff->go32stub == NULL)
return NULL;
}
if (coff->go32stub != NULL)
memcpy (coff->go32stub, internal_f->go32stub, GO32_STUBSIZE);

return coff;
}
#endif
Expand Down Expand Up @@ -2278,6 +2282,8 @@ coff_set_arch_mach_hook (bfd *abfd, void * filehdr)
bfd_size_type amt = bfd_coff_symesz (abfd);

buf = bfd_malloc (amt);
if (buf == NULL)
return FALSE;
if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
|| bfd_bread (buf, amt, abfd) != amt)
{
Expand Down Expand Up @@ -2666,10 +2672,16 @@ coff_write_relocs (bfd * abfd, int first_undef)
amt = s->reloc_count;
amt *= sizeof (arelent *);
p = bfd_malloc (amt);
if (p == NULL && s->reloc_count > 0)
return FALSE;
memcpy (p, s->orelocation, (size_t) amt);
qsort (p, s->reloc_count, sizeof (arelent *), compare_arelent_ptr);
if (p == NULL)
{
if (s->reloc_count > 0)
return FALSE;
}
else
{
memcpy (p, s->orelocation, (size_t) amt);
qsort (p, s->reloc_count, sizeof (arelent *), compare_arelent_ptr);
}
}
#endif

Expand Down Expand Up @@ -4526,6 +4538,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
unsigned int nbr_func;
LINENO *src;
bfd_boolean have_func;
bfd_boolean ret = TRUE;

BFD_ASSERT (asect->lineno == NULL);

Expand Down Expand Up @@ -4575,6 +4588,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
(_("%B: warning: illegal symbol index 0x%lx in line number entry %d"),
abfd, (long) symndx, counter);
cache_ptr->line_number = -1;
ret = FALSE;
continue;
}

Expand All @@ -4587,6 +4601,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
(_("%B: warning: illegal symbol index 0x%lx in line number entry %d"),
abfd, (long) symndx, counter);
cache_ptr->line_number = -1;
ret = FALSE;
continue;
}
sym = (coff_symbol_type *) (ent->u.syment._n._n_n._n_zeroes);
Expand All @@ -4599,6 +4614,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
(_("%B: warning: illegal symbol in line number entry %d"),
abfd, counter);
cache_ptr->line_number = -1;
ret = FALSE;
continue;
}

Expand Down Expand Up @@ -4678,11 +4694,15 @@ coff_slurp_line_table (bfd *abfd, asection *asect)

memcpy (lineno_cache, n_lineno_cache, amt);
}
else
ret = FALSE;
bfd_release (abfd, func_table);
}
else
ret = FALSE;
}

return TRUE;
return ret;
}

/* Slurp in the symbol table, converting it to generic form. Note
Expand All @@ -4697,6 +4717,7 @@ coff_slurp_symbol_table (bfd * abfd)
unsigned int *table_ptr;
bfd_size_type amt;
unsigned int number_of_symbols = 0;
bfd_boolean ret = TRUE;

if (obj_symbols (abfd))
return TRUE;
Expand Down Expand Up @@ -5017,6 +5038,7 @@ coff_slurp_symbol_table (bfd * abfd)
(_("%B: Unrecognized storage class %d for %s symbol `%s'"),
abfd, src->u.syment.n_sclass,
dst->symbol.section->name, dst->symbol.name);
ret = FALSE;
case C_EXTLAB: /* External load time label. */
case C_HIDDEN: /* Ext symbol in dmert public lib. */
dst->symbol.flags = BSF_DEBUGGING;
Expand Down Expand Up @@ -5052,7 +5074,7 @@ coff_slurp_symbol_table (bfd * abfd)
}
}

return TRUE;
return ret;
}

/* Classify a COFF symbol. A couple of targets have globally visible
Expand Down
54 changes: 34 additions & 20 deletions bfd/mach-o.c
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,20 @@ bfd_mach_o_bfd_copy_private_header_data (bfd *ibfd, bfd *obfd)
ody->export_size = idy->export_size;
ody->export_content = idy->export_content;
}
/* PR 17512L: file: 730e492d. */
else
{
ody->rebase_size =
ody->bind_size =
ody->weak_bind_size =
ody->lazy_bind_size =
ody->export_size = 0;
ody->rebase_content =
ody->bind_content =
ody->weak_bind_content =
ody->lazy_bind_content =
ody->export_content = NULL;
}
}
break;

Expand Down Expand Up @@ -2764,7 +2778,14 @@ bfd_mach_o_build_exec_seg_command (bfd *abfd, bfd_mach_o_segment_command *seg)

bfd_mach_o_append_section_to_segment (seg, s);

BFD_ASSERT (s->addr >= vma);
if (s->addr < vma)
{
(*_bfd_error_handler)
(_("section address (%lx) below start of segment (%lx)"),
(unsigned long) s->addr, (unsigned long) vma);
return FALSE;
}

vma = s->addr + s->size;
}

Expand Down Expand Up @@ -2839,14 +2860,15 @@ bfd_mach_o_build_exec_seg_command (bfd *abfd, bfd_mach_o_segment_command *seg)
/* Layout the commands: set commands size and offset, set ncmds and sizeofcmds
fields in header. */

static void
static bfd_boolean
bfd_mach_o_layout_commands (bfd_mach_o_data_struct *mdata)
{
unsigned wide = mach_o_wide_p (&mdata->header);
unsigned int hdrlen;
ufile_ptr offset;
bfd_mach_o_load_command *cmd;
unsigned int align;
bfd_boolean ret = TRUE;

hdrlen = wide ? BFD_MACH_O_HEADER_64_SIZE : BFD_MACH_O_HEADER_SIZE;
align = wide ? 8 - 1 : 4 - 1;
Expand Down Expand Up @@ -2902,6 +2924,7 @@ bfd_mach_o_layout_commands (bfd_mach_o_data_struct *mdata)
(*_bfd_error_handler)
(_("unable to layout unknown load command 0x%lx"),
(unsigned long) cmd->type);
ret = FALSE;
break;
}

Expand All @@ -2910,6 +2933,8 @@ bfd_mach_o_layout_commands (bfd_mach_o_data_struct *mdata)
}
mdata->header.sizeofcmds = offset - hdrlen;
mdata->filelen = offset;

return ret;
}

/* Subroutine of bfd_mach_o_build_commands: set type, name and nsects of a
Expand Down Expand Up @@ -3044,8 +3069,7 @@ bfd_mach_o_build_commands (bfd *abfd)
if (nbr_commands == 0)
{
/* Layout commands (well none...) and set headers command fields. */
bfd_mach_o_layout_commands (mdata);
return TRUE;
return bfd_mach_o_layout_commands (mdata);
}

/* Create commands for segments (and symtabs), prepend them. */
Expand Down Expand Up @@ -3128,7 +3152,8 @@ bfd_mach_o_build_commands (bfd *abfd)
}

/* Layout commands. */
bfd_mach_o_layout_commands (mdata);
if (! bfd_mach_o_layout_commands (mdata))
return FALSE;

/* So, now we have sized the commands and the filelen set to that.
Now we can build the segment command and set the section file offsets. */
Expand Down Expand Up @@ -4687,21 +4712,10 @@ bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command)
return FALSE;
break;
default:
{
static bfd_boolean unknown_set = FALSE;
static unsigned long unknown_command = 0;

/* Prevent reams of error messages when parsing corrupt binaries. */
if (!unknown_set)
unknown_set = TRUE;
else if (command->type == unknown_command)
break;
unknown_command = command->type;

(*_bfd_error_handler)(_("%B: unknown load command 0x%lx"),
abfd, (unsigned long) command->type);
break;
}
command->len = 0;
(*_bfd_error_handler)(_("%B: unknown load command 0x%lx"),
abfd, (unsigned long) command->type);
return FALSE;
}

return TRUE;
Expand Down
20 changes: 18 additions & 2 deletions bfd/peXXigen.c
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,8 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
(*_bfd_error_handler)
(_("%B: aout header specifies an invalid number of data-directory entries: %d"),
abfd, a->NumberOfRvaAndSizes);
bfd_set_error (bfd_error_bad_value);

/* Paranoia: If the number is corrupt, then assume that the
actual entries themselves might be corrupt as well. */
a->NumberOfRvaAndSizes = 0;
Expand Down Expand Up @@ -2007,7 +2009,11 @@ slurp_symtab (bfd *abfd, sym_cache *psc)
if (storage < 0)
return NULL;
if (storage)
sy = (asymbol **) bfd_malloc (storage);
{
sy = (asymbol **) bfd_malloc (storage);
if (sy == NULL)
return NULL;
}

psc->symcount = bfd_canonicalize_symtab (abfd, sy);
if (psc->symcount < 0)
Expand Down Expand Up @@ -2963,8 +2969,16 @@ _bfd_XX_bfd_copy_private_bfd_data_common (bfd * ibfd, bfd * obfd)
}

if (!bfd_set_section_contents (obfd, section, data, 0, section->size))
_bfd_error_handler (_("Failed to update file offsets in debug directory"));
{
_bfd_error_handler (_("Failed to update file offsets in debug directory"));
return FALSE;
}
}
else if (section)
{
_bfd_error_handler (_("%A: Failed to read debug data section"), obfd);
return FALSE;
}
}

return TRUE;
Expand Down Expand Up @@ -4475,6 +4489,8 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
}
free (tmp_data);
}
else
result = FALSE;
}
}
#endif
Expand Down
3 changes: 3 additions & 0 deletions bfd/peicode.h
Original file line number Diff line number Diff line change
Expand Up @@ -1343,7 +1343,10 @@ pe_bfd_object_p (bfd * abfd)
!= (bfd_size_type) opt_hdr_size)
return NULL;

bfd_set_error (bfd_error_no_error);
bfd_coff_swap_aouthdr_in (abfd, opthdr, & internal_a);
if (bfd_get_error () != bfd_error_no_error)
return NULL;
}

return coff_real_object_p (abfd, internal_f.f_nscns, &internal_f,
Expand Down
6 changes: 6 additions & 0 deletions bfd/tekhex.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,13 @@ first_phase (bfd *abfd, int type, char *src, char * src_end)
return FALSE;
if (!getvalue (&src, &val, src_end))
return FALSE;
if (val < section->vma)
val = section->vma;
section->size = val - section->vma;
/* PR 17512: file: objdump-s-endless-loop.tekhex.
Check for overlarge section sizes. */
if (section->size & 0x80000000)
return FALSE;
section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
break;
case '0':
Expand Down
Loading

0 comments on commit 86eafac

Please sign in to comment.