From bae7501e87ab614115d9d3213b4dd18d96e604db Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Sat, 1 Jul 2017 21:58:10 +0930
Subject: [PATCH] Use bfd_malloc_and_get_section

It's nicer than xmalloc followed by bfd_get_section_contents, since
xmalloc exits on failure and needs a check that its size_t arg doesn't
lose high bits when converted from bfd_size_type.

	PR binutils/21665
	* objdump.c (strtab): Make var a bfd_byte*.
	(disassemble_section): Don't limit malloc size.  Instead, use
	bfd_malloc_and_get_section.
	(read_section_stabs): Use bfd_malloc_and_get_section.  Return
	bfd_byte*.
	(find_stabs_section): Remove now unnecessary cast.
	* objcopy.c (copy_object): Use bfd_malloc_and_get_section.  Free
	contents on error return.
	* nlmconv.c (copy_sections): Use bfd_malloc_and_get_section.

Upstream-Status: Backport
CVE: CVE-2017-9955 #8
Signed-off-by: Armin Kuster <akuster@mvista.com>

---
 binutils/ChangeLog | 13 +++++++++++++
 binutils/nlmconv.c |  6 ++----
 binutils/objcopy.c |  5 +++--
 binutils/objdump.c | 44 +++++++-------------------------------------
 4 files changed, 25 insertions(+), 43 deletions(-)

Index: git/binutils/ChangeLog
===================================================================
--- git.orig/binutils/ChangeLog
+++ git/binutils/ChangeLog
@@ -1,3 +1,16 @@
+2017-07-01  Alan Modra  <amodra@gmail.com>
+
+	PR binutils/21665
+	* objdump.c (strtab): Make var a bfd_byte*.
+	(disassemble_section): Don't limit malloc size.  Instead, use
+	bfd_malloc_and_get_section.
+	(read_section_stabs): Use bfd_malloc_and_get_section.  Return
+	bfd_byte*.
+	(find_stabs_section): Remove now unnecessary cast.
+	* objcopy.c (copy_object): Use bfd_malloc_and_get_section.  Free
+	contents on error return.
+	* nlmconv.c (copy_sections): Use bfd_malloc_and_get_section.
+
 2017-06-30  Nick Clifton  <nickc@redhat.com>
 
        PR binutils/21665
Index: git/binutils/nlmconv.c
===================================================================
--- git.orig/binutils/nlmconv.c
+++ git/binutils/nlmconv.c
@@ -1224,7 +1224,7 @@ copy_sections (bfd *inbfd, asection *ins
   const char *inname;
   asection *outsec;
   bfd_size_type size;
-  void *contents;
+  bfd_byte *contents;
   long reloc_size;
   bfd_byte buf[4];
   bfd_size_type add;
@@ -1240,9 +1240,7 @@ copy_sections (bfd *inbfd, asection *ins
     contents = NULL;
   else
     {
-      contents = xmalloc (size);
-      if (! bfd_get_section_contents (inbfd, insec, contents,
-				      (file_ptr) 0, size))
+      if (!bfd_malloc_and_get_section (inbfd, insec, &contents))
 	bfd_fatal (bfd_get_filename (inbfd));
     }
 
Index: git/binutils/objdump.c
===================================================================
--- git.orig/binutils/objdump.c
+++ git/binutils/objdump.c
@@ -180,7 +180,7 @@ static long dynsymcount = 0;
 static bfd_byte *stabs;
 static bfd_size_type stab_size;
 
-static char *strtab;
+static bfd_byte *strtab;
 static bfd_size_type stabstr_size;
 
 static bfd_boolean is_relocatable = FALSE;
@@ -2112,29 +2112,6 @@ disassemble_section (bfd *abfd, asection
     }
   rel_ppend = rel_pp + rel_count;
 
-  /* PR 21665: Check for overlarge datasizes.
-     Note - we used to check for "datasize > bfd_get_file_size (abfd)" but
-     this fails when using compressed sections or compressed file formats
-     (eg MMO, tekhex).
-
-     The call to xmalloc below will fail if too much memory is requested,
-     which will catch the problem in the normal use case.  But if a memory
-     checker is in use, eg valgrind or sanitize, then an exception will
-     be still generated, so we try to catch the problem first.
-
-     Unfortunately there is no simple way to determine how much memory can
-     be allocated by calling xmalloc.  So instead we use a simple, arbitrary
-     limit of 2Gb.  Hopefully this should be enough for most users.  If
-     someone does start trying to disassemble sections larger then 2Gb in
-     size they will doubtless complain and we can increase the limit.  */
-#define MAX_XMALLOC (1024 * 1024 * 1024 * 2UL) /* 2Gb */
-  if (datasize > MAX_XMALLOC)
-    {
-      non_fatal (_("Reading section %s failed because it is too big (%#lx)"),
-		 section->name, (unsigned long) datasize);
-      return;
-    }
-
   data = (bfd_byte *) xmalloc (datasize);
 
   bfd_get_section_contents (abfd, section, data, 0, datasize);
@@ -2652,12 +2629,11 @@ dump_dwarf (bfd *abfd)
 /* Read ABFD's stabs section STABSECT_NAME, and return a pointer to
    it.  Return NULL on failure.   */
 
-static char *
+static bfd_byte *
 read_section_stabs (bfd *abfd, const char *sect_name, bfd_size_type *size_ptr)
 {
   asection *stabsect;
-  bfd_size_type size;
-  char *contents;
+  bfd_byte *contents;
 
   stabsect = bfd_get_section_by_name (abfd, sect_name);
   if (stabsect == NULL)
@@ -2666,10 +2642,7 @@ read_section_stabs (bfd *abfd, const cha
       return FALSE;
     }
 
-  size = bfd_section_size (abfd, stabsect);
-  contents  = (char *) xmalloc (size);
-
-  if (! bfd_get_section_contents (abfd, stabsect, contents, 0, size))
+  if (!bfd_malloc_and_get_section (abfd, stabsect, &contents))
     {
       non_fatal (_("reading %s section of %s failed: %s"),
 		 sect_name, bfd_get_filename (abfd),
@@ -2679,7 +2652,7 @@ read_section_stabs (bfd *abfd, const cha
       return NULL;
     }
 
-  *size_ptr = size;
+  *size_ptr = bfd_section_size (abfd, stabsect);
 
   return contents;
 }
@@ -2806,8 +2779,7 @@ find_stabs_section (bfd *abfd, asection
 
       if (strtab)
 	{
-	  stabs = (bfd_byte *) read_section_stabs (abfd, section->name,
-						   &stab_size);
+	  stabs = read_section_stabs (abfd, section->name, &stab_size);
 	  if (stabs)
 	    print_section_stabs (abfd, section->name, &sought->string_offset);
 	}
Index: git/binutils/objcopy.c
===================================================================
--- git.orig/binutils/objcopy.c
+++ git/binutils/objcopy.c
@@ -2186,14 +2186,15 @@ copy_object (bfd *ibfd, bfd *obfd, const
 	      continue;
 	    }
 
-	  bfd_byte * contents = xmalloc (size);
-	  if (bfd_get_section_contents (ibfd, sec, contents, 0, size))
+	  bfd_byte *contents;
+          if (bfd_malloc_and_get_section (ibfd, sec, &contents))
 	    {
 	      if (fwrite (contents, 1, size, f) != size)
 		{
 		  non_fatal (_("error writing section contents to %s (error: %s)"),
 			     pdump->filename,
 			     strerror (errno));
+                  free (contents);
 		  return FALSE;
 		}
 	    }
