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
|