[binutils-gdb] Prevent attempts to allocate excessive amounts of memory when parsing corrupt ELF files.

Nick Clifton nickc@sourceware.org
Fri Jun 28 14:31:00 GMT 2019


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

commit 7e56c51c7932cfdb178e9457011d09d53e98937b
Author: Nick Clifton <nickc@redhat.com>
Date:   Fri Jun 28 15:30:43 2019 +0100

    Prevent attempts to allocate excessive amounts of memory when parsing corrupt ELF files.
    
    	PR 24708
    	* elf.c (_bfd_elf_slurp_version_tables): Check for an excessively
    	large version reference section.
    	* compress.c (bfd_get_full_section_contents): Check for an
    	uncompressed section whose size is larger than the file size.

Diff:
---
 bfd/ChangeLog      |  8 ++++++++
 bfd/compress.c     | 17 +++++++++++++++++
 bfd/elf.c          | 12 ++++++++++++
 binutils/ChangeLog |  3 ++-
 binutils/objdump.c |  6 +++++-
 5 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 04bdb78..31d4eee 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,11 @@
+2019-06-28  Nick Clifton  <nickc@redhat.com>
+
+	PR 24708
+	* elf.c (_bfd_elf_slurp_version_tables): Check for an excessively
+	large version reference section.
+	* compress.c (bfd_get_full_section_contents): Check for an
+	uncompressed section whose size is larger than the file size.
+
 2019-06-28  Alan Modra  <amodra@gmail.com>
 
 	* format.c (bfd_check_format_matches): Don't match plugin target
diff --git a/bfd/compress.c b/bfd/compress.c
index b5db7a7..cba281d 100644
--- a/bfd/compress.c
+++ b/bfd/compress.c
@@ -250,6 +250,23 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
     case COMPRESS_SECTION_NONE:
       if (p == NULL)
 	{
+	  ufile_ptr filesize = bfd_get_file_size (abfd);
+	  if (filesize > 0
+	      && filesize < sz
+	      /* The MMO file format supports its own special compression
+		 technique, but it uses COMPRESS_SECTION_NONE when loading
+		 a section's contents.  */
+	      && bfd_get_flavour (abfd) != bfd_target_mmo_flavour)
+	    {
+	      /* PR 24708: Avoid attempts to allocate a ridiculous amount
+		 of memory.  */
+	      bfd_set_error (bfd_error_no_memory);
+	      _bfd_error_handler
+		/* xgettext:c-format */
+		(_("error: %pB(%pA) section size (%#" PRIx64 " bytes) is larger than file size (%#" PRIx64 " bytes)"),
+		 abfd, sec, (uint64_t) sz, (uint64_t) filesize);
+	      return FALSE;
+	    }
 	  p = (bfd_byte *) bfd_malloc (sz);
 	  if (p == NULL)
 	    {
diff --git a/bfd/elf.c b/bfd/elf.c
index 2094fca..75efcc6 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -8443,6 +8443,18 @@ error_return_verref:
 	  goto error_return;
 	}
 
+      ufile_ptr filesize = bfd_get_file_size (abfd);
+      if (filesize > 0 && filesize < hdr->sh_size)
+	{
+	  /* PR 24708: Avoid attempts to allocate a ridiculous amount
+	     of memory.  */
+	  bfd_set_error (bfd_error_no_memory);
+	  _bfd_error_handler
+	    /* xgettext:c-format */
+	    (_("error: %pB version reference section is too large (%#" PRIx64 " bytes)"),
+	     abfd, (uint64_t) hdr->sh_size);
+	  goto error_return_verref;
+	}
       contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
       if (contents == NULL)
 	goto error_return_verref;
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index e9f83e6..d723171 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -2,7 +2,8 @@
 
 	PR 24707
 	* objdump.c (slurp_symtab): Fail with a helpful error message if
-	the symbol table is too large.
+	the symbol table is too large.  Skip this check for MMO format
+	files.
 
 2019-06-26  Nick Clifton  <nickc@redhat.com>
 
diff --git a/binutils/objdump.c b/binutils/objdump.c
index 32e6f24..6812ba7 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -708,7 +708,11 @@ slurp_symtab (bfd *abfd)
       off_t filesize = bfd_get_file_size (abfd);
 
       /* qv PR 24707.  */
-      if (filesize > 0 && filesize < storage)
+      if (filesize > 0
+	  && filesize < storage
+	  /* The MMO file format supports its own special compression
+	     technique, so its sections can be larger than the file size.  */
+	  && bfd_get_flavour (abfd) != bfd_target_mmo_flavour)	  
 	{
 	  bfd_nonfatal_message (bfd_get_filename (abfd), abfd, NULL,
 				_("error: symbol table size (%#lx) is larger than filesize (%#lx)"),



More information about the Binutils-cvs mailing list