Skip to content

Commit 86eafac

Browse files
committed
Fix memory access violations triggered by running strip on fuzzed binaries.
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.
1 parent ffbc464 commit 86eafac

23 files changed

+185
-38
lines changed

bfd/ChangeLog

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,37 @@
1+
2015-01-21 Nick Clifton <[email protected]>
2+
3+
PR binutils/17512
4+
* coffcode.h (coff_set_arch_mach_hook): Check return value from
5+
bfd_malloc.
6+
(coff_slurp_line_table): Return FALSE if the line number
7+
information was corrupt.
8+
(coff_slurp_symbol_table): Return FALSE if the symbol information
9+
was corrupt.
10+
* mach-o.c (bfd_mach_o_bfd_copy_private_header_data): Always
11+
initialise the fields of the dyld_info structure.
12+
(bfd_mach_o_build_exec_seg_command): Replace assertion with an
13+
error message and a return value.
14+
(bfd_mach_o_layout_commands): Change the function to boolean.
15+
Return FALSE if the function fails.
16+
(bfd_mach_o_build_commands): Fail if bfd_mach_o_layout_commands
17+
fails.
18+
(bfd_mach_o_read_command): Fail if an unrecognised command is
19+
encountered.
20+
* peXXigen.c (_bfd_XXi_swap_aouthdr_in): Set bfd_error if the
21+
read fails.
22+
(slurp_symtab): Check the return from bfd_malloc.
23+
(_bfd_XX_bfd_copy_private_bfd_data_common): Fail if the copy
24+
encountered an error.
25+
(_bfd_XXi_final_link_postscript): Fail if a section could not be
26+
copied.
27+
* peicode.h (pe_bfd_object_p): Fail if the header could not be
28+
swapped in.
29+
* tekhex.c (first_phase): Fail if the section is too big.
30+
* versados.c (struct esdid): Add content_size field.
31+
(process_otr): Use and check the new field.
32+
(versados_get_section_contents): Check that the section exists and
33+
that the requested data is available.
34+
135
2015-01-20 Chung-Lin Tang <[email protected]>
236

337
* elf32-nios2.c (elf_backend_default_execstack): Define as 0.

bfd/coffcode.h

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,10 +2073,14 @@ coff_mkobject_hook (bfd * abfd,
20732073
#endif
20742074

20752075
if ((internal_f->f_flags & F_GO32STUB) != 0)
2076-
coff->go32stub = (char *) bfd_alloc (abfd, (bfd_size_type) GO32_STUBSIZE);
2076+
{
2077+
coff->go32stub = (char *) bfd_alloc (abfd, (bfd_size_type) GO32_STUBSIZE);
2078+
if (coff->go32stub == NULL)
2079+
return NULL;
2080+
}
20772081
if (coff->go32stub != NULL)
20782082
memcpy (coff->go32stub, internal_f->go32stub, GO32_STUBSIZE);
2079-
2083+
20802084
return coff;
20812085
}
20822086
#endif
@@ -2278,6 +2282,8 @@ coff_set_arch_mach_hook (bfd *abfd, void * filehdr)
22782282
bfd_size_type amt = bfd_coff_symesz (abfd);
22792283

22802284
buf = bfd_malloc (amt);
2285+
if (buf == NULL)
2286+
return FALSE;
22812287
if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
22822288
|| bfd_bread (buf, amt, abfd) != amt)
22832289
{
@@ -2666,10 +2672,16 @@ coff_write_relocs (bfd * abfd, int first_undef)
26662672
amt = s->reloc_count;
26672673
amt *= sizeof (arelent *);
26682674
p = bfd_malloc (amt);
2669-
if (p == NULL && s->reloc_count > 0)
2670-
return FALSE;
2671-
memcpy (p, s->orelocation, (size_t) amt);
2672-
qsort (p, s->reloc_count, sizeof (arelent *), compare_arelent_ptr);
2675+
if (p == NULL)
2676+
{
2677+
if (s->reloc_count > 0)
2678+
return FALSE;
2679+
}
2680+
else
2681+
{
2682+
memcpy (p, s->orelocation, (size_t) amt);
2683+
qsort (p, s->reloc_count, sizeof (arelent *), compare_arelent_ptr);
2684+
}
26732685
}
26742686
#endif
26752687

