| From 7296a62a2a237f6b1ad8db8c38b090e9f592c8cf Mon Sep 17 00:00:00 2001 |
| From: Nick Clifton <nickc@redhat.com> |
| 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. |
| |
| Upstream-Status: Backport |
| CVE: CVE-2017-9040 |
| CVE: CVE-2017-9042 |
| Signed-off-by: Armin Kuster <akuster@mvista.com> |
| |
| --- |
| binutils/ChangeLog | 12 ++++++++++++ |
| binutils/readelf.c | 26 +++++++++++++++++++++----- |
| 2 files changed, 33 insertions(+), 5 deletions(-) |
| |
| Index: git/binutils/readelf.c |
| =================================================================== |
| --- git.orig/binutils/readelf.c |
| +++ git/binutils/readelf.c |
| @@ -9306,6 +9306,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; |
| @@ -15175,6 +15181,15 @@ process_mips_specific (FILE * file) |
| return 0; |
| } |
| |
| + /* 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) |
| { |