blob: 010e6b5d530c0f19a4bea1f8beb942d45a6c8a62 [file] [log] [blame]
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001From 0930cb3021b8078b34cf216e79eb8608d017864f Mon Sep 17 00:00:00 2001
2From: Alan Modra <amodra@gmail.com>
3Date: Sat, 13 Oct 2018 22:03:02 +1030
4Subject: [PATCH] _bfd_clear_contents bounds checking
5
6This PR shows a fuzzed binary triggering a segfault via a bad
7relocation in .debug_line. It turns out that unlike normal
8relocations applied to a section, the linker applies those with
9symbols from discarded sections via _bfd_clear_contents without
10checking that the relocation is within the section bounds. The same
11thing now happens when reading debug sections since commit
12a4cd947aca23, the PR23425 fix.
13
14 PR 23770
15 PR 23425
16 * reloc.c (_bfd_clear_contents): Replace "location" param with
17 "buf" and "off". Bounds check "off". Return status.
18 * cofflink.c (_bfd_coff_generic_relocate_section): Update
19 _bfd_clear_contents call.
20 * elf-bfd.h (RELOC_AGAINST_DISCARDED_SECTION): Likewise.
21 * elf32-arc.c (elf_arc_relocate_section): Likewise.
22 * elf32-i386.c (elf_i386_relocate_section): Likewise.
23 * elf32-metag.c (metag_final_link_relocate): Likewise.
24 * elf32-nds32.c (nds32_elf_get_relocated_section_contents): Likewise.
25 * elf32-ppc.c (ppc_elf_relocate_section): Likewise.
26 * elf32-visium.c (visium_elf_relocate_section): Likewise.
27 * elf64-ppc.c (ppc64_elf_relocate_section): Likewise.
28 * elf64-x86-64.c *(elf_x86_64_relocate_section): Likewise.
29 * libbfd-in.h (_bfd_clear_contents): Update prototype.
30 * libbfd.h: Regenerate.
31
32Upstream-Status: Backport
33CVE: CVE-2018-18605
34Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
35---
36 bfd/ChangeLog | 20 ++++++++++++++++++++
37 bfd/cofflink.c | 2 +-
38 bfd/elf-bfd.h | 2 +-
39 bfd/elf32-arc.c | 2 +-
40 bfd/elf32-i386.c | 2 +-
41 bfd/elf32-metag.c | 2 +-
42 bfd/elf32-nds32.c | 8 ++++----
43 bfd/elf32-ppc.c | 2 +-
44 bfd/elf32-visium.c | 2 +-
45 bfd/elf64-ppc.c | 2 +-
46 bfd/elf64-x86-64.c | 2 +-
47 bfd/libbfd-in.h | 4 ++--
48 bfd/libbfd.h | 4 ++--
49 bfd/reloc.c | 19 +++++++++++++------
50 14 files changed, 50 insertions(+), 23 deletions(-)
51
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080052--- a/bfd/cofflink.c
53+++ b/bfd/cofflink.c
Brad Bishop977dc1a2019-02-06 16:01:43 -050054@@ -3080,7 +3080,7 @@ _bfd_coff_generic_relocate_section (bfd
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080055 if (sec != NULL && discarded_section (sec))
56 {
57 _bfd_clear_contents (howto, input_bfd, input_section,
58- contents + (rel->r_vaddr - input_section->vma));
59+ contents, rel->r_vaddr - input_section->vma);
60 continue;
61 }
62
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080063--- a/bfd/elf-bfd.h
64+++ b/bfd/elf-bfd.h
Brad Bishop977dc1a2019-02-06 16:01:43 -050065@@ -2811,7 +2811,7 @@ extern asection _bfd_elf_large_com_secti
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080066 { \
67 int i_; \
68 _bfd_clear_contents (howto, input_bfd, input_section, \
69- contents + rel[index].r_offset); \
70+ contents, rel[index].r_offset); \
71 \
72 if (bfd_link_relocatable (info) \
73 && (input_section->flags & SEC_DEBUGGING)) \
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080074--- a/bfd/elf32-arc.c
75+++ b/bfd/elf32-arc.c
Brad Bishop977dc1a2019-02-06 16:01:43 -050076@@ -1552,7 +1552,7 @@ elf_arc_relocate_section (bfd * outp
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080077 if (sec != NULL && discarded_section (sec))
78 {
79 _bfd_clear_contents (howto, input_bfd, input_section,
80- contents + rel->r_offset);
81+ contents, rel->r_offset);
82 rel->r_info = 0;
83 rel->r_addend = 0;
84
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080085--- a/bfd/elf32-i386.c
86+++ b/bfd/elf32-i386.c
Brad Bishop977dc1a2019-02-06 16:01:43 -050087@@ -2197,7 +2197,7 @@ elf_i386_relocate_section (bfd *output_b
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080088 if (sec != NULL && discarded_section (sec))
89 {
90 _bfd_clear_contents (howto, input_bfd, input_section,
91- contents + rel->r_offset);
92+ contents, rel->r_offset);
93 wrel->r_offset = rel->r_offset;
94 wrel->r_info = 0;
95 wrel->r_addend = 0;
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080096--- a/bfd/elf32-metag.c
97+++ b/bfd/elf32-metag.c
Brad Bishop977dc1a2019-02-06 16:01:43 -050098@@ -1396,7 +1396,7 @@ metag_final_link_relocate (reloc_howto_t
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080099 rel, relend, howto, contents) \
100 { \
101 _bfd_clear_contents (howto, input_bfd, input_section, \
102- contents + rel->r_offset); \
103+ contents, rel->r_offset); \
104 \
105 if (bfd_link_relocatable (info) \
106 && (input_section->flags & SEC_DEBUGGING)) \
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800107--- a/bfd/elf32-nds32.c
108+++ b/bfd/elf32-nds32.c
Brad Bishop977dc1a2019-02-06 16:01:43 -0500109@@ -12582,14 +12582,14 @@ nds32_elf_get_relocated_section_contents
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800110 symbol = *(*parent)->sym_ptr_ptr;
111 if (symbol->section && discarded_section (symbol->section))
112 {
113- bfd_byte *p;
114+ bfd_vma off;
115 static reloc_howto_type none_howto
116 = HOWTO (0, 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL,
117 "unused", FALSE, 0, 0, FALSE);
118
119- p = data + (*parent)->address * bfd_octets_per_byte (input_bfd);
120- _bfd_clear_contents ((*parent)->howto, input_bfd, input_section,
121- p);
122+ off = (*parent)->address * bfd_octets_per_byte (input_bfd);
123+ _bfd_clear_contents ((*parent)->howto, input_bfd,
124+ input_section, data, off);
125 (*parent)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
126 (*parent)->addend = 0;
127 (*parent)->howto = &none_howto;
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800128--- a/bfd/elf32-ppc.c
129+++ b/bfd/elf32-ppc.c
Brad Bishop977dc1a2019-02-06 16:01:43 -0500130@@ -8232,7 +8232,7 @@ ppc_elf_relocate_section (bfd *output_bf
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800131 howto = ppc_elf_howto_table[r_type];
132
133 _bfd_clear_contents (howto, input_bfd, input_section,
134- contents + rel->r_offset);
135+ contents, rel->r_offset);
136 wrel->r_offset = rel->r_offset;
137 wrel->r_info = 0;
138 wrel->r_addend = 0;
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800139--- a/bfd/elf32-visium.c
140+++ b/bfd/elf32-visium.c
Brad Bishop977dc1a2019-02-06 16:01:43 -0500141@@ -621,7 +621,7 @@ visium_elf_relocate_section (bfd *output
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800142 or sections discarded by a linker script, we just want the
143 section contents zeroed. Avoid any special processing. */
144 _bfd_clear_contents (howto, input_bfd, input_section,
145- contents + rel->r_offset);
146+ contents, rel->r_offset);
147
148 rel->r_info = 0;
149 rel->r_addend = 0;
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800150--- a/bfd/elf64-ppc.c
151+++ b/bfd/elf64-ppc.c
Brad Bishop977dc1a2019-02-06 16:01:43 -0500152@@ -14074,7 +14074,7 @@ ppc64_elf_relocate_section (bfd *output_
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800153 {
154 _bfd_clear_contents (ppc64_elf_howto_table[r_type],
155 input_bfd, input_section,
156- contents + rel->r_offset);
157+ contents, rel->r_offset);
158 wrel->r_offset = rel->r_offset;
159 wrel->r_info = 0;
160 wrel->r_addend = 0;
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800161--- a/bfd/elf64-x86-64.c
162+++ b/bfd/elf64-x86-64.c
Brad Bishop977dc1a2019-02-06 16:01:43 -0500163@@ -2490,7 +2490,7 @@ elf_x86_64_relocate_section (bfd *output
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800164 if (sec != NULL && discarded_section (sec))
165 {
166 _bfd_clear_contents (howto, input_bfd, input_section,
167- contents + rel->r_offset);
168+ contents, rel->r_offset);
169 wrel->r_offset = rel->r_offset;
170 wrel->r_info = 0;
171 wrel->r_addend = 0;
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800172--- a/bfd/libbfd-in.h
173+++ b/bfd/libbfd-in.h
Brad Bishop977dc1a2019-02-06 16:01:43 -0500174@@ -696,8 +696,8 @@ extern bfd_reloc_status_type _bfd_reloca
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800175 (reloc_howto_type *, bfd *, bfd_vma, bfd_byte *) ATTRIBUTE_HIDDEN;
176
177 /* Clear a given location using a given howto. */
178-extern void _bfd_clear_contents
179- (reloc_howto_type *, bfd *, asection *, bfd_byte *) ATTRIBUTE_HIDDEN;
180+extern bfd_reloc_status_type _bfd_clear_contents
181+ (reloc_howto_type *, bfd *, asection *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN;
182
183 /* Link stabs in sections in the first pass. */
184
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800185--- a/bfd/libbfd.h
186+++ b/bfd/libbfd.h
Brad Bishop977dc1a2019-02-06 16:01:43 -0500187@@ -701,8 +701,8 @@ extern bfd_reloc_status_type _bfd_reloca
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800188 (reloc_howto_type *, bfd *, bfd_vma, bfd_byte *) ATTRIBUTE_HIDDEN;
189
190 /* Clear a given location using a given howto. */
191-extern void _bfd_clear_contents
192- (reloc_howto_type *, bfd *, asection *, bfd_byte *) ATTRIBUTE_HIDDEN;
193+extern bfd_reloc_status_type _bfd_clear_contents
194+ (reloc_howto_type *, bfd *, asection *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN;
195
196 /* Link stabs in sections in the first pass. */
197
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800198--- a/bfd/reloc.c
199+++ b/bfd/reloc.c
Brad Bishop977dc1a2019-02-06 16:01:43 -0500200@@ -1613,16 +1613,22 @@ _bfd_relocate_contents (reloc_howto_type
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800201 relocations against discarded symbols, to make ignorable debug or unwind
202 information more obvious. */
203
204-void
205+bfd_reloc_status_type
206 _bfd_clear_contents (reloc_howto_type *howto,
207 bfd *input_bfd,
208 asection *input_section,
209- bfd_byte *location)
210+ bfd_byte *buf,
211+ bfd_vma off)
212 {
213 int size;
214 bfd_vma x = 0;
215+ bfd_byte *location;
216+
217+ if (!bfd_reloc_offset_in_range (howto, input_bfd, input_section, off))
218+ return bfd_reloc_outofrange;
219
220 /* Get the value we are going to relocate. */
221+ location = buf + off;
222 size = bfd_get_reloc_size (howto);
223 switch (size)
224 {
Brad Bishop977dc1a2019-02-06 16:01:43 -0500225@@ -1681,6 +1687,7 @@ _bfd_clear_contents (reloc_howto_type *h
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800226 #endif
227 break;
228 }
229+ return bfd_reloc_ok;
230 }
231
232 /*
Brad Bishop977dc1a2019-02-06 16:01:43 -0500233@@ -8268,14 +8275,14 @@ bfd_generic_get_relocated_section_conten
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800234
235 if (symbol->section && discarded_section (symbol->section))
236 {
237- bfd_byte *p;
238+ bfd_vma off;
239 static reloc_howto_type none_howto
240 = HOWTO (0, 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL,
241 "unused", FALSE, 0, 0, FALSE);
242
243- p = data + (*parent)->address * bfd_octets_per_byte (input_bfd);
244- _bfd_clear_contents ((*parent)->howto, input_bfd, input_section,
245- p);
246+ off = (*parent)->address * bfd_octets_per_byte (input_bfd);
247+ _bfd_clear_contents ((*parent)->howto, input_bfd,
248+ input_section, data, off);
249 (*parent)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
250 (*parent)->addend = 0;
251 (*parent)->howto = &none_howto;