@@ -4526,6 +4538,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
45264538
unsigned int nbr_func;
45274539
LINENO *src;
45284540
bfd_boolean have_func;
4541+
bfd_boolean ret = TRUE;
45294542

45304543
BFD_ASSERT (asect->lineno == NULL);
45314544

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

@@ -4587,6 +4601,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
45874601
(_("%B: warning: illegal symbol index 0x%lx in line number entry %d"),
45884602
abfd, (long) symndx, counter);
45894603
cache_ptr->line_number = -1;
4604+
ret = FALSE;
45904605
continue;
45914606
}
45924607
sym = (coff_symbol_type *) (ent->u.syment._n._n_n._n_zeroes);
@@ -4599,6 +4614,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
45994614
(_("%B: warning: illegal symbol in line number entry %d"),
46004615
abfd, counter);
46014616
cache_ptr->line_number = -1;
4617+
ret = FALSE;
46024618
continue;
46034619
}
46044620

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

46794695
memcpy (lineno_cache, n_lineno_cache, amt);
46804696
}
4697+
else
4698+
ret = FALSE;
46814699
bfd_release (abfd, func_table);
46824700
}
4701+
else
4702+
ret = FALSE;
46834703
}
46844704

4685-
return TRUE;
4705+
return ret;
46864706
}
46874707

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

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

5055-
return TRUE;
5077+
return ret;
50565078
}
50575079

50585080
/* Classify a COFF symbol. A couple of targets have globally visible

bfd/mach-o.c

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,20 @@ bfd_mach_o_bfd_copy_private_header_data (bfd *ibfd, bfd *obfd)
690690
ody->export_size = idy->export_size;
691691
ody->export_content = idy->export_content;
692692
}
693+
/* PR 17512L: file: 730e492d. */
694+
else
695+
{
696+
ody->rebase_size =
697+
ody->bind_size =
698+
ody->weak_bind_size =
699+
ody->lazy_bind_size =
700+
ody->export_size = 0;
701+
ody->rebase_content =
702+
ody->bind_content =
703+
ody->weak_bind_content =
704+
ody->lazy_bind_content =
705+
ody->export_content = NULL;
706+
}
693707
}
694708
break;
695709

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

27652779
bfd_mach_o_append_section_to_segment (seg, s);
27662780

2767-
BFD_ASSERT (s->addr >= vma);
2781+
if (s->addr < vma)
2782+
{
2783+
(*_bfd_error_handler)
2784+
(_("section address (%lx) below start of segment (%lx)"),
2785+
(unsigned long) s->addr, (unsigned long) vma);
2786+
return FALSE;
2787+
}
2788+
27682789
vma = s->addr + s->size;
27692790
}
27702791

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

2842-
static void
2863+
static bfd_boolean
28432864
bfd_mach_o_layout_commands (bfd_mach_o_data_struct *mdata)
28442865
{
28452866
unsigned wide = mach_o_wide_p (&mdata->header);
28462867
unsigned int hdrlen;
28472868
ufile_ptr offset;
28482869
bfd_mach_o_load_command *cmd;
28492870
unsigned int align;
2871+
bfd_boolean ret = TRUE;
28502872

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

@@ -2910,6 +2933,8 @@ bfd_mach_o_layout_commands (bfd_mach_o_data_struct *mdata)
29102933
}
29112934
mdata->header.sizeofcmds = offset - hdrlen;
29122935
mdata->filelen = offset;
2936+
2937+
return ret;
29132938
}
29142939

29152940
/* Subroutine of bfd_mach_o_build_commands: set type, name and nsects of a
@@ -3044,8 +3069,7 @@ bfd_mach_o_build_commands (bfd *abfd)
30443069
if (nbr_commands == 0)
30453070
{
30463071
/* Layout commands (well none...) and set headers command fields. */
3047-
bfd_mach_o_layout_commands (mdata);
3048-
return TRUE;
3072+
return bfd_mach_o_layout_commands (mdata);
30493073
}
30503074

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

31303154
/* Layout commands. */
3131-
bfd_mach_o_layout_commands (mdata);
3155+
if (! bfd_mach_o_layout_commands (mdata))
3156+
return FALSE;
31323157

