aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/binutils/binutils/CVE-2017-6965.patch
blob: 1334c9444d18811c426b3b38446e7ba939b23526 (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
From bdc5166c274b842f83f8328e7cfaaf80fd29934e 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 f21867f98c..e789a3b99b 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-03-02  Tristan Gingold  <gingold@adacore.com>
 
 	* configure: Regenerate.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index b5f577f5a1..8cdaae3b8c 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -11585,6 +11585,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);
@@ -11625,13 +11626,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;
@@ -11662,13 +11669,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;
@@ -11703,12 +11715,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;
 
@@ -12325,7 +12345,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