aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/binutils/binutils/CVE-2017-6965.patch
blob: 85f7f98fe049f04dcdd0cfd6567af0a30ca004e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
From 6f898c17b1d6f6a29a05ca6de31f0fc8f52cfbfe Mon Sep 17 00:00:00 2001
From: Nick Clifton <nickc@redhat.com>
Date: Mon, 13 Feb 2017 13:08:32 +0000
Subject: [PATCH 1/2] 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.

(cherry pick from commit 03f7786e2f440b9892b1c34a58fb26222ce1b493)
Upstream-Status: Backport [master]
CVE: CVE-2017-6965

Signed-off-by: Yuanjie Huang <yuanjie.huang@windriver.com>
---
 binutils/ChangeLog |  7 +++++++
 binutils/readelf.c | 30 +++++++++++++++++++++++++-----
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 995de87dc3..154b797a29 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -5,6 +5,13 @@
 	Check for buffer overflow before writing relocated values.
 	(apply_relocations): Pass end to target_specific_reloc_handling.
 
+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.
+
 2016-08-03  Tristan Gingold  <gingold@adacore.com>
 
 	* configure: Regenerate.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index d31558c3b4..220671f76f 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -11345,6 +11345,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);
@@ -11384,13 +11385,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;
@@ -11421,13 +11428,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;
@@ -11462,12 +11474,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;
 
@@ -12074,7 +12094,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;
-- 
2.11.0