From 7296a62a2a237f6b1ad8db8c38b090e9f592c8cf Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Thu, 13 Apr 2017 16:06:30 +0100 Subject: [PATCH] readelf: fix out of range subtraction, seg fault from a NULL pointer and memory exhaustion, all from parsing corrupt binaries. PR binutils/21379 * readelf.c (process_dynamic_section): Detect over large section offsets in the DT_SYMTAB entry. PR binutils/21345 * readelf.c (process_mips_specific): Catch an unfeasible memory allocation before it happens and print a suitable error message. --- binutils/ChangeLog | 12 ++++++++++++ binutils/readelf.c | 26 +++++++++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index ae734c4bbe5..5f75c170fa8 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,15 @@ +2017-04-13 Nick Clifton + + PR binutils/21379 + * readelf.c (process_dynamic_section): Detect over large section + offsets in the DT_SYMTAB entry. + +2017-04-13 Nick Clifton + + PR binutils/21345 + * readelf.c (process_mips_specific): Catch an unfeasible memory + allocation before it happens and print a suitable error message. + 2017-04-13 Nick Clifton * objcopy.c: Add --no-merge-notes option to disable note merging. diff --git a/binutils/readelf.c b/binutils/readelf.c index 93b94023659..ab53473b433 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -9436,6 +9436,12 @@ process_dynamic_section (FILE * file) processing that. This is overkill, I know, but it should work. */ section.sh_offset = offset_from_vma (file, entry->d_un.d_val, 0); + if ((bfd_size_type) section.sh_offset > current_file_size) + { + /* See PR 21379 for a reproducer. */ + error (_("Invalid DT_SYMTAB entry: %lx"), (long) section.sh_offset); + return FALSE; + } if (archive_file_offset != 0) section.sh_size = archive_file_size - section.sh_offset; @@ -15370,6 +15376,15 @@ process_mips_specific (FILE * file) return FALSE; } + /* PR 21345 - print a slightly more helpful error message + if we are sure that the cmalloc will fail. */ + if (conflictsno * sizeof (* iconf) > current_file_size) + { + error (_("Overlarge number of conflicts detected: %lx\n"), + (long) conflictsno); + return FALSE; + } + iconf = (Elf32_Conflict *) cmalloc (conflictsno, sizeof (* iconf)); if (iconf == NULL) { @@ -16656,10 +16671,11 @@ print_symbol_for_build_attribute (FILE * file, static unsigned long strtablen; static Elf_Internal_Sym * symtab; static unsigned long nsyms; - Elf_Internal_Sym * saved_sym = NULL; - Elf_Internal_Sym * sym; + Elf_Internal_Sym * saved_sym = NULL; + Elf_Internal_Sym * sym; - if (saved_file == NULL || file != saved_file) + if (section_headers != NULL + && (saved_file == NULL || file != saved_file)) { Elf_Internal_Shdr * symsec; @@ -16822,7 +16838,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote) if (name == NULL || pnote->namesz < 2) { error (_("corrupt name field in GNU build attribute note: size = %ld\n"), pnote->namesz); - print_symbol (-20, _(" ")); + print_symbol (-20, _(" ")); return FALSE; } @@ -17452,7 +17468,7 @@ process_arch_specific (FILE * file) return process_mips_specific (file); case EM_MSP430: - return process_attributes (file, "mspabi", SHT_MSP430_ATTRIBUTES, + return process_attributes (file, "mspabi", SHT_MSP430_ATTRIBUTES, display_msp430x_attribute, display_generic_attribute); -- 2.30.2