From cfd14a500e0485374596234de4db10e88ebc7618 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Mon, 26 Jun 2017 15:25:08 +0100 Subject: [PATCH] Fix address violations when atempting to parse fuzzed binaries. PR binutils/21665 bfd * opncls.c (get_build_id): Check that the section is beig enough to contain the whole note. * compress.c (bfd_get_full_section_contents): Check for and reject a section whoes size is greater than the size of the entire file. * elf32-v850.c (v850_elf_copy_notes): Allow for the ouput to not contain a notes section. binutils* objdump.c (disassemble_section): Skip any section that is bigger than the entire file. --- bfd/ChangeLog | 10 ++++++++++ bfd/compress.c | 6 ++++++ bfd/elf32-v850.c | 4 +++- bfd/opncls.c | 18 ++++++++++++++++-- binutils/ChangeLog | 6 ++++++ binutils/objdump.c | 4 ++-- 6 files changed, 43 insertions(+), 5 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b8624c8..8a4352f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2017-06-26 Nick Clifton + + PR binutils/21665 + * opncls.c (get_build_id): Check that the section is beig enough + to contain the whole note. + * compress.c (bfd_get_full_section_contents): Check for and reject + a section whoes size is greater than the size of the entire file. + * elf32-v850.c (v850_elf_copy_notes): Allow for the ouput to not + contain a notes section. + 2017-06-26 Andreas Krebbel * elf64-s390.c (elf_s390_additional_program_headers): Add NULL diff --git a/bfd/compress.c b/bfd/compress.c index c854a20..7b2c37c 100644 --- a/bfd/compress.c +++ b/bfd/compress.c @@ -239,6 +239,12 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) *ptr = NULL; return TRUE; } + else if (bfd_get_file_size (abfd) > 0 + && sz > (bfd_size_type) bfd_get_file_size (abfd)) + { + *ptr = NULL; + return FALSE; + } switch (sec->compress_status) { diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c index 0e9ed5f..8db7507 100644 --- a/bfd/elf32-v850.c +++ b/bfd/elf32-v850.c @@ -2450,7 +2450,9 @@ v850_elf_copy_notes (bfd *ibfd, bfd *obfd) BFD_ASSERT (bfd_malloc_and_get_section (ibfd, inotes, & icont)); if ((ocont = elf_section_data (onotes)->this_hdr.contents) == NULL) - BFD_ASSERT (bfd_malloc_and_get_section (obfd, onotes, & ocont)); + /* If the output is being stripped then it is possible for + the notes section to disappear. In this case do nothing. */ + return; /* Copy/overwrite notes from the input to the output. */ memcpy (ocont, icont, bfd_section_size (obfd, onotes)); diff --git a/bfd/opncls.c b/bfd/opncls.c index 994b950..913341c 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -1825,6 +1825,7 @@ get_build_id (bfd *abfd) Elf_External_Note *enote; bfd_byte *contents; asection *sect; + bfd_size_type size; BFD_ASSERT (abfd); @@ -1839,8 +1840,9 @@ get_build_id (bfd *abfd) return NULL; } + size = bfd_get_section_size (sect); /* FIXME: Should we support smaller build-id notes ? */ - if (bfd_get_section_size (sect) < 0x24) + if (size < 0x24) { bfd_set_error (bfd_error_invalid_operation); return NULL; @@ -1853,6 +1855,17 @@ get_build_id (bfd *abfd) return NULL; } + /* FIXME: Paranoia - allow for compressed build-id sections. + Maybe we should complain if this size is different from + the one obtained above... */ + size = bfd_get_section_size (sect); + if (size < sizeof (Elf_External_Note)) + { + bfd_set_error (bfd_error_invalid_operation); + free (contents); + return NULL; + } + enote = (Elf_External_Note *) contents; inote.type = H_GET_32 (abfd, enote->type); inote.namesz = H_GET_32 (abfd, enote->namesz); @@ -1864,7 +1877,8 @@ get_build_id (bfd *abfd) if (inote.descsz == 0 || inote.type != NT_GNU_BUILD_ID || inote.namesz != 4 /* sizeof "GNU" */ - || strcmp (inote.namedata, "GNU") != 0) + || strncmp (inote.namedata, "GNU", 4) != 0 + || size < (12 + BFD_ALIGN (inote.namesz, 4) + inote.descsz)) { free (contents); bfd_set_error (bfd_error_invalid_operation); diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 6810c22..af2a348 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,5 +1,11 @@ 2017-06-26 Nick Clifton + PR binutils/21665 + * objdump.c (disassemble_section): Skip any section that is bigger + than the entire file. + +2017-06-26 Nick Clifton + PR binutils/21659 * bucomm.c (get_file_size): Explicitly warn if the file is a directory. diff --git a/binutils/objdump.c b/binutils/objdump.c index 16e1f0e..ed8c645 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -2114,7 +2114,7 @@ disassemble_section (bfd *abfd, asection *section, void *inf) return; datasize = bfd_get_section_size (section); - if (datasize == 0) + if (datasize == 0 || datasize >= (bfd_size_type) bfd_get_file_size (abfd)) return; if (start_address == (bfd_vma) -1 @@ -2985,7 +2985,7 @@ dump_target_specific (bfd *abfd) static void dump_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED) { - bfd_byte *data = 0; + bfd_byte *data = NULL; bfd_size_type datasize; bfd_vma addr_offset; bfd_vma start_offset; -- 2.7.4