From 75e100a30d5dfdd3ac2b0391c17173645fc77633 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 12 Aug 2020 20:18:43 +0930 Subject: [PATCH] PR26348, Malloc error in write_zeros This adds a few more sanity checks on ELF objects, and a BFD flag to disable objcopy and strip when fuzzed input files belong in the "too hard" basket. bfd/ PR 26348 * bfd.c (struct bfd): Add read_only. * elfcode.h (elf_swap_shdr_in): Test both sh_offset and sh_size. Set read_only on warning. (elf_object_p): Sanity check program header alignment. Set read_only on warning. * bfd-in2.h: Regenerate. binutils/ PR 26348 * objcopy.c (copy_object): Report file name with endian error. Error and return on abfd->read_only. --- bfd/ChangeLog | 10 ++++++++++ bfd/bfd-in2.h | 4 ++++ bfd/bfd.c | 4 ++++ bfd/elfcode.h | 22 +++++++++++++++++----- binutils/ChangeLog | 6 ++++++ binutils/objcopy.c | 10 +++++++++- 6 files changed, 50 insertions(+), 6 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a2342588e80..0e22506e022 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2020-08-13 Alan Modra + + PR 26348 + * bfd.c (struct bfd): Add read_only. + * elfcode.h (elf_swap_shdr_in): Test both sh_offset and sh_size. + Set read_only on warning. + (elf_object_p): Sanity check program header alignment. Set + read_only on warning. + * bfd-in2.h: Regenerate. + 2020-08-12 Jon Turney * elf.c (elfcore_grok_win32pstatus): Use unsigned int for diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 35ef4d755bb..94d3195836a 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -6678,6 +6678,10 @@ struct bfd /* Set if this is a slim LTO object not loaded with a compiler plugin. */ unsigned int lto_slim_object : 1; + /* Do not attempt to modify this file. Set when detecting errors + that BFD is not prepared to handle for objcopy/strip. */ + unsigned int read_only : 1; + /* Set to dummy BFD created when claimed by a compiler plug-in library. */ bfd *plugin_dummy_bfd; diff --git a/bfd/bfd.c b/bfd/bfd.c index 538bdfa5d7d..ec38a0673c7 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -245,6 +245,10 @@ CODE_FRAGMENT . {* Set if this is a slim LTO object not loaded with a compiler plugin. *} . unsigned int lto_slim_object : 1; . +. {* Do not attempt to modify this file. Set when detecting errors +. that BFD is not prepared to handle for objcopy/strip. *} +. unsigned int read_only : 1; +. . {* Set to dummy BFD created when claimed by a compiler plug-in . library. *} . bfd *plugin_dummy_bfd; diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 2e2c5343f2c..84b08b57ebc 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -321,11 +321,14 @@ elf_swap_shdr_in (bfd *abfd, { ufile_ptr filesize = bfd_get_file_size (abfd); - if (filesize != 0 && dst->sh_size > filesize) - _bfd_error_handler - (_("warning: %pB has a corrupt section with a size (%" - BFD_VMA_FMT "x) larger than the file size"), - abfd, dst->sh_size); + if (filesize != 0 + && ((ufile_ptr) dst->sh_offset > filesize + || dst->sh_size > filesize - dst->sh_offset)) + { + abfd->read_only = 1; + _bfd_error_handler (_("warning: %pB has a section " + "extending past end of file"), abfd); + } } dst->sh_link = H_GET_32 (abfd, src->sh_link); dst->sh_info = H_GET_32 (abfd, src->sh_info); @@ -764,6 +767,7 @@ elf_object_p (bfd *abfd) So we are kind, and reset the string index value to 0 so that at least some processing can be done. */ i_ehdrp->e_shstrndx = SHN_UNDEF; + abfd->read_only = 1; _bfd_error_handler (_("warning: %pB has a corrupt string table index - ignoring"), abfd); @@ -804,6 +808,14 @@ elf_object_p (bfd *abfd) if (bfd_bread (&x_phdr, sizeof x_phdr, abfd) != sizeof x_phdr) goto got_no_match; elf_swap_phdr_in (abfd, &x_phdr, i_phdr); + /* Too much code in BFD relies on alignment being a power of + two, as required by the ELF spec. */ + if (i_phdr->p_align != (i_phdr->p_align & -i_phdr->p_align)) + { + abfd->read_only = 1; + _bfd_error_handler (_("warning: %pB has a program header " + "with invalid alignment"), abfd); + } } } diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 5037d91e0dd..0006ad1740f 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2020-08-13 Alan Modra + + PR 26348 + * objcopy.c (copy_object): Report file name with endian error. + Error and return on abfd->read_only. + 2020-08-12 Tom Tromey * dwarf-mode.el (Version): Now 1.6. diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 3866c7f4588..c5af179b17e 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -2604,7 +2604,15 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) { /* PR 17636: Call non-fatal so that we return to our parent who may need to tidy temporary files. */ - non_fatal (_("Unable to change endianness of input file(s)")); + non_fatal (_("unable to change endianness of '%s'"), + bfd_get_archive_filename (ibfd)); + return FALSE; + } + + if (ibfd->read_only) + { + non_fatal (_("unable to modify '%s' due to errors"), + bfd_get_archive_filename (ibfd)); return FALSE; } -- 2.30.2