Fix address violations when atempting to parse fuzzed binaries.
authorNick Clifton <nickc@redhat.com>
Mon, 26 Jun 2017 14:25:08 +0000 (15:25 +0100)
committerNick Clifton <nickc@redhat.com>
Mon, 26 Jun 2017 14:25:08 +0000 (15:25 +0100)
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
bfd/compress.c
bfd/elf32-v850.c
bfd/opncls.c
binutils/ChangeLog
binutils/objdump.c

index b8624c8..8a4352f 100644 (file)
@@ -1,3 +1,13 @@
+2017-06-26  Nick Clifton  <nickc@redhat.com>
+
+       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  <krebbel@linux.vnet.ibm.com>
 
        * elf64-s390.c (elf_s390_additional_program_headers): Add NULL
index c854a20..7b2c37c 100644 (file)
@@ -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)
     {
index 0e9ed5f..8db7507 100644 (file)
@@ -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));
index 994b950..913341c 100644 (file)
@@ -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);
index 6810c22..af2a348 100644 (file)
@@ -1,5 +1,11 @@
 2017-06-26  Nick Clifton  <nickc@redhat.com>
 
+       PR binutils/21665
+       * objdump.c (disassemble_section): Skip any section that is bigger
+       than the entire file.
+
+2017-06-26  Nick Clifton  <nickc@redhat.com>
+
        PR binutils/21659
        * bucomm.c (get_file_size): Explicitly warn if the file is a
        directory.
index 16e1f0e..ed8c645 100644 (file)
@@ -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;