This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Fix seg-faults when running readelf on fuzzed binaries.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d8024a9189b9e686e403512a96e4256823b5c6e4

commit d8024a9189b9e686e403512a96e4256823b5c6e4
Author: Nick Clifton <nickc@redhat.com>
Date:   Mon Aug 8 13:20:04 2016 +0100

    Fix seg-faults when running readelf on fuzzed binaries.
    
    	PR binutils/20440
    	* dwarf.c (display_debug_lines_decoded): Add checks for running
    	off the end of the section when populating the directory table and
    	file table.
    	(frame_display_row): Set max_regs equal to ncols.
    	(load_specific_debug_section): If the section is compressed, but
    	it is not big enough to hold a compression header then warn and
    	return 0.

Diff:
---
 binutils/ChangeLog |  9 +++++++++
 binutils/dwarf.c   | 31 +++++++++++++++++++++++++++----
 binutils/readelf.c | 20 +++++++++++++++++---
 3 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 2ba1bbd..d21c299 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,5 +1,14 @@
 2016-08-08  Nick Clifton  <nickc@redhat.com>
 
+	PR binutils/20440
+	* dwarf.c (display_debug_lines_decoded): Add checks for running
+	off the end of the section when populating the directory table and
+	file table.
+	(frame_display_row): Set max_regs equal to ncols.
+	(load_specific_debug_section): If the section is compressed, but
+	it is not big enough to hold a compression header then warn and
+	return 0.
+
 	PR binutils/20439
 	* dwarf.c (display_debug_lines_decoded): Check directory and file
 	indicies before using them to access directory and file tables.
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 2f2d8ae..e07f661 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -3252,16 +3252,32 @@ display_debug_lines_decoded (struct dwarf_section *section,
 
 	  /* Traverse the Directory table just to count entries.  */
 	  data = standard_opcodes + linfo.li_opcode_base - 1;
+	  /* PR 20440 */
+	  if (data >= end)
+	    {
+	      warn (_("opcode base of %d extends beyond end of section\n"),
+		    linfo.li_opcode_base);
+	      return 0;
+	    }
+
 	  if (*data != 0)
 	    {
 	      unsigned char *ptr_directory_table = data;
 
-	      while (*data != 0)
+	      while (data < end && *data != 0)
 		{
 		  data += strnlen ((char *) data, end - data) + 1;
 		  n_directories++;
 		}
 
+	      /* PR 20440 */
+	      if (data >= end)
+		{
+		  warn (_("directory table ends unexpectedly\n"));
+		  n_directories = 0;
+		  break;
+		}
+
 	      /* Go through the directory table again to save the directories.  */
 	      directory_table = (unsigned char **)
 		xmalloc (n_directories * sizeof (unsigned char *));
@@ -3279,11 +3295,11 @@ display_debug_lines_decoded (struct dwarf_section *section,
 	  data++;
 
 	  /* Traverse the File Name table just to count the entries.  */
-	  if (*data != 0)
+	  if (data < end && *data != 0)
 	    {
 	      unsigned char *ptr_file_name_table = data;
 
-	      while (*data != 0)
+	      while (data < end && *data != 0)
 		{
 		  unsigned int bytes_read;
 
@@ -3300,6 +3316,13 @@ display_debug_lines_decoded (struct dwarf_section *section,
 		  n_files++;
 		}
 
+	      if (data >= end)
+		{
+		  warn (_("file table ends unexpectedly\n"));
+		  n_files = 0;
+		  break;
+		}
+
 	      /* Go through the file table again to save the strings.  */
 	      file_table = (File_Entry *) xmalloc (n_files * sizeof (File_Entry));
 
@@ -5582,7 +5605,7 @@ frame_display_row (Frame_Chunk *fc, int *need_col_headers, unsigned int *max_reg
   unsigned int r;
   char tmp[100];
 
-  if (*max_regs < fc->ncols)
+  if (*max_regs != fc->ncols)
     *max_regs = fc->ncols;
 
   if (*need_col_headers)
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 4c7ad4c..e6674c2 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -5622,6 +5622,7 @@ get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf)
   if (is_32bit_elf)
     {
       Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) buf;
+
       chdr->ch_type = BYTE_GET (echdr->ch_type);
       chdr->ch_size = BYTE_GET (echdr->ch_size);
       chdr->ch_addralign = BYTE_GET (echdr->ch_addralign);
@@ -5630,6 +5631,7 @@ get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf)
   else
     {
       Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) buf;
+
       chdr->ch_type = BYTE_GET (echdr->ch_type);
       chdr->ch_size = BYTE_GET (echdr->ch_size);
       chdr->ch_addralign = BYTE_GET (echdr->ch_addralign);
@@ -6086,12 +6088,15 @@ process_section_headers (FILE * file)
 	      /* Minimum section size is 12 bytes for 32-bit compression
 		 header + 12 bytes for compressed data header.  */
 	      unsigned char buf[24];
+
 	      assert (sizeof (buf) >= sizeof (Elf64_External_Chdr));
 	      if (get_data (&buf, (FILE *) file, section->sh_offset, 1,
 			    sizeof (buf), _("compression header")))
 		{
 		  Elf_Internal_Chdr chdr;
-		  get_compression_header (&chdr, buf);
+
+		  (void) get_compression_header (&chdr, buf);
+
 		  if (chdr.ch_type == ELFCOMPRESS_ZLIB)
 		    printf ("       ZLIB, ");
 		  else
@@ -12573,8 +12578,17 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
       if ((sec->sh_flags & SHF_COMPRESSED) != 0)
 	{
 	  Elf_Internal_Chdr chdr;
-	  unsigned int compression_header_size
-	    = get_compression_header (&chdr, start);
+	  unsigned int compression_header_size;
+
+	  if (size < sizeof chdr)
+	    {
+	      warn (_("compressed section %s is too small to contain a compression header"),
+		    section->name);
+	      return 0;
+	    }
+
+	  compression_header_size = get_compression_header (&chdr, start);
+
 	  if (chdr.ch_type != ELFCOMPRESS_ZLIB)
 	    {
 	      warn (_("section '%s' has unsupported compress type: %d\n"),


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]