]> git.ipfire.org Git - thirdparty/glibc.git/blob - elf/dl-runtime.c
85a229f6f019f59e90d2104585fe2c1b63aeb2c5
[thirdparty/glibc.git] / elf / dl-runtime.c
1 /* On-demand PLT fixup for shared objects.
2 Copyright (C) 1995-2020 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19 #define IN_DL_RUNTIME 1 /* This can be tested in dl-machine.h. */
20
21 #include <alloca.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <sys/param.h>
25 #include <ldsodefs.h>
26 #include <sysdep-cancel.h>
27 #include "dynamic-link.h"
28 #include <tls.h>
29 #include <dl-irel.h>
30 #include <dl-runtime.h>
31
32
33 #if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
34 || ELF_MACHINE_NO_REL
35 # define PLTREL ElfW(Rela)
36 #else
37 # define PLTREL ElfW(Rel)
38 #endif
39
40 /* The fixup functions might have need special attributes. If none
41 are provided define the macro as empty. */
42 #ifndef ARCH_FIXUP_ATTRIBUTE
43 # define ARCH_FIXUP_ATTRIBUTE
44 #endif
45
46 /* This function is called through a special trampoline from the PLT the
47 first time each PLT entry is called. We must perform the relocation
48 specified in the PLT of the given shared object, and return the resolved
49 function address to the trampoline, which will restart the original call
50 to that address. Future calls will bounce directly from the PLT to the
51 function. */
52
53 DL_FIXUP_VALUE_TYPE
54 attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
55 _dl_fixup (
56 # ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
57 ELF_MACHINE_RUNTIME_FIXUP_ARGS,
58 # endif
59 struct link_map *l, ElfW(Word) reloc_arg)
60 {
61 const ElfW(Sym) *const symtab
62 = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
63 const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
64
65 const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
66
67 const PLTREL *const reloc
68 = (const void *) (D_PTR (l, l_info[DT_JMPREL])
69 + reloc_offset (pltgot, reloc_arg));
70 const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
71 const ElfW(Sym) *refsym = sym;
72 void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
73 lookup_t result;
74 DL_FIXUP_VALUE_TYPE value;
75
76 /* Sanity check that we're really looking at a PLT relocation. */
77 assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
78
79 /* Look up the target symbol. If the normal lookup rules are not
80 used don't look in the global scope. */
81 if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
82 {
83 const struct r_found_version *version = NULL;
84
85 if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
86 {
87 const ElfW(Half) *vernum =
88 (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
89 ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
90 version = &l->l_versions[ndx];
91 if (version->hash == 0)
92 version = NULL;
93 }
94
95 /* We need to keep the scope around so do some locking. This is
96 not necessary for objects which cannot be unloaded or when
97 we are not using any threads (yet). */
98 int flags = DL_LOOKUP_ADD_DEPENDENCY;
99 if (!RTLD_SINGLE_THREAD_P)
100 {
101 THREAD_GSCOPE_SET_FLAG ();
102 flags |= DL_LOOKUP_GSCOPE_LOCK;
103 }
104
105 #ifdef RTLD_ENABLE_FOREIGN_CALL
106 RTLD_ENABLE_FOREIGN_CALL;
107 #endif
108
109 result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope,
110 version, ELF_RTYPE_CLASS_PLT, flags, NULL);
111
112 /* We are done with the global scope. */
113 if (!RTLD_SINGLE_THREAD_P)
114 THREAD_GSCOPE_RESET_FLAG ();
115
116 #ifdef RTLD_FINALIZE_FOREIGN_CALL
117 RTLD_FINALIZE_FOREIGN_CALL;
118 #endif
119
120 /* Currently result contains the base load address (or link map)
121 of the object that defines sym. Now add in the symbol
122 offset. */
123 value = DL_FIXUP_MAKE_VALUE (result,
124 SYMBOL_ADDRESS (result, sym, false));
125 }
126 else
127 {
128 /* We already found the symbol. The module (and therefore its load
129 address) is also known. */
130 value = DL_FIXUP_MAKE_VALUE (l, SYMBOL_ADDRESS (l, sym, true));
131 result = l;
132 }
133
134 /* And now perhaps the relocation addend. */
135 value = elf_machine_plt_value (l, reloc, value);
136
137 if (sym != NULL
138 && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0))
139 value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
140
141 /* Finally, fix up the plt itself. */
142 if (__glibc_unlikely (GLRO(dl_bind_not)))
143 return value;
144
145 return elf_machine_fixup_plt (l, result, refsym, sym, reloc, rel_addr, value);
146 }
147
148 #ifndef PROF
149 DL_FIXUP_VALUE_TYPE
150 __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
151 _dl_profile_fixup (
152 #ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
153 ELF_MACHINE_RUNTIME_FIXUP_ARGS,
154 #endif
155 struct link_map *l, ElfW(Word) reloc_arg,
156 ElfW(Addr) retaddr, void *regs, long int *framesizep)
157 {
158 void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
159
160 if (l->l_reloc_result == NULL)
161 {
162 /* BZ #14843: ELF_DYNAMIC_RELOCATE is called before l_reloc_result
163 is allocated. We will get here if ELF_DYNAMIC_RELOCATE calls a
164 resolver function to resolve an IRELATIVE relocation and that
165 resolver calls a function that is not yet resolved (lazy). For
166 example, the resolver in x86-64 libm.so calls __get_cpu_features
167 defined in libc.so. Skip audit and resolve the external function
168 in this case. */
169 *framesizep = -1;
170 return _dl_fixup (
171 # ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
172 # ifndef ELF_MACHINE_RUNTIME_FIXUP_PARAMS
173 # error Please define ELF_MACHINE_RUNTIME_FIXUP_PARAMS.
174 # endif
175 ELF_MACHINE_RUNTIME_FIXUP_PARAMS,
176 # endif
177 l, reloc_arg);
178 }
179
180 const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
181
182 /* This is the address in the array where we store the result of previous
183 relocations. */
184 struct reloc_result *reloc_result
185 = &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
186
187 /* CONCURRENCY NOTES:
188
189 Multiple threads may be calling the same PLT sequence and with
190 LD_AUDIT enabled they will be calling into _dl_profile_fixup to
191 update the reloc_result with the result of the lazy resolution.
192 The reloc_result guard variable is reloc_init, and we use
193 acquire/release loads and store to it to ensure that the results of
194 the structure are consistent with the loaded value of the guard.
195 This does not fix all of the data races that occur when two or more
196 threads read reloc_result->reloc_init with a value of zero and read
197 and write to that reloc_result concurrently. The expectation is
198 generally that while this is a data race it works because the
199 threads write the same values. Until the data races are fixed
200 there is a potential for problems to arise from these data races.
201 The reloc result updates should happen in parallel but there should
202 be an atomic RMW which does the final update to the real result
203 entry (see bug 23790).
204
205 The following code uses reloc_result->init set to 0 to indicate if it is
206 the first time this object is being relocated, otherwise 1 which
207 indicates the object has already been relocated.
208
209 Reading/Writing from/to reloc_result->reloc_init must not happen
210 before previous writes to reloc_result complete as they could
211 end-up with an incomplete struct. */
212 DL_FIXUP_VALUE_TYPE value;
213 unsigned int init = atomic_load_acquire (&reloc_result->init);
214
215 if (init == 0)
216 {
217 /* This is the first time we have to relocate this object. */
218 const ElfW(Sym) *const symtab
219 = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
220 const char *strtab = (const char *) D_PTR (l, l_info[DT_STRTAB]);
221
222 const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
223
224 const PLTREL *const reloc
225 = (const void *) (D_PTR (l, l_info[DT_JMPREL])
226 + reloc_offset (pltgot, reloc_arg));
227 const ElfW(Sym) *refsym = &symtab[ELFW(R_SYM) (reloc->r_info)];
228 const ElfW(Sym) *defsym = refsym;
229 lookup_t result;
230
231 /* Sanity check that we're really looking at a PLT relocation. */
232 assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
233
234 /* Look up the target symbol. If the symbol is marked STV_PROTECTED
235 don't look in the global scope. */
236 if (__builtin_expect (ELFW(ST_VISIBILITY) (refsym->st_other), 0) == 0)
237 {
238 const struct r_found_version *version = NULL;
239
240 if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
241 {
242 const ElfW(Half) *vernum =
243 (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
244 ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
245 version = &l->l_versions[ndx];
246 if (version->hash == 0)
247 version = NULL;
248 }
249
250 /* We need to keep the scope around so do some locking. This is
251 not necessary for objects which cannot be unloaded or when
252 we are not using any threads (yet). */
253 int flags = DL_LOOKUP_ADD_DEPENDENCY;
254 if (!RTLD_SINGLE_THREAD_P)
255 {
256 THREAD_GSCOPE_SET_FLAG ();
257 flags |= DL_LOOKUP_GSCOPE_LOCK;
258 }
259
260 result = _dl_lookup_symbol_x (strtab + refsym->st_name, l,
261 &defsym, l->l_scope, version,
262 ELF_RTYPE_CLASS_PLT, flags, NULL);
263
264 /* We are done with the global scope. */
265 if (!RTLD_SINGLE_THREAD_P)
266 THREAD_GSCOPE_RESET_FLAG ();
267
268 /* Currently result contains the base load address (or link map)
269 of the object that defines sym. Now add in the symbol
270 offset. */
271 value = DL_FIXUP_MAKE_VALUE (result,
272 SYMBOL_ADDRESS (result, defsym, false));
273
274 if (defsym != NULL
275 && __builtin_expect (ELFW(ST_TYPE) (defsym->st_info)
276 == STT_GNU_IFUNC, 0))
277 value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
278 }
279 else
280 {
281 /* We already found the symbol. The module (and therefore its load
282 address) is also known. */
283 value = DL_FIXUP_MAKE_VALUE (l, SYMBOL_ADDRESS (l, refsym, true));
284
285 if (__builtin_expect (ELFW(ST_TYPE) (refsym->st_info)
286 == STT_GNU_IFUNC, 0))
287 value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
288
289 result = l;
290 }
291 /* And now perhaps the relocation addend. */
292 value = elf_machine_plt_value (l, reloc, value);
293
294 #ifdef SHARED
295 /* Auditing checkpoint: we have a new binding. Provide the
296 auditing libraries the possibility to change the value and
297 tell us whether further auditing is wanted. */
298 if (defsym != NULL && GLRO(dl_naudit) > 0)
299 {
300 reloc_result->bound = result;
301 /* Compute index of the symbol entry in the symbol table of
302 the DSO with the definition. */
303 reloc_result->boundndx = (defsym
304 - (ElfW(Sym) *) D_PTR (result,
305 l_info[DT_SYMTAB]));
306
307 /* Determine whether any of the two participating DSOs is
308 interested in auditing. */
309 if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0)
310 {
311 unsigned int flags = 0;
312 struct audit_ifaces *afct = GLRO(dl_audit);
313 /* Synthesize a symbol record where the st_value field is
314 the result. */
315 ElfW(Sym) sym = *defsym;
316 sym.st_value = DL_FIXUP_VALUE_ADDR (value);
317
318 /* Keep track whether there is any interest in tracing
319 the call in the lower two bits. */
320 assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8);
321 assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3);
322 reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT;
323
324 const char *strtab2 = (const void *) D_PTR (result,
325 l_info[DT_STRTAB]);
326
327 for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
328 {
329 /* XXX Check whether both DSOs must request action or
330 only one */
331 struct auditstate *l_state = link_map_audit_state (l, cnt);
332 struct auditstate *result_state
333 = link_map_audit_state (result, cnt);
334 if ((l_state->bindflags & LA_FLG_BINDFROM) != 0
335 && (result_state->bindflags & LA_FLG_BINDTO) != 0)
336 {
337 if (afct->symbind != NULL)
338 {
339 uintptr_t new_value
340 = afct->symbind (&sym, reloc_result->boundndx,
341 &l_state->cookie,
342 &result_state->cookie,
343 &flags,
344 strtab2 + defsym->st_name);
345 if (new_value != (uintptr_t) sym.st_value)
346 {
347 flags |= LA_SYMB_ALTVALUE;
348 sym.st_value = new_value;
349 }
350 }
351
352 /* Remember the results for every audit library and
353 store a summary in the first two bits. */
354 reloc_result->enterexit
355 &= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
356 reloc_result->enterexit
357 |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
358 << ((cnt + 1) * 2));
359 }
360 else
361 /* If the bind flags say this auditor is not interested,
362 set the bits manually. */
363 reloc_result->enterexit
364 |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)
365 << ((cnt + 1) * 2));
366
367 afct = afct->next;
368 }
369
370 reloc_result->flags = flags;
371 value = DL_FIXUP_ADDR_VALUE (sym.st_value);
372 }
373 else
374 /* Set all bits since this symbol binding is not interesting. */
375 reloc_result->enterexit = (1u << DL_NNS) - 1;
376 }
377 #endif
378
379 /* Store the result for later runs. */
380 if (__glibc_likely (! GLRO(dl_bind_not)))
381 {
382 reloc_result->addr = value;
383 /* Guarantee all previous writes complete before
384 init is updated. See CONCURRENCY NOTES earlier */
385 atomic_store_release (&reloc_result->init, 1);
386 }
387 init = 1;
388 }
389 else
390 value = reloc_result->addr;
391
392 /* By default we do not call the pltexit function. */
393 long int framesize = -1;
394
395
396 #ifdef SHARED
397 /* Auditing checkpoint: report the PLT entering and allow the
398 auditors to change the value. */
399 if (GLRO(dl_naudit) > 0
400 /* Don't do anything if no auditor wants to intercept this call. */
401 && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
402 {
403 /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been
404 initialized earlier in this function or in another thread. */
405 assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0);
406 ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
407 l_info[DT_SYMTAB])
408 + reloc_result->boundndx);
409
410 /* Set up the sym parameter. */
411 ElfW(Sym) sym = *defsym;
412 sym.st_value = DL_FIXUP_VALUE_ADDR (value);
413
414 /* Get the symbol name. */
415 const char *strtab = (const void *) D_PTR (reloc_result->bound,
416 l_info[DT_STRTAB]);
417 const char *symname = strtab + sym.st_name;
418
419 /* Keep track of overwritten addresses. */
420 unsigned int flags = reloc_result->flags;
421
422 struct audit_ifaces *afct = GLRO(dl_audit);
423 for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
424 {
425 if (afct->ARCH_LA_PLTENTER != NULL
426 && (reloc_result->enterexit
427 & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)
428 {
429 long int new_framesize = -1;
430 struct auditstate *l_state = link_map_audit_state (l, cnt);
431 struct auditstate *bound_state
432 = link_map_audit_state (reloc_result->bound, cnt);
433 uintptr_t new_value
434 = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,
435 &l_state->cookie,
436 &bound_state->cookie,
437 regs, &flags, symname,
438 &new_framesize);
439 if (new_value != (uintptr_t) sym.st_value)
440 {
441 flags |= LA_SYMB_ALTVALUE;
442 sym.st_value = new_value;
443 }
444
445 /* Remember the results for every audit library and
446 store a summary in the first two bits. */
447 reloc_result->enterexit
448 |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
449 << (2 * (cnt + 1)));
450
451 if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT
452 << (2 * (cnt + 1))))
453 == 0 && new_framesize != -1 && framesize != -2)
454 {
455 /* If this is the first call providing information,
456 use it. */
457 if (framesize == -1)
458 framesize = new_framesize;
459 /* If two pltenter calls provide conflicting information,
460 use the larger value. */
461 else if (new_framesize != framesize)
462 framesize = MAX (new_framesize, framesize);
463 }
464 }
465
466 afct = afct->next;
467 }
468
469 value = DL_FIXUP_ADDR_VALUE (sym.st_value);
470 }
471 #endif
472
473 /* Store the frame size information. */
474 *framesizep = framesize;
475
476 (*mcount_fct) (retaddr, DL_FIXUP_VALUE_CODE_ADDR (value));
477
478 return value;
479 }
480
481 #endif /* PROF */
482
483
484 #include <stdio.h>
485 void
486 ARCH_FIXUP_ATTRIBUTE
487 _dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
488 const void *inregs, void *outregs)
489 {
490 #ifdef SHARED
491 const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
492
493 /* This is the address in the array where we store the result of previous
494 relocations. */
495 // XXX Maybe the bound information must be stored on the stack since
496 // XXX with bind_not a new value could have been stored in the meantime.
497 struct reloc_result *reloc_result =
498 &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
499 ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
500 l_info[DT_SYMTAB])
501 + reloc_result->boundndx);
502
503 /* Set up the sym parameter. */
504 ElfW(Sym) sym = *defsym;
505 sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr);
506
507 /* Get the symbol name. */
508 const char *strtab = (const void *) D_PTR (reloc_result->bound,
509 l_info[DT_STRTAB]);
510 const char *symname = strtab + sym.st_name;
511
512 struct audit_ifaces *afct = GLRO(dl_audit);
513 for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
514 {
515 if (afct->ARCH_LA_PLTEXIT != NULL
516 && (reloc_result->enterexit
517 & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
518 {
519 struct auditstate *l_state = link_map_audit_state (l, cnt);
520 struct auditstate *bound_state
521 = link_map_audit_state (reloc_result->bound, cnt);
522 afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
523 &l_state->cookie, &bound_state->cookie,
524 inregs, outregs, symname);
525 }
526
527 afct = afct->next;
528 }
529 #endif
530 }