summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarish Sadineni <Harish.Sadineni@windriver.com>2025-05-21 08:02:13 -0700
committerSteve Sakoman <steve@sakoman.com>2025-06-02 07:12:34 -0700
commit186e2b2b0540a091cdc3b0646eedafa8646c575a (patch)
treef59d3aba3e170d1818723714a13caa9b95010273
parent53ab80ae8f0394f7a57ae144076ac0c1c97e9002 (diff)
downloadpoky-186e2b2b0540a091cdc3b0646eedafa8646c575a.tar.gz
binutils: Fix CVE-2025-1179
CVE-2025-1179-pre.patch is dependency patch for CVE-2025-1179.patch Upstream-Status: Submitted [https://sourceware.org/pipermail/binutils/2025-May/141322.html && https://sourceware.org/pipermail/binutils/2025-May/141321.html] CVE: CVE-2025-1179 cherry picked from upstream commit: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=67e30b15212adc1502b898a1ca224fdf65dc110d https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1d68a49ac5d71b648304f69af978fce0f4413800 (From OE-Core rev: 8f54548f784ef60eaf7fb6b3f539d48b0f7192a3) Signed-off-by: Harish Sadineni <Harish.Sadineni@windriver.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r--meta/recipes-devtools/binutils/binutils-2.42.inc2
-rw-r--r--meta/recipes-devtools/binutils/binutils/CVE-2025-1179-pre.patch1086
-rw-r--r--meta/recipes-devtools/binutils/binutils/CVE-2025-1179.patch269
3 files changed, 1357 insertions, 0 deletions
diff --git a/meta/recipes-devtools/binutils/binutils-2.42.inc b/meta/recipes-devtools/binutils/binutils-2.42.inc
index bc826753cf..6d0390b5a9 100644
--- a/meta/recipes-devtools/binutils/binutils-2.42.inc
+++ b/meta/recipes-devtools/binutils/binutils-2.42.inc
@@ -48,5 +48,7 @@ SRC_URI = "\
48 file://0019-CVE-2025-1153-1.patch \ 48 file://0019-CVE-2025-1153-1.patch \
49 file://0020-CVE-2025-1153-2.patch \ 49 file://0020-CVE-2025-1153-2.patch \
50 file://0021-CVE-2025-1153-3.patch \ 50 file://0021-CVE-2025-1153-3.patch \
51 file://CVE-2025-1179-pre.patch \
52 file://CVE-2025-1179.patch \
51" 53"
52S = "${WORKDIR}/git" 54S = "${WORKDIR}/git"
diff --git a/meta/recipes-devtools/binutils/binutils/CVE-2025-1179-pre.patch b/meta/recipes-devtools/binutils/binutils/CVE-2025-1179-pre.patch
new file mode 100644
index 0000000000..b5bf27ec6d
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/CVE-2025-1179-pre.patch
@@ -0,0 +1,1086 @@
1From 1d68a49ac5d71b648304f69af978fce0f4413800 Mon Sep 17 00:00:00 2001
2From: "H.J. Lu" <hjl.tools@gmail.com>
3Date: Tue, 23 Jul 2024 23:39:50 -0700
4Subject: [PATCH 1/2] x86: Improve TLS transition error check
5
6Provide detailed TLS transition errors when unsupported instructions are
7used. Treat R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_6_GOTTPOFF as
8R_X86_64_GOTTPOFF when performing TLS transition.
9
10bfd/
11
12 PR ld/32017
13 * elf32-i386.c (elf_i386_check_tls_transition): Return different
14 enums for different errors.
15 (elf_i386_tls_transition): Change argument from r_symndx to sym.
16 Call _bfd_x86_elf_link_report_tls_transition_error to report TLS
17 transition errors.
18 (elf_i386_scan_relocs): Pass isym instead of r_symndx to
19 elf_i386_tls_transition.
20 (elf_i386_relocate_section): Pass sym instead of r_symndx to
21 elf_i386_tls_transition.
22 * elf64-x86-64.c (elf_x86_64_check_tls_transition): Return
23 different enums for different errors.
24 (elf_x86_64_tls_transition): Change argument from r_symndx to sym.
25 Treat R_X86_64_CODE_4_GOTTPOFF and R_X86_64_CODE_6_GOTTPOFF as
26 R_X86_64_GOTTPOFF. Call
27 _bfd_x86_elf_link_report_tls_transition_error to report TLS
28 transition errors.
29 (elf_x86_64_scan_relocs): Pass isym instead of r_symndx to
30 elf_x86_64_tls_transition.
31 (elf_x86_64_relocate_section): Pass sym instead of r_symndx to
32 elf_x86_64_tls_transition.
33 * elfxx-x86.c (_bfd_x86_elf_link_report_tls_transition_error): New.
34 * elfxx-x86.h (elf_x86_tls_error_type): Likewise.
35 (_bfd_x86_elf_link_report_tls_transition_error): Likewise.
36
37ld/
38
39 PR ld/32017
40 * testsuite/ld-i386/i386.exp: Run tlsgdesc1 and tlsgdesc2.
41 * testsuite/ld-i386/tlsie2.d: Updated.
42 * testsuite/ld-i386/tlsie3.d: Likewise.
43 * testsuite/ld-i386/tlsie4.d: Likewise.
44 * testsuite/ld-i386/tlsie5.d: Likewise.
45 * testsuite/ld-x86-64/tlsie2.d: Likewise.
46 * testsuite/ld-x86-64/tlsie3.d: Likewise.
47 * testsuite/ld-i386/tlsgdesc1.d: New file.
48 * testsuite/ld-i386/tlsgdesc1.s: Likewise.
49 * testsuite/ld-i386/tlsgdesc2.d: Likewise.
50 * testsuite/ld-i386/tlsgdesc2.s: Likewise.
51 * testsuite/ld-x86-64/tlsdesc3.d: Likewise.
52 * testsuite/ld-x86-64/tlsdesc3.s: Likewise.
53 * testsuite/ld-x86-64/tlsdesc4.d: Likewise.
54 * testsuite/ld-x86-64/tlsdesc4.s: Likewise.
55 * testsuite/ld-x86-64/tlsie5.d: Likewise.
56 * testsuite/ld-x86-64/tlsie5.s: Likewise.
57 * testsuite/ld-x86-64/x86-64.exp: Run tlsie5, tlsdesc3 and
58 tlsdesc4.
59
60(cherry picked from commit:1d68a49ac5d71b648304f69af978fce0f4413800)
61Upstream-Status: Submitted [https://sourceware.org/pipermail/binutils/2025-May/141322.html]
62CVE: CVE-2025-1179
63
64Signed-off-by: Harish Sadineni <Harish.Sadineni@windriver.com>
65---
66 bfd/elf32-i386.c | 118 +++++++++++++-------------
67 bfd/elf64-x86-64.c | 133 ++++++++++++++++--------------
68 bfd/elfxx-x86.c | 85 +++++++++++++++++++
69 bfd/elfxx-x86.h | 18 ++++
70 ld/testsuite/ld-i386/i386.exp | 2 +
71 ld/testsuite/ld-i386/tlsgdesc1.d | 4 +
72 ld/testsuite/ld-i386/tlsgdesc1.s | 11 +++
73 ld/testsuite/ld-i386/tlsgdesc2.d | 4 +
74 ld/testsuite/ld-i386/tlsgdesc2.s | 11 +++
75 ld/testsuite/ld-i386/tlsie2.d | 2 +-
76 ld/testsuite/ld-i386/tlsie3.d | 2 +-
77 ld/testsuite/ld-i386/tlsie4.d | 2 +-
78 ld/testsuite/ld-i386/tlsie5.d | 2 +-
79 ld/testsuite/ld-x86-64/tlsdesc3.d | 4 +
80 ld/testsuite/ld-x86-64/tlsdesc3.s | 13 +++
81 ld/testsuite/ld-x86-64/tlsdesc4.d | 4 +
82 ld/testsuite/ld-x86-64/tlsdesc4.s | 13 +++
83 ld/testsuite/ld-x86-64/tlsie2.d | 2 +-
84 ld/testsuite/ld-x86-64/tlsie3.d | 2 +-
85 ld/testsuite/ld-x86-64/tlsie5.d | 4 +
86 ld/testsuite/ld-x86-64/tlsie5.s | 12 +++
87 ld/testsuite/ld-x86-64/x86-64.exp | 3 +
88 22 files changed, 319 insertions(+), 132 deletions(-)
89 create mode 100644 ld/testsuite/ld-i386/tlsgdesc1.d
90 create mode 100644 ld/testsuite/ld-i386/tlsgdesc1.s
91 create mode 100644 ld/testsuite/ld-i386/tlsgdesc2.d
92 create mode 100644 ld/testsuite/ld-i386/tlsgdesc2.s
93 create mode 100644 ld/testsuite/ld-x86-64/tlsdesc3.d
94 create mode 100644 ld/testsuite/ld-x86-64/tlsdesc3.s
95 create mode 100644 ld/testsuite/ld-x86-64/tlsdesc4.d
96 create mode 100644 ld/testsuite/ld-x86-64/tlsdesc4.s
97 create mode 100644 ld/testsuite/ld-x86-64/tlsie5.d
98 create mode 100644 ld/testsuite/ld-x86-64/tlsie5.s
99
100diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
101index e2f88a11487..18a28d2491c 100644
102--- a/bfd/elf32-i386.c
103+++ b/bfd/elf32-i386.c
104@@ -839,7 +839,7 @@ static const struct elf_x86_non_lazy_plt_layout elf_i386_non_lazy_ibt_plt =
105 /* Return TRUE if the TLS access code sequence support transition
106 from R_TYPE. */
107
108-static bool
109+static enum elf_x86_tls_error_type
110 elf_i386_check_tls_transition (asection *sec,
111 bfd_byte *contents,
112 Elf_Internal_Shdr *symtab_hdr,
113@@ -861,7 +861,7 @@ elf_i386_check_tls_transition (asection *sec,
114 case R_386_TLS_GD:
115 case R_386_TLS_LDM:
116 if (offset < 2 || (rel + 1) >= relend)
117- return false;
118+ return elf_x86_tls_error_yes;
119
120 indirect_call = false;
121 call = contents + offset + 4;
122@@ -884,19 +884,19 @@ elf_i386_check_tls_transition (asection *sec,
123 can transit to different access model. */
124 if ((offset + 10) > sec->size
125 || (type != 0x8d && type != 0x04))
126- return false;
127+ return elf_x86_tls_error_yes;
128
129 if (type == 0x04)
130 {
131 /* leal foo@tlsgd(,%ebx,1), %eax
132 call ___tls_get_addr@PLT */
133 if (offset < 3)
134- return false;
135+ return elf_x86_tls_error_yes;
136
137 if (*(call - 7) != 0x8d
138 || val != 0x1d
139 || call[0] != 0xe8)
140- return false;
141+ return elf_x86_tls_error_yes;
142 }
143 else
144 {
145@@ -914,7 +914,7 @@ elf_i386_check_tls_transition (asection *sec,
146 is used to pass parameter to ___tls_get_addr. */
147 reg = val & 7;
148 if ((val & 0xf8) != 0x80 || reg == 4 || reg == 0)
149- return false;
150+ return elf_x86_tls_error_yes;
151
152 indirect_call = call[0] == 0xff;
153 if (!(reg == 3 && call[0] == 0xe8 && call[5] == 0x90)
154@@ -922,7 +922,7 @@ elf_i386_check_tls_transition (asection *sec,
155 && !(indirect_call
156 && (call[1] & 0xf8) == 0x90
157 && (call[1] & 0x7) == reg))
158- return false;
159+ return elf_x86_tls_error_yes;
160 }
161 }
162 else
163@@ -937,13 +937,13 @@ elf_i386_check_tls_transition (asection *sec,
164 addr32 call ___tls_get_addr
165 can transit to different access model. */
166 if (type != 0x8d || (offset + 9) > sec->size)
167- return false;
168+ return elf_x86_tls_error_yes;
169
170 /* %eax can't be used as the GOT base register since it is
171 used to pass parameter to ___tls_get_addr. */
172 reg = val & 7;
173 if ((val & 0xf8) != 0x80 || reg == 4 || reg == 0)
174- return false;
175+ return elf_x86_tls_error_yes;
176
177 indirect_call = call[0] == 0xff;
178 if (!(reg == 3 && call[0] == 0xe8)
179@@ -951,23 +951,27 @@ elf_i386_check_tls_transition (asection *sec,
180 && !(indirect_call
181 && (call[1] & 0xf8) == 0x90
182 && (call[1] & 0x7) == reg))
183- return false;
184+ return elf_x86_tls_error_yes;
185 }
186
187 r_symndx = ELF32_R_SYM (rel[1].r_info);
188 if (r_symndx < symtab_hdr->sh_info)
189- return false;
190+ return elf_x86_tls_error_yes;
191
192 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
193 if (h == NULL
194 || !((struct elf_x86_link_hash_entry *) h)->tls_get_addr)
195- return false;
196+ return elf_x86_tls_error_yes;
197 else if (indirect_call)
198- return (ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32X
199- || ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32);
200+ return ((ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32X
201+ || ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32)
202+ ? elf_x86_tls_error_none
203+ : elf_x86_tls_error_yes);
204 else
205- return (ELF32_R_TYPE (rel[1].r_info) == R_386_PC32
206- || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
207+ return ((ELF32_R_TYPE (rel[1].r_info) == R_386_PC32
208+ || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32)
209+ ? elf_x86_tls_error_none
210+ : elf_x86_tls_error_yes);
211
212 case R_386_TLS_IE:
213 /* Check transition from IE access model:
214@@ -977,20 +981,23 @@ elf_i386_check_tls_transition (asection *sec,
215 */
216
217 if (offset < 1 || (offset + 4) > sec->size)
218- return false;
219+ return elf_x86_tls_error_yes;
220
221 /* Check "movl foo@tpoff(%rip), %eax" first. */
222 val = bfd_get_8 (abfd, contents + offset - 1);
223 if (val == 0xa1)
224- return true;
225+ return elf_x86_tls_error_none;
226
227 if (offset < 2)
228- return false;
229+ return elf_x86_tls_error_yes;
230
231 /* Check movl|addl foo@tpoff(%rip), %reg. */
232 type = bfd_get_8 (abfd, contents + offset - 2);
233- return ((type == 0x8b || type == 0x03)
234- && (val & 0xc7) == 0x05);
235+ if (type != 0x8b && type != 0x03)
236+ return elf_x86_tls_error_add_mov;
237+ return ((val & 0xc7) == 0x05
238+ ? elf_x86_tls_error_none
239+ : elf_x86_tls_error_yes);
240
241 case R_386_TLS_GOTIE:
242 case R_386_TLS_IE_32:
243@@ -1001,14 +1008,16 @@ elf_i386_check_tls_transition (asection *sec,
244 */
245
246 if (offset < 2 || (offset + 4) > sec->size)
247- return false;
248+ return elf_x86_tls_error_yes;
249
250 val = bfd_get_8 (abfd, contents + offset - 1);
251 if ((val & 0xc0) != 0x80 || (val & 7) == 4)
252- return false;
253+ return elf_x86_tls_error_yes;
254
255 type = bfd_get_8 (abfd, contents + offset - 2);
256- return type == 0x8b || type == 0x2b || type == 0x03;
257+ return (type == 0x8b || type == 0x2b || type == 0x03
258+ ? elf_x86_tls_error_none
259+ : elf_x86_tls_error_add_sub_mov);
260
261 case R_386_TLS_GOTDESC:
262 /* Check transition from GDesc access model:
263@@ -1019,13 +1028,15 @@ elf_i386_check_tls_transition (asection *sec,
264 going to be eax. */
265
266 if (offset < 2 || (offset + 4) > sec->size)
267- return false;
268+ return elf_x86_tls_error_yes;
269
270 if (bfd_get_8 (abfd, contents + offset - 2) != 0x8d)
271- return false;
272+ return elf_x86_tls_error_lea;
273
274 val = bfd_get_8 (abfd, contents + offset - 1);
275- return (val & 0xc7) == 0x83;
276+ return ((val & 0xc7) == 0x83
277+ ? elf_x86_tls_error_none
278+ : elf_x86_tls_error_yes);
279
280 case R_386_TLS_DESC_CALL:
281 /* Check transition from GDesc access model:
282@@ -1035,10 +1046,12 @@ elf_i386_check_tls_transition (asection *sec,
283 {
284 /* Make sure that it's a call *x@tlsdesc(%eax). */
285 call = contents + offset;
286- return call[0] == 0xff && call[1] == 0x10;
287+ return (call[0] == 0xff && call[1] == 0x10
288+ ? elf_x86_tls_error_none
289+ : elf_x86_tls_error_indirect_call);
290 }
291
292- return false;
293+ return elf_x86_tls_error_yes;
294
295 default:
296 abort ();
297@@ -1057,7 +1070,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
298 const Elf_Internal_Rela *rel,
299 const Elf_Internal_Rela *relend,
300 struct elf_link_hash_entry *h,
301- unsigned long r_symndx,
302+ Elf_Internal_Sym *sym,
303 bool from_relocate_section)
304 {
305 unsigned int from_type = *r_type;
306@@ -1142,43 +1155,24 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
307 return true;
308
309 /* Check if the transition can be performed. */
310+ enum elf_x86_tls_error_type tls_error;
311 if (check
312- && ! elf_i386_check_tls_transition (sec, contents,
313- symtab_hdr, sym_hashes,
314- from_type, rel, relend))
315+ && ((tls_error = elf_i386_check_tls_transition (sec, contents,
316+ symtab_hdr,
317+ sym_hashes,
318+ from_type, rel,
319+ relend))
320+ != elf_x86_tls_error_none))
321 {
322 reloc_howto_type *from, *to;
323- const char *name;
324
325 from = elf_i386_rtype_to_howto (from_type);
326 to = elf_i386_rtype_to_howto (to_type);
327
328- if (h)
329- name = h->root.root.string;
330- else
331- {
332- struct elf_x86_link_hash_table *htab;
333-
334- htab = elf_x86_hash_table (info, I386_ELF_DATA);
335- if (htab == NULL)
336- name = "*unknown*";
337- else
338- {
339- Elf_Internal_Sym *isym;
340-
341- isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
342- abfd, r_symndx);
343- name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
344- }
345- }
346+ _bfd_x86_elf_link_report_tls_transition_error
347+ (info, abfd, sec, symtab_hdr, h, sym, rel, from->name,
348+ to->name, tls_error);
349
350- _bfd_error_handler
351- /* xgettext:c-format */
352- (_("%pB: TLS transition from %s to %s against `%s'"
353- " at %#" PRIx64 " in section `%pA' failed"),
354- abfd, from->name, to->name, name,
355- (uint64_t) rel->r_offset, sec);
356- bfd_set_error (bfd_error_bad_value);
357 return false;
358 }
359
360@@ -1600,7 +1594,7 @@ elf_i386_scan_relocs (bfd *abfd,
361 if (! elf_i386_tls_transition (info, abfd, sec, contents,
362 symtab_hdr, sym_hashes,
363 &r_type, GOT_UNKNOWN,
364- rel, rel_end, h, r_symndx, false))
365+ rel, rel_end, h, isym, false))
366 goto error_return;
367
368 /* Check if _GLOBAL_OFFSET_TABLE_ is referenced. */
369@@ -2875,7 +2869,7 @@ elf_i386_relocate_section (bfd *output_bfd,
370 input_section, contents,
371 symtab_hdr, sym_hashes,
372 &r_type_tls, tls_type, rel,
373- relend, h, r_symndx, true))
374+ relend, h, sym, true))
375 return false;
376
377 expected_tls_le = htab->elf.target_os == is_solaris
378@@ -3365,7 +3359,7 @@ elf_i386_relocate_section (bfd *output_bfd,
379 input_section, contents,
380 symtab_hdr, sym_hashes,
381 &r_type, GOT_UNKNOWN, rel,
382- relend, h, r_symndx, true))
383+ relend, h, sym, true))
384 return false;
385
386 if (r_type != R_386_TLS_LDM)
387diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
388index 2ed120af780..f116e423f61 100644
389--- a/bfd/elf64-x86-64.c
390+++ b/bfd/elf64-x86-64.c
391@@ -1120,7 +1120,7 @@ elf32_x86_64_elf_object_p (bfd *abfd)
392 /* Return TRUE if the TLS access code sequence support transition
393 from R_TYPE. */
394
395-static bool
396+static enum elf_x86_tls_error_type
397 elf_x86_64_check_tls_transition (bfd *abfd,
398 struct bfd_link_info *info,
399 asection *sec,
400@@ -1147,7 +1147,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
401 case R_X86_64_TLSGD:
402 case R_X86_64_TLSLD:
403 if ((rel + 1) >= relend)
404- return false;
405+ return elf_x86_tls_error_yes;
406
407 if (r_type == R_X86_64_TLSGD)
408 {
409@@ -1184,7 +1184,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
410 static const unsigned char leaq[] = { 0x66, 0x48, 0x8d, 0x3d };
411
412 if ((offset + 12) > sec->size)
413- return false;
414+ return elf_x86_tls_error_yes;
415
416 call = contents + offset + 4;
417 if (call[0] != 0x66
418@@ -1208,20 +1208,20 @@ elf_x86_64_check_tls_transition (bfd *abfd,
419 || call[14] != 0xd0
420 || !((call[10] == 0x48 && call[12] == 0xd8)
421 || (call[10] == 0x4c && call[12] == 0xf8)))
422- return false;
423+ return elf_x86_tls_error_yes;
424 largepic = true;
425 }
426 else if (ABI_64_P (abfd))
427 {
428 if (offset < 4
429 || memcmp (contents + offset - 4, leaq, 4) != 0)
430- return false;
431+ return elf_x86_tls_error_yes;
432 }
433 else
434 {
435 if (offset < 3
436 || memcmp (contents + offset - 3, leaq + 1, 3) != 0)
437- return false;
438+ return elf_x86_tls_error_yes;
439 }
440 indirect_call = call[2] == 0xff;
441 }
442@@ -1250,10 +1250,10 @@ elf_x86_64_check_tls_transition (bfd *abfd,
443 static const unsigned char lea[] = { 0x48, 0x8d, 0x3d };
444
445 if (offset < 3 || (offset + 9) > sec->size)
446- return false;
447+ return elf_x86_tls_error_yes;
448
449 if (memcmp (contents + offset - 3, lea, 3) != 0)
450- return false;
451+ return elf_x86_tls_error_yes;
452
453 call = contents + offset + 4;
454 if (!(call[0] == 0xe8
455@@ -1268,7 +1268,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
456 || call[14] != 0xd0
457 || !((call[10] == 0x48 && call[12] == 0xd8)
458 || (call[10] == 0x4c && call[12] == 0xf8)))
459- return false;
460+ return elf_x86_tls_error_yes;
461 largepic = true;
462 }
463 indirect_call = call[0] == 0xff;
464@@ -1276,22 +1276,30 @@ elf_x86_64_check_tls_transition (bfd *abfd,
465
466 r_symndx = htab->r_sym (rel[1].r_info);
467 if (r_symndx < symtab_hdr->sh_info)
468- return false;
469+ return elf_x86_tls_error_yes;
470
471 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
472 if (h == NULL
473 || !((struct elf_x86_link_hash_entry *) h)->tls_get_addr)
474- return false;
475+ return elf_x86_tls_error_yes;
476 else
477 {
478 r_type = (ELF32_R_TYPE (rel[1].r_info)
479 & ~R_X86_64_converted_reloc_bit);
480 if (largepic)
481- return r_type == R_X86_64_PLTOFF64;
482+ return (r_type == R_X86_64_PLTOFF64
483+ ? elf_x86_tls_error_none
484+ : elf_x86_tls_error_yes);
485 else if (indirect_call)
486- return (r_type == R_X86_64_GOTPCRELX || r_type == R_X86_64_GOTPCREL);
487+ return ((r_type == R_X86_64_GOTPCRELX
488+ || r_type == R_X86_64_GOTPCREL)
489+ ? elf_x86_tls_error_none
490+ : elf_x86_tls_error_yes);
491 else
492- return (r_type == R_X86_64_PC32 || r_type == R_X86_64_PLT32);
493+ return ((r_type == R_X86_64_PC32
494+ || r_type == R_X86_64_PLT32)
495+ ? elf_x86_tls_error_none
496+ : elf_x86_tls_error_yes);
497 }
498
499 case R_X86_64_CODE_4_GOTTPOFF:
500@@ -1303,7 +1311,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
501 if (offset < 4
502 || (offset + 4) > sec->size
503 || contents[offset - 4] != 0xd5)
504- return false;
505+ return elf_x86_tls_error_yes;
506
507 goto check_gottpoff;
508
509@@ -1315,14 +1323,16 @@ elf_x86_64_check_tls_transition (bfd *abfd,
510 if (offset < 6
511 || (offset + 4) > sec->size
512 || contents[offset - 6] != 0x62)
513- return false;
514+ return elf_x86_tls_error_yes;
515
516 val = bfd_get_8 (abfd, contents + offset - 2);
517 if (val != 0x01 && val != 0x03)
518- return false;
519+ return elf_x86_tls_error_add;
520
521 val = bfd_get_8 (abfd, contents + offset - 1);
522- return (val & 0xc7) == 5;
523+ return ((val & 0xc7) == 5
524+ ? elf_x86_tls_error_none
525+ : elf_x86_tls_error_yes);
526
527 case R_X86_64_GOTTPOFF:
528 /* Check transition from IE access model:
529@@ -1338,25 +1348,27 @@ elf_x86_64_check_tls_transition (bfd *abfd,
530 {
531 /* X32 may have 0x44 REX prefix or no REX prefix. */
532 if (ABI_64_P (abfd))
533- return false;
534+ return elf_x86_tls_error_yes;
535 }
536 }
537 else
538 {
539 /* X32 may not have any REX prefix. */
540 if (ABI_64_P (abfd))
541- return false;
542+ return elf_x86_tls_error_yes;
543 if (offset < 2 || (offset + 3) > sec->size)
544- return false;
545+ return elf_x86_tls_error_yes;
546 }
547
548 check_gottpoff:
549 val = bfd_get_8 (abfd, contents + offset - 2);
550 if (val != 0x8b && val != 0x03)
551- return false;
552+ return elf_x86_tls_error_add_mov;
553
554 val = bfd_get_8 (abfd, contents + offset - 1);
555- return (val & 0xc7) == 5;
556+ return ((val & 0xc7) == 5
557+ ? elf_x86_tls_error_none
558+ : elf_x86_tls_error_yes);
559
560 case R_X86_64_CODE_4_GOTPC32_TLSDESC:
561 /* Check transition from GDesc access model:
562@@ -1366,7 +1378,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
563 if (offset < 4
564 || (offset + 4) > sec->size
565 || contents[offset - 4] != 0xd5)
566- return false;
567+ return elf_x86_tls_error_yes;
568
569 goto check_tlsdesc;
570
571@@ -1380,19 +1392,21 @@ elf_x86_64_check_tls_transition (bfd *abfd,
572 going to be rax. */
573
574 if (offset < 3 || (offset + 4) > sec->size)
575- return false;
576+ return elf_x86_tls_error_yes;
577
578 val = bfd_get_8 (abfd, contents + offset - 3);
579 val &= 0xfb;
580 if (val != 0x48 && (ABI_64_P (abfd) || val != 0x40))
581- return false;
582+ return elf_x86_tls_error_yes;
583
584 check_tlsdesc:
585 if (bfd_get_8 (abfd, contents + offset - 2) != 0x8d)
586- return false;
587+ return elf_x86_tls_error_lea;
588
589 val = bfd_get_8 (abfd, contents + offset - 1);
590- return (val & 0xc7) == 0x05;
591+ return ((val & 0xc7) == 0x05
592+ ? elf_x86_tls_error_none
593+ : elf_x86_tls_error_yes);
594
595 case R_X86_64_TLSDESC_CALL:
596 /* Check transition from GDesc access model:
597@@ -1411,14 +1425,16 @@ elf_x86_64_check_tls_transition (bfd *abfd,
598 {
599 prefix = 1;
600 if (offset + 3 > sec->size)
601- return false;
602+ return elf_x86_tls_error_yes;
603 }
604 }
605 /* Make sure that it's a call *x@tlsdesc(%rax). */
606- return call[prefix] == 0xff && call[1 + prefix] == 0x10;
607+ return (call[prefix] == 0xff && call[1 + prefix] == 0x10
608+ ? elf_x86_tls_error_none
609+ : elf_x86_tls_error_indirect_call);
610 }
611
612- return false;
613+ return elf_x86_tls_error_yes;
614
615 default:
616 abort ();
617@@ -1437,7 +1453,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
618 const Elf_Internal_Rela *rel,
619 const Elf_Internal_Rela *relend,
620 struct elf_link_hash_entry *h,
621- unsigned long r_symndx,
622+ Elf_Internal_Sym *sym,
623 bool from_relocate_section)
624 {
625 unsigned int from_type = *r_type;
626@@ -1488,7 +1504,12 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
627 /* We checked the transition before when we were called from
628 elf_x86_64_scan_relocs. We only want to check the new
629 transition which hasn't been checked before. */
630- check = new_to_type != to_type && from_type == to_type;
631+ check = (new_to_type != to_type
632+ && (from_type == to_type
633+ || (from_type == R_X86_64_CODE_4_GOTTPOFF
634+ && to_type == R_X86_64_GOTTPOFF)
635+ || (from_type == R_X86_64_CODE_6_GOTTPOFF
636+ && to_type == R_X86_64_GOTTPOFF)));
637 to_type = new_to_type;
638 }
639
640@@ -1512,13 +1533,18 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
641 return true;
642
643 /* Check if the transition can be performed. */
644+ enum elf_x86_tls_error_type tls_error;
645 if (check
646- && ! elf_x86_64_check_tls_transition (abfd, info, sec, contents,
647- symtab_hdr, sym_hashes,
648- from_type, rel, relend))
649+ && ((tls_error = elf_x86_64_check_tls_transition (abfd, info, sec,
650+ contents,
651+ symtab_hdr,
652+ sym_hashes,
653+ from_type, rel,
654+ relend))
655+ != elf_x86_tls_error_none))
656+
657 {
658 reloc_howto_type *from, *to;
659- const char *name;
660
661 from = elf_x86_64_rtype_to_howto (abfd, from_type);
662 to = elf_x86_64_rtype_to_howto (abfd, to_type);
663@@ -1526,31 +1552,10 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
664 if (from == NULL || to == NULL)
665 return false;
666
667- if (h)
668- name = h->root.root.string;
669- else
670- {
671- struct elf_x86_link_hash_table *htab;
672-
673- htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
674- if (htab == NULL)
675- name = "*unknown*";
676- else
677- {
678- Elf_Internal_Sym *isym;
679+ _bfd_x86_elf_link_report_tls_transition_error
680+ (info, abfd, sec, symtab_hdr, h, sym, rel, from->name,
681+ to->name, tls_error);
682
683- isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
684- abfd, r_symndx);
685- name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
686- }
687- }
688-
689- _bfd_error_handler
690- /* xgettext:c-format */
691- (_("%pB: TLS transition from %s to %s against `%s' at %#" PRIx64
692- " in section `%pA' failed"),
693- abfd, from->name, to->name, name, (uint64_t) rel->r_offset, sec);
694- bfd_set_error (bfd_error_bad_value);
695 return false;
696 }
697
698@@ -2198,7 +2203,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
699 if (! elf_x86_64_tls_transition (info, abfd, sec, contents,
700 symtab_hdr, sym_hashes,
701 &r_type, GOT_UNKNOWN,
702- rel, rel_end, h, r_symndx, false))
703+ rel, rel_end, h, isym, false))
704 goto error_return;
705
706 /* Check if _GLOBAL_OFFSET_TABLE_ is referenced. */
707@@ -3648,7 +3653,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
708 input_section, contents,
709 symtab_hdr, sym_hashes,
710 &r_type_tls, tls_type, rel,
711- relend, h, r_symndx, true))
712+ relend, h, sym, true))
713 return false;
714
715 if (r_type_tls == R_X86_64_TPOFF32)
716@@ -4308,7 +4313,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
717 input_section, contents,
718 symtab_hdr, sym_hashes,
719 &r_type, GOT_UNKNOWN, rel,
720- relend, h, r_symndx, true))
721+ relend, h, sym, true))
722 return false;
723
724 if (r_type != R_X86_64_TLSLD)
725diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
726index 508fd771da3..b17dad759c8 100644
727--- a/bfd/elfxx-x86.c
728+++ b/bfd/elfxx-x86.c
729@@ -3202,6 +3202,91 @@ _bfd_x86_elf_link_report_relative_reloc
730 asect, abfd);
731 }
732
733+/* Report TLS transition error. */
734+
735+void
736+_bfd_x86_elf_link_report_tls_transition_error
737+ (struct bfd_link_info *info, bfd *abfd, asection *asect,
738+ Elf_Internal_Shdr *symtab_hdr, struct elf_link_hash_entry *h,
739+ Elf_Internal_Sym *sym, const Elf_Internal_Rela *rel,
740+ const char *from_reloc_name, const char *to_reloc_name,
741+ enum elf_x86_tls_error_type tls_error)
742+{
743+ const char *name;
744+
745+ if (h)
746+ name = h->root.root.string;
747+ else
748+ {
749+ const struct elf_backend_data *bed
750+ = get_elf_backend_data (abfd);
751+ struct elf_x86_link_hash_table *htab
752+ = elf_x86_hash_table (info, bed->target_id);
753+ if (htab == NULL)
754+ name = "*unknown*";
755+ else
756+ name = bfd_elf_sym_name (abfd, symtab_hdr, sym, NULL);
757+ }
758+
759+ switch (tls_error)
760+ {
761+ case elf_x86_tls_error_yes:
762+ info->callbacks->einfo
763+ /* xgettext:c-format */
764+ (_("%pB: TLS transition from %s to %s against `%s' at 0x%v in "
765+ "section `%pA' failed"),
766+ abfd, from_reloc_name, to_reloc_name, name, rel->r_offset,
767+ asect);
768+ break;
769+
770+ case elf_x86_tls_error_add:
771+ info->callbacks->einfo
772+ /* xgettext:c-format */
773+ (_("%pB(%pA+0x%v): relocation %s against `%s' must be used "
774+ "in ADD only"),
775+ abfd, asect, rel->r_offset, from_reloc_name, name);
776+ break;
777+
778+ case elf_x86_tls_error_add_mov:
779+ info->callbacks->einfo
780+ /* xgettext:c-format */
781+ (_("%pB(%pA+0x%v): relocation %s against `%s' must be used "
782+ "in ADD or MOV only"),
783+ abfd, asect, rel->r_offset, from_reloc_name, name);
784+ break;
785+
786+ case elf_x86_tls_error_add_sub_mov:
787+ info->callbacks->einfo
788+ /* xgettext:c-format */
789+ (_("%pB(%pA+0x%v): relocation %s against `%s' must be used "
790+ "in ADD, SUB or MOV only"),
791+ abfd, asect, rel->r_offset, from_reloc_name, name);
792+ break;
793+
794+ case elf_x86_tls_error_indirect_call:
795+ info->callbacks->einfo
796+ /* xgettext:c-format */
797+ (_("%pB(%pA+0x%v): relocation %s against `%s' must be used "
798+ "in indirect CALL only"),
799+ abfd, asect, rel->r_offset, from_reloc_name, name);
800+ break;
801+
802+ case elf_x86_tls_error_lea:
803+ info->callbacks->einfo
804+ /* xgettext:c-format */
805+ (_("%pB(%pA+0x%v): relocation %s against `%s' must be used "
806+ "in LEA only"),
807+ abfd, asect, rel->r_offset, from_reloc_name, name);
808+ break;
809+
810+ default:
811+ abort ();
812+ break;
813+ }
814+
815+ bfd_set_error (bfd_error_bad_value);
816+}
817+
818 /* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
819
820 bool
821diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
822index 110bcb9ad71..02e2efa6c56 100644
823--- a/bfd/elfxx-x86.h
824+++ b/bfd/elfxx-x86.h
825@@ -767,6 +767,18 @@ struct elf_x86_plt
826 long count;
827 };
828
829+enum elf_x86_tls_error_type
830+{
831+ elf_x86_tls_error_none,
832+ elf_x86_tls_error_add,
833+ elf_x86_tls_error_add_mov,
834+ elf_x86_tls_error_add_sub_mov,
835+ elf_x86_tls_error_indirect_call,
836+ elf_x86_tls_error_lea,
837+ elf_x86_tls_error_yes
838+};
839+
840+
841 /* Set if a relocation is converted from a GOTPCREL relocation. */
842 #define R_X86_64_converted_reloc_bit (1 << 7)
843
844@@ -908,6 +920,12 @@ extern void _bfd_x86_elf_link_fixup_ifunc_symbol
845 extern void _bfd_x86_elf_link_report_relative_reloc
846 (struct bfd_link_info *, asection *, struct elf_link_hash_entry *,
847 Elf_Internal_Sym *, const char *, const void *);
848+extern void _bfd_x86_elf_link_report_tls_transition_error
849+ (struct bfd_link_info *, bfd *, asection *, Elf_Internal_Shdr *,
850+ struct elf_link_hash_entry *, Elf_Internal_Sym *,
851+ const Elf_Internal_Rela *, const char *, const char *,
852+ enum elf_x86_tls_error_type);
853+
854
855 #define bfd_elf64_mkobject \
856 _bfd_x86_elf_mkobject
857diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
858index 18d1c9198ca..a8db2c713f3 100644
859--- a/ld/testsuite/ld-i386/i386.exp
860+++ b/ld/testsuite/ld-i386/i386.exp
861@@ -541,6 +541,8 @@ run_dump_test "tlsdesc2"
862 run_dump_test "report-reloc-1"
863 run_dump_test "pr27998a"
864 run_dump_test "pr27998b"
865+run_dump_test "tlsgdesc1"
866+run_dump_test "tlsgdesc2"
867
868 proc undefined_weak {cflags ldflags} {
869 set testname "Undefined weak symbol"
870diff --git a/ld/testsuite/ld-i386/tlsgdesc1.d b/ld/testsuite/ld-i386/tlsgdesc1.d
871new file mode 100644
872index 00000000000..2a70e81c444
873--- /dev/null
874+++ b/ld/testsuite/ld-i386/tlsgdesc1.d
875@@ -0,0 +1,4 @@
876+#name: TLS GDesc->LE transition check (LEA)
877+#as: --32
878+#ld: -melf_i386
879+#error: .*: relocation R_386_TLS_GOTDESC against `foo' must be used in LEA only
880diff --git a/ld/testsuite/ld-i386/tlsgdesc1.s b/ld/testsuite/ld-i386/tlsgdesc1.s
881new file mode 100644
882index 00000000000..c30f7523462
883--- /dev/null
884+++ b/ld/testsuite/ld-i386/tlsgdesc1.s
885@@ -0,0 +1,11 @@
886+ .text
887+ .globl _start
888+_start:
889+ movl foo@tlsdesc(%ebx), %eax
890+ call *foo@tlscall(%eax)
891+ .section .tdata,"awT",@progbits
892+ .align 4
893+ .type foo, @object
894+ .size foo, 4
895+foo:
896+ .long 100
897diff --git a/ld/testsuite/ld-i386/tlsgdesc2.d b/ld/testsuite/ld-i386/tlsgdesc2.d
898new file mode 100644
899index 00000000000..2e6a66d372c
900--- /dev/null
901+++ b/ld/testsuite/ld-i386/tlsgdesc2.d
902@@ -0,0 +1,4 @@
903+#name: TLS GDesc->LE transition check (indirect CALL)
904+#as: --32
905+#ld: -melf_i386
906+#error: .*: relocation R_386_TLS_DESC_CALL against `foo' must be used in indirect CALL only
907diff --git a/ld/testsuite/ld-i386/tlsgdesc2.s b/ld/testsuite/ld-i386/tlsgdesc2.s
908new file mode 100644
909index 00000000000..7d9d556e2ab
910--- /dev/null
911+++ b/ld/testsuite/ld-i386/tlsgdesc2.s
912@@ -0,0 +1,11 @@
913+ .text
914+ .globl _start
915+_start:
916+ leal foo@tlsdesc(%ebx), %eax
917+ jmp *foo@tlscall(%eax)
918+ .section .tdata,"awT",@progbits
919+ .align 4
920+ .type foo, @object
921+ .size foo, 4
922+foo:
923+ .long 100
924diff --git a/ld/testsuite/ld-i386/tlsie2.d b/ld/testsuite/ld-i386/tlsie2.d
925index ebb85fde7e7..9f9e63029d6 100644
926--- a/ld/testsuite/ld-i386/tlsie2.d
927+++ b/ld/testsuite/ld-i386/tlsie2.d
928@@ -1,4 +1,4 @@
929 #name: TLS IE->LE transition check (R_386_TLS_GOTIE with %eax)
930 #as: --32
931 #ld: -melf_i386
932-#error: .*TLS transition from R_386_TLS_GOTIE to R_386_TLS_LE_32 against `foo'.*failed.*
933+#error: .*: relocation R_386_TLS_GOTIE against `foo' must be used in ADD, SUB or MOV only
934diff --git a/ld/testsuite/ld-i386/tlsie3.d b/ld/testsuite/ld-i386/tlsie3.d
935index d993f303c25..506f1a02605 100644
936--- a/ld/testsuite/ld-i386/tlsie3.d
937+++ b/ld/testsuite/ld-i386/tlsie3.d
938@@ -1,4 +1,4 @@
939 #name: TLS IE->LE transition check (R_386_TLS_GOTIE)
940 #as: --32
941 #ld: -melf_i386
942-#error: .*TLS transition from R_386_TLS_GOTIE to R_386_TLS_LE_32 against `foo'.*failed.*
943+#error: .*: relocation R_386_TLS_GOTIE against `foo' must be used in ADD, SUB or MOV only
944diff --git a/ld/testsuite/ld-i386/tlsie4.d b/ld/testsuite/ld-i386/tlsie4.d
945index 3ca8fddf5dd..a516d002660 100644
946--- a/ld/testsuite/ld-i386/tlsie4.d
947+++ b/ld/testsuite/ld-i386/tlsie4.d
948@@ -1,4 +1,4 @@
949 #name: TLS IE->LE transition check (R_386_TLS_IE with %eax)
950 #as: --32
951 #ld: -melf_i386
952-#error: .*TLS transition from R_386_TLS_IE to R_386_TLS_LE_32 against `foo'.*failed.*
953+#error: .*: relocation R_386_TLS_IE against `foo' must be used in ADD or MOV only
954diff --git a/ld/testsuite/ld-i386/tlsie5.d b/ld/testsuite/ld-i386/tlsie5.d
955index 3febeb159a9..d3447182e19 100644
956--- a/ld/testsuite/ld-i386/tlsie5.d
957+++ b/ld/testsuite/ld-i386/tlsie5.d
958@@ -1,4 +1,4 @@
959 #name: TLS IE->LE transition check (R_386_TLS_IE)
960 #as: --32
961 #ld: -melf_i386
962-#error: .*TLS transition from R_386_TLS_IE to R_386_TLS_LE_32 against `foo'.*failed.*
963+#error: .*: relocation R_386_TLS_IE against `foo' must be used in ADD or MOV only
964diff --git a/ld/testsuite/ld-x86-64/tlsdesc3.d b/ld/testsuite/ld-x86-64/tlsdesc3.d
965new file mode 100644
966index 00000000000..bbf22ebeafe
967--- /dev/null
968+++ b/ld/testsuite/ld-x86-64/tlsdesc3.d
969@@ -0,0 +1,4 @@
970+#name: TLS GDesc->LE transition check (LEA)
971+#as: --64
972+#ld: -melf_x86_64
973+#error: .*: relocation R_X86_64_GOTPC32_TLSDESC against `foo' must be used in LEA only
974diff --git a/ld/testsuite/ld-x86-64/tlsdesc3.s b/ld/testsuite/ld-x86-64/tlsdesc3.s
975new file mode 100644
976index 00000000000..45310654ffc
977--- /dev/null
978+++ b/ld/testsuite/ld-x86-64/tlsdesc3.s
979@@ -0,0 +1,13 @@
980+ .text
981+ .globl _start
982+ .type _start,@function
983+_start:
984+ movq foo@tlsdesc(%rip), %rax
985+ call *foo@tlscall(%rax)
986+ .globl foo
987+ .section .tdata,"awT",@progbits
988+ .align 8
989+ .type foo, @object
990+ .size foo, 8
991+foo:
992+ .quad 100
993diff --git a/ld/testsuite/ld-x86-64/tlsdesc4.d b/ld/testsuite/ld-x86-64/tlsdesc4.d
994new file mode 100644
995index 00000000000..b50115c7178
996--- /dev/null
997+++ b/ld/testsuite/ld-x86-64/tlsdesc4.d
998@@ -0,0 +1,4 @@
999+#name: TLS GDesc->LE transition check (indirect CALL)
1000+#as: --64
1001+#ld: -melf_x86_64
1002+#error: .*: relocation R_X86_64_TLSDESC_CALL against `foo' must be used in indirect CALL only
1003diff --git a/ld/testsuite/ld-x86-64/tlsdesc4.s b/ld/testsuite/ld-x86-64/tlsdesc4.s
1004new file mode 100644
1005index 00000000000..b3d6c12d4fc
1006--- /dev/null
1007+++ b/ld/testsuite/ld-x86-64/tlsdesc4.s
1008@@ -0,0 +1,13 @@
1009+ .text
1010+ .globl _start
1011+ .type _start,@function
1012+_start:
1013+ leaq foo@tlsdesc(%rip), %rax
1014+ jmp *foo@tlscall(%rax)
1015+ .globl foo
1016+ .section .tdata,"awT",@progbits
1017+ .align 8
1018+ .type foo, @object
1019+ .size foo, 8
1020+foo:
1021+ .quad 100
1022diff --git a/ld/testsuite/ld-x86-64/tlsie2.d b/ld/testsuite/ld-x86-64/tlsie2.d
1023index 97dcc288a3d..bf8a8198b5b 100644
1024--- a/ld/testsuite/ld-x86-64/tlsie2.d
1025+++ b/ld/testsuite/ld-x86-64/tlsie2.d
1026@@ -1,4 +1,4 @@
1027 #name: TLS IE->LE transition check
1028 #as: --64
1029 #ld: -melf_x86_64
1030-#error: .*TLS transition from R_X86_64_GOTTPOFF to R_X86_64_TPOFF32 against `foo'.*failed.*
1031+#error: .*: relocation R_X86_64_GOTTPOFF against `foo' must be used in ADD or MOV only
1032diff --git a/ld/testsuite/ld-x86-64/tlsie3.d b/ld/testsuite/ld-x86-64/tlsie3.d
1033index 8c982a69838..49d8464fbaf 100644
1034--- a/ld/testsuite/ld-x86-64/tlsie3.d
1035+++ b/ld/testsuite/ld-x86-64/tlsie3.d
1036@@ -1,4 +1,4 @@
1037 #name: TLS IE->LE transition check (%r12)
1038 #as: --64
1039 #ld: -melf_x86_64
1040-#error: .*TLS transition from R_X86_64_GOTTPOFF to R_X86_64_TPOFF32 against `foo'.*failed.*
1041+#error: .*: relocation R_X86_64_GOTTPOFF against `foo' must be used in ADD or MOV only
1042diff --git a/ld/testsuite/ld-x86-64/tlsie5.d b/ld/testsuite/ld-x86-64/tlsie5.d
1043new file mode 100644
1044index 00000000000..29de1cebf8e
1045--- /dev/null
1046+++ b/ld/testsuite/ld-x86-64/tlsie5.d
1047@@ -0,0 +1,4 @@
1048+#name: TLS IE->LE transition check (APX)
1049+#as: --64
1050+#ld: -melf_x86_64
1051+#error: .*: relocation R_X86_64_CODE_6_GOTTPOFF against `foo' must be used in ADD only
1052diff --git a/ld/testsuite/ld-x86-64/tlsie5.s b/ld/testsuite/ld-x86-64/tlsie5.s
1053new file mode 100644
1054index 00000000000..c39e46fd97b
1055--- /dev/null
1056+++ b/ld/testsuite/ld-x86-64/tlsie5.s
1057@@ -0,0 +1,12 @@
1058+ .text
1059+ .globl _start
1060+_start:
1061+ xorq %rax, foo@GOTTPOFF(%rip), %rax
1062+ movq (%rax), %rax
1063+ .globl foo
1064+ .section .tdata,"awT",@progbits
1065+ .align 4
1066+ .type foo, @object
1067+ .size foo, 4
1068+foo:
1069+ .long 100
1070diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
1071index 2a40f0b095b..811813466f8 100644
1072--- a/ld/testsuite/ld-x86-64/x86-64.exp
1073+++ b/ld/testsuite/ld-x86-64/x86-64.exp
1074@@ -741,6 +741,9 @@ run_dump_test "pr27016b"
1075 run_dump_test "report-reloc-1"
1076 run_dump_test "report-reloc-1-x32"
1077 run_dump_test "pr29820"
1078+run_dump_test "tlsie5"
1079+run_dump_test "tlsdesc3"
1080+run_dump_test "tlsdesc4"
1081
1082 proc undefined_weak {cflags ldflags} {
1083 set testname "Undefined weak symbol"
1084--
10852.49.0
1086
diff --git a/meta/recipes-devtools/binutils/binutils/CVE-2025-1179.patch b/meta/recipes-devtools/binutils/binutils/CVE-2025-1179.patch
new file mode 100644
index 0000000000..89312d8501
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/CVE-2025-1179.patch
@@ -0,0 +1,269 @@
1From 67e30b15212adc1502b898a1ca224fdf65dc110d Mon Sep 17 00:00:00 2001
2From: "H.J. Lu" <hjl.tools@gmail.com>
3Date: Thu, 29 Aug 2024 08:47:00 -0700
4Subject: [PATCH] x86: Check invalid TLS descriptor call TLS descriptor
5 call,
6
7call *x@tlsdesc(%rax)
8
9or
10
11call *x@tlsdesc(%eax)
12
13calls _dl_tlsdesc_return which expects that RAX/EAX points to the TLS
14descriptor. Update x86 linker to issue an error with or without TLS
15transition.
16
17bfd/
18
19 PR ld/32123
20 * elf32-i386.c (elf_i386_check_tls_transition): Move
21 R_386_TLS_DESC_CALL to ...
22 (elf_i386_tls_transition): Here.
23 * elf64-x86-64.c (elf_x86_64_check_tls_transition): Move.
24 R_X86_64_TLSDESC_CALL check to ...
25 (elf_x86_64_tls_transition): Here.
26
27ld/
28
29 PR ld/32123
30 * testsuite/ld-i386/i386.exp: Run tlsgdesc3.
31 * testsuite/ld-i386/tlsgdesc3.d: New file.
32 * testsuite/ld-x86-64/tlsdesc5.d: Likewise.
33 * testsuite/ld-x86-64/x86-64.exp: Run tlsdesc5.
34
35(cherry picked from commit:67e30b15212adc1502b898a1ca224fdf65dc110d)
36Upstream-Status: Submitted [https://sourceware.org/pipermail/binutils/2025-May/141321.html]
37CVE: CVE-2025-1179
38
39Signed-off-by: Harish Sadineni <Harish.Sadineni@windriver.com>
40---
41 bfd/elf32-i386.c | 44 +++++++++++++------
42 bfd/elf64-x86-64.c | 71 +++++++++++++++++++------------
43 ld/testsuite/ld-i386/i386.exp | 1 +
44 ld/testsuite/ld-i386/tlsgdesc3.d | 5 +++
45 ld/testsuite/ld-x86-64/tlsdesc5.d | 5 +++
46 ld/testsuite/ld-x86-64/x86-64.exp | 1 +
47 6 files changed, 86 insertions(+), 41 deletions(-)
48 create mode 100644 ld/testsuite/ld-i386/tlsgdesc3.d
49 create mode 100644 ld/testsuite/ld-x86-64/tlsdesc5.d
50
51diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
52index 18a28d2491c..9dea465f721 100644
53--- a/bfd/elf32-i386.c
54+++ b/bfd/elf32-i386.c
55@@ -1039,19 +1039,8 @@ elf_i386_check_tls_transition (asection *sec,
56 : elf_x86_tls_error_yes);
57
58 case R_386_TLS_DESC_CALL:
59- /* Check transition from GDesc access model:
60- call *x@tlsdesc(%eax)
61- */
62- if (offset + 2 <= sec->size)
63- {
64- /* Make sure that it's a call *x@tlsdesc(%eax). */
65- call = contents + offset;
66- return (call[0] == 0xff && call[1] == 0x10
67- ? elf_x86_tls_error_none
68- : elf_x86_tls_error_indirect_call);
69- }
70-
71- return elf_x86_tls_error_yes;
72+ /* It has been checked in elf_i386_tls_transition. */
73+ return elf_x86_tls_error_none;
74
75 default:
76 abort ();
77@@ -1077,6 +1066,8 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
78 unsigned int to_type = from_type;
79 bool check = true;
80 unsigned int to_le_type, to_ie_type;
81+ bfd_vma offset;
82+ bfd_byte *call;
83
84 /* Skip TLS transition for functions. */
85 if (h != NULL
86@@ -1098,9 +1089,34 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
87
88 switch (from_type)
89 {
90+ case R_386_TLS_DESC_CALL:
91+ /* Check valid GDesc call:
92+ call *x@tlsdesc(%eax)
93+ */
94+ offset = rel->r_offset;
95+ call = NULL;
96+ if (offset + 2 <= sec->size)
97+ {
98+ /* Make sure that it's a call *x@tlsdesc(%eax). */
99+ call = contents + offset;
100+ if (call[0] != 0xff || call[1] != 0x10)
101+ call = NULL;
102+ }
103+
104+ if (call == NULL)
105+ {
106+ _bfd_x86_elf_link_report_tls_transition_error
107+ (info, abfd, sec, symtab_hdr, h, sym, rel,
108+ "R_386_TLS_DESC_CALL", NULL,
109+ elf_x86_tls_error_indirect_call);
110+
111+ return false;
112+ }
113+
114+ /* Fall through. */
115+
116 case R_386_TLS_GD:
117 case R_386_TLS_GOTDESC:
118- case R_386_TLS_DESC_CALL:
119 case R_386_TLS_IE_32:
120 case R_386_TLS_IE:
121 case R_386_TLS_GOTIE:
122diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
123index f116e423f61..7af2e607b02 100644
124--- a/bfd/elf64-x86-64.c
125+++ b/bfd/elf64-x86-64.c
126@@ -1409,32 +1409,8 @@ elf_x86_64_check_tls_transition (bfd *abfd,
127 : elf_x86_tls_error_yes);
128
129 case R_X86_64_TLSDESC_CALL:
130- /* Check transition from GDesc access model:
131- call *x@tlsdesc(%rax) <--- LP64 mode.
132- call *x@tlsdesc(%eax) <--- X32 mode.
133- */
134- if (offset + 2 <= sec->size)
135- {
136- unsigned int prefix;
137- call = contents + offset;
138- prefix = 0;
139- if (!ABI_64_P (abfd))
140- {
141- /* Check for call *x@tlsdesc(%eax). */
142- if (call[0] == 0x67)
143- {
144- prefix = 1;
145- if (offset + 3 > sec->size)
146- return elf_x86_tls_error_yes;
147- }
148- }
149- /* Make sure that it's a call *x@tlsdesc(%rax). */
150- return (call[prefix] == 0xff && call[1 + prefix] == 0x10
151- ? elf_x86_tls_error_none
152- : elf_x86_tls_error_indirect_call);
153- }
154-
155- return elf_x86_tls_error_yes;
156+ /* It has been checked in elf_x86_64_tls_transition. */
157+ return elf_x86_tls_error_none;
158
159 default:
160 abort ();
161@@ -1459,6 +1435,8 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
162 unsigned int from_type = *r_type;
163 unsigned int to_type = from_type;
164 bool check = true;
165+ bfd_vma offset;
166+ bfd_byte *call;
167
168 /* Skip TLS transition for functions. */
169 if (h != NULL
170@@ -1468,10 +1446,49 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
171
172 switch (from_type)
173 {
174+ case R_X86_64_TLSDESC_CALL:
175+ /* Check valid GDesc call:
176+ call *x@tlsdesc(%rax) <--- LP64 mode.
177+ call *x@tlsdesc(%eax) <--- X32 mode.
178+ */
179+ offset = rel->r_offset;
180+ call = NULL;
181+ if (offset + 2 <= sec->size)
182+ {
183+ unsigned int prefix;
184+ call = contents + offset;
185+ prefix = 0;
186+ if (!ABI_64_P (abfd))
187+ {
188+ /* Check for call *x@tlsdesc(%eax). */
189+ if (call[0] == 0x67)
190+ {
191+ prefix = 1;
192+ if (offset + 3 > sec->size)
193+ call = NULL;
194+ }
195+ }
196+
197+ /* Make sure that it's a call *x@tlsdesc(%rax). */
198+ if (call != NULL
199+ && (call[prefix] != 0xff || call[1 + prefix] != 0x10))
200+ call = NULL;
201+ }
202+
203+ if (call == NULL)
204+ {
205+ _bfd_x86_elf_link_report_tls_transition_error
206+ (info, abfd, sec, symtab_hdr, h, sym, rel,
207+ "R_X86_64_TLSDESC_CALL", NULL,
208+ elf_x86_tls_error_indirect_call);
209+ return false;
210+ }
211+
212+ /* Fall through. */
213+
214 case R_X86_64_TLSGD:
215 case R_X86_64_GOTPC32_TLSDESC:
216 case R_X86_64_CODE_4_GOTPC32_TLSDESC:
217- case R_X86_64_TLSDESC_CALL:
218 case R_X86_64_GOTTPOFF:
219 case R_X86_64_CODE_4_GOTTPOFF:
220 case R_X86_64_CODE_6_GOTTPOFF:
221diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
222index a8db2c713f3..41e8725d059 100644
223--- a/ld/testsuite/ld-i386/i386.exp
224+++ b/ld/testsuite/ld-i386/i386.exp
225@@ -543,6 +543,7 @@ run_dump_test "pr27998a"
226 run_dump_test "pr27998b"
227 run_dump_test "tlsgdesc1"
228 run_dump_test "tlsgdesc2"
229+run_dump_test "tlsgdesc3"
230
231 proc undefined_weak {cflags ldflags} {
232 set testname "Undefined weak symbol"
233diff --git a/ld/testsuite/ld-i386/tlsgdesc3.d b/ld/testsuite/ld-i386/tlsgdesc3.d
234new file mode 100644
235index 00000000000..f2c29d880f2
236--- /dev/null
237+++ b/ld/testsuite/ld-i386/tlsgdesc3.d
238@@ -0,0 +1,5 @@
239+#source: tlsgdesc2.s
240+#name: TLS GDesc call (indirect CALL)
241+#as: --32
242+#ld: -shared -melf_i386
243+#error: .*: relocation R_386_TLS_DESC_CALL against `foo' must be used in indirect CALL with EAX register only
244diff --git a/ld/testsuite/ld-x86-64/tlsdesc5.d b/ld/testsuite/ld-x86-64/tlsdesc5.d
245new file mode 100644
246index 00000000000..6a0158b44b7
247--- /dev/null
248+++ b/ld/testsuite/ld-x86-64/tlsdesc5.d
249@@ -0,0 +1,5 @@
250+#source: tlsdesc4.s
251+#name: TLS GDesc call (indirect CALL)
252+#as: --64
253+#ld: -shared -melf_x86_64
254+#error: .*: relocation R_X86_64_TLSDESC_CALL against `foo' must be used in indirect CALL with RAX register only
255diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
256index 811813466f8..82b0520c52a 100644
257--- a/ld/testsuite/ld-x86-64/x86-64.exp
258+++ b/ld/testsuite/ld-x86-64/x86-64.exp
259@@ -744,6 +744,7 @@ run_dump_test "pr29820"
260 run_dump_test "tlsie5"
261 run_dump_test "tlsdesc3"
262 run_dump_test "tlsdesc4"
263+run_dump_test "tlsdesc5"
264
265 proc undefined_weak {cflags ldflags} {
266 set testname "Undefined weak symbol"
267--
2682.49.0
269