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 readelf writing to illegal addresses whilst processing corrupt input files containing symbol-dif


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

commit 03f7786e2f440b9892b1c34a58fb26222ce1b493
Author: Nick Clifton <nickc@redhat.com>
Date:   Mon Feb 13 13:08:32 2017 +0000

    Fix readelf writing to illegal addresses whilst processing corrupt input files containing symbol-difference relocations.
    
    	PR binutils/21137
    	* readelf.c (target_specific_reloc_handling): Add end parameter.
    	Check for buffer overflow before writing relocated values.
    	(apply_relocations): Pass end to target_specific_reloc_handling.

Diff:
---
 binutils/ChangeLog |  7 +++++++
 binutils/readelf.c | 30 +++++++++++++++++++++++++-----
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index a734433..6480c8f 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,10 @@
+2017-02-13  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/21137
+	* readelf.c (target_specific_reloc_handling): Add end parameter.
+	Check for buffer overflow before writing relocated values.
+	(apply_relocations): Pass end to target_specific_reloc_handling.
+
 2017-01-27  Dilyan Palauzov  <dilyan.palauzov@aegee.org>
 	    Nick Clifton  <nickc@redhat.com>
 
diff --git a/binutils/readelf.c b/binutils/readelf.c
index b488714..e474f27 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -11591,6 +11591,7 @@ process_syminfo (FILE * file ATTRIBUTE_UNUSED)
 static bfd_boolean
 target_specific_reloc_handling (Elf_Internal_Rela * reloc,
 				unsigned char *     start,
+				unsigned char *     end,
 				Elf_Internal_Sym *  symtab)
 {
   unsigned int reloc_type = get_reloc_type (reloc->r_info);
@@ -11631,13 +11632,19 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
 	  handle_sym_diff:
 	    if (saved_sym != NULL)
 	      {
+		int reloc_size = reloc_type == 1 ? 4 : 2;
 		bfd_vma value;
 
 		value = reloc->r_addend
 		  + (symtab[get_reloc_symindex (reloc->r_info)].st_value
 		     - saved_sym->st_value);
 
-		byte_put (start + reloc->r_offset, value, reloc_type == 1 ? 4 : 2);
+		if (start + reloc->r_offset + reloc_size >= end)
+		  /* PR 21137 */
+		  error (_("MSP430 sym diff reloc writes past end of section (%p vs %p)\n"),
+			 start + reloc->r_offset + reloc_size, end);
+		else
+		  byte_put (start + reloc->r_offset, value, reloc_size);
 
 		saved_sym = NULL;
 		return TRUE;
@@ -11668,13 +11675,18 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
 	  case 2: /* R_MN10300_16 */
 	    if (saved_sym != NULL)
 	      {
+		int reloc_size = reloc_type == 1 ? 4 : 2;
 		bfd_vma value;
 
 		value = reloc->r_addend
 		  + (symtab[get_reloc_symindex (reloc->r_info)].st_value
 		     - saved_sym->st_value);
 
-		byte_put (start + reloc->r_offset, value, reloc_type == 1 ? 4 : 2);
+		if (start + reloc->r_offset + reloc_size >= end)
+		  error (_("MN10300 sym diff reloc writes past end of section (%p vs %p)\n"),
+			 start + reloc->r_offset + reloc_size, end);
+		else
+		  byte_put (start + reloc->r_offset, value, reloc_size);
 
 		saved_sym = NULL;
 		return TRUE;
@@ -11709,12 +11721,20 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
 	    break;
 
 	  case 0x41: /* R_RL78_ABS32.  */
-	    byte_put (start + reloc->r_offset, value, 4);
+	    if (start + reloc->r_offset + 4 >= end)
+	      error (_("RL78 sym diff reloc writes past end of section (%p vs %p)\n"),
+		     start + reloc->r_offset + 2, end);
+	    else
+	      byte_put (start + reloc->r_offset, value, 4);
 	    value = 0;
 	    return TRUE;
 
 	  case 0x43: /* R_RL78_ABS16.  */
-	    byte_put (start + reloc->r_offset, value, 2);
+	    if (start + reloc->r_offset + 2 >= end)
+	      error (_("RL78 sym diff reloc writes past end of section (%p vs %p)\n"),
+		     start + reloc->r_offset + 2, end);
+	    else
+	      byte_put (start + reloc->r_offset, value, 2);
 	    value = 0;
 	    return TRUE;
 
@@ -12340,7 +12360,7 @@ apply_relocations (void *                     file,
 
 	  reloc_type = get_reloc_type (rp->r_info);
 
-	  if (target_specific_reloc_handling (rp, start, symtab))
+	  if (target_specific_reloc_handling (rp, start, end, symtab))
 	    continue;
 	  else if (is_none_reloc (reloc_type))
 	    continue;


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