blob: 85f7f98fe049f04dcdd0cfd6567af0a30ca004e0 [file] [log] [blame]
Brad Bishop37a0e4d2017-12-04 01:01:44 -05001From 6f898c17b1d6f6a29a05ca6de31f0fc8f52cfbfe Mon Sep 17 00:00:00 2001
2From: Nick Clifton <nickc@redhat.com>
3Date: Mon, 13 Feb 2017 13:08:32 +0000
4Subject: [PATCH 1/2] Fix readelf writing to illegal addresses whilst
5 processing corrupt input files containing symbol-difference relocations.
6
7 PR binutils/21137
8 * readelf.c (target_specific_reloc_handling): Add end parameter.
9 Check for buffer overflow before writing relocated values.
10 (apply_relocations): Pass end to target_specific_reloc_handling.
11
12(cherry pick from commit 03f7786e2f440b9892b1c34a58fb26222ce1b493)
13Upstream-Status: Backport [master]
14CVE: CVE-2017-6965
15
16Signed-off-by: Yuanjie Huang <yuanjie.huang@windriver.com>
17---
18 binutils/ChangeLog | 7 +++++++
19 binutils/readelf.c | 30 +++++++++++++++++++++++++-----
20 2 files changed, 32 insertions(+), 5 deletions(-)
21
22diff --git a/binutils/ChangeLog b/binutils/ChangeLog
23index 995de87dc3..154b797a29 100644
24--- a/binutils/ChangeLog
25+++ b/binutils/ChangeLog
26@@ -5,6 +5,13 @@
27 Check for buffer overflow before writing relocated values.
28 (apply_relocations): Pass end to target_specific_reloc_handling.
29
30+2017-02-13 Nick Clifton <nickc@redhat.com>
31+
32+ PR binutils/21137
33+ * readelf.c (target_specific_reloc_handling): Add end parameter.
34+ Check for buffer overflow before writing relocated values.
35+ (apply_relocations): Pass end to target_specific_reloc_handling.
36+
37 2016-08-03 Tristan Gingold <gingold@adacore.com>
38
39 * configure: Regenerate.
40diff --git a/binutils/readelf.c b/binutils/readelf.c
41index d31558c3b4..220671f76f 100644
42--- a/binutils/readelf.c
43+++ b/binutils/readelf.c
44@@ -11345,6 +11345,7 @@ process_syminfo (FILE * file ATTRIBUTE_UNUSED)
45 static bfd_boolean
46 target_specific_reloc_handling (Elf_Internal_Rela * reloc,
47 unsigned char * start,
48+ unsigned char * end,
49 Elf_Internal_Sym * symtab)
50 {
51 unsigned int reloc_type = get_reloc_type (reloc->r_info);
52@@ -11384,13 +11385,19 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
53 handle_sym_diff:
54 if (saved_sym != NULL)
55 {
56+ int reloc_size = reloc_type == 1 ? 4 : 2;
57 bfd_vma value;
58
59 value = reloc->r_addend
60 + (symtab[get_reloc_symindex (reloc->r_info)].st_value
61 - saved_sym->st_value);
62
63- byte_put (start + reloc->r_offset, value, reloc_type == 1 ? 4 : 2);
64+ if (start + reloc->r_offset + reloc_size >= end)
65+ /* PR 21137 */
66+ error (_("MSP430 sym diff reloc writes past end of section (%p vs %p)\n"),
67+ start + reloc->r_offset + reloc_size, end);
68+ else
69+ byte_put (start + reloc->r_offset, value, reloc_size);
70
71 saved_sym = NULL;
72 return TRUE;
73@@ -11421,13 +11428,18 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
74 case 2: /* R_MN10300_16 */
75 if (saved_sym != NULL)
76 {
77+ int reloc_size = reloc_type == 1 ? 4 : 2;
78 bfd_vma value;
79
80 value = reloc->r_addend
81 + (symtab[get_reloc_symindex (reloc->r_info)].st_value
82 - saved_sym->st_value);
83
84- byte_put (start + reloc->r_offset, value, reloc_type == 1 ? 4 : 2);
85+ if (start + reloc->r_offset + reloc_size >= end)
86+ error (_("MN10300 sym diff reloc writes past end of section (%p vs %p)\n"),
87+ start + reloc->r_offset + reloc_size, end);
88+ else
89+ byte_put (start + reloc->r_offset, value, reloc_size);
90
91 saved_sym = NULL;
92 return TRUE;
93@@ -11462,12 +11474,20 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
94 break;
95
96 case 0x41: /* R_RL78_ABS32. */
97- byte_put (start + reloc->r_offset, value, 4);
98+ if (start + reloc->r_offset + 4 >= end)
99+ error (_("RL78 sym diff reloc writes past end of section (%p vs %p)\n"),
100+ start + reloc->r_offset + 2, end);
101+ else
102+ byte_put (start + reloc->r_offset, value, 4);
103 value = 0;
104 return TRUE;
105
106 case 0x43: /* R_RL78_ABS16. */
107- byte_put (start + reloc->r_offset, value, 2);
108+ if (start + reloc->r_offset + 2 >= end)
109+ error (_("RL78 sym diff reloc writes past end of section (%p vs %p)\n"),
110+ start + reloc->r_offset + 2, end);
111+ else
112+ byte_put (start + reloc->r_offset, value, 2);
113 value = 0;
114 return TRUE;
115
116@@ -12074,7 +12094,7 @@ apply_relocations (void * file,
117
118 reloc_type = get_reloc_type (rp->r_info);
119
120- if (target_specific_reloc_handling (rp, start, symtab))
121+ if (target_specific_reloc_handling (rp, start, end, symtab))
122 continue;
123 else if (is_none_reloc (reloc_type))
124 continue;
125--
1262.11.0
127