31333158
/* So, now we have sized the commands and the filelen set to that.
31343159
Now we can build the segment command and set the section file offsets. */
@@ -4687,21 +4712,10 @@ bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command)
46874712
return FALSE;
46884713
break;
46894714
default:
4690-
{
4691-
static bfd_boolean unknown_set = FALSE;
4692-
static unsigned long unknown_command = 0;
4693-
4694-
/* Prevent reams of error messages when parsing corrupt binaries. */
4695-
if (!unknown_set)
4696-
unknown_set = TRUE;
4697-
else if (command->type == unknown_command)
4698-
break;
4699-
unknown_command = command->type;
4700-
4701-
(*_bfd_error_handler)(_("%B: unknown load command 0x%lx"),
4702-
abfd, (unsigned long) command->type);
4703-
break;
4704-
}
4715+
command->len = 0;
4716+
(*_bfd_error_handler)(_("%B: unknown load command 0x%lx"),
4717+
abfd, (unsigned long) command->type);
4718+
return FALSE;
47054719
}
47064720

47074721
return TRUE;

bfd/peXXigen.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,8 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
526526
(*_bfd_error_handler)
527527
(_("%B: aout header specifies an invalid number of data-directory entries: %d"),
528528
abfd, a->NumberOfRvaAndSizes);
529+
bfd_set_error (bfd_error_bad_value);
530+
529531
/* Paranoia: If the number is corrupt, then assume that the
530532
actual entries themselves might be corrupt as well. */
531533
a->NumberOfRvaAndSizes = 0;
@@ -2007,7 +2009,11 @@ slurp_symtab (bfd *abfd, sym_cache *psc)
20072009
if (storage < 0)
20082010
return NULL;
20092011
if (storage)
2010-
sy = (asymbol **) bfd_malloc (storage);
2012+
{
2013+
sy = (asymbol **) bfd_malloc (storage);
2014+
if (sy == NULL)
2015+
return NULL;
2016+
}
20112017

20122018
psc->symcount = bfd_canonicalize_symtab (abfd, sy);
20132019
if (psc->symcount < 0)
@@ -2963,8 +2969,16 @@ _bfd_XX_bfd_copy_private_bfd_data_common (bfd * ibfd, bfd * obfd)
29632969
}
29642970

29652971
if (!bfd_set_section_contents (obfd, section, data, 0, section->size))
2966-
_bfd_error_handler (_("Failed to update file offsets in debug directory"));
2972+
{
2973+
_bfd_error_handler (_("Failed to update file offsets in debug directory"));
2974+
return FALSE;
2975+
}
29672976
}
2977+
else if (section)
2978+
{
2979+
_bfd_error_handler (_("%A: Failed to read debug data section"), obfd);
2980+
return FALSE;
2981+
}
29682982
}
29692983

29702984
return TRUE;
@@ -4475,6 +4489,8 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
44754489
}
44764490
free (tmp_data);
44774491
}
4492+
else
4493+
result = FALSE;
44784494
}
44794495
}
44804496
#endif

bfd/peicode.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,7 +1343,10 @@ pe_bfd_object_p (bfd * abfd)
13431343
!= (bfd_size_type) opt_hdr_size)
13441344
return NULL;
13451345

1346+
bfd_set_error (bfd_error_no_error);
13461347
bfd_coff_swap_aouthdr_in (abfd, opthdr, & internal_a);
1348+
if (bfd_get_error () != bfd_error_no_error)
1349+
return NULL;
13471350
}
13481351

13491352
return coff_real_object_p (abfd, internal_f.f_nscns, &internal_f,

bfd/tekhex.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,13 @@ first_phase (bfd *abfd, int type, char *src, char * src_end)
407407
return FALSE;
408408
if (!getvalue (&src, &val, src_end))
409409
return FALSE;
410+
if (val < section->vma)
411+
val = section->vma;
410412
section->size = val - section->vma;
413+
/* PR 17512: file: objdump-s-endless-loop.tekhex.
414+
Check for overlarge section sizes. */
415+
if (section->size & 0x80000000)
416+
return FALSE;
411417
section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
412418
break;
413419
case '0':

0 commit comments

Comments
 (0)