1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright 1996, 1997, 1998, 1999 John D. Polstra. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * Dynamic linker for ELF. 30 * 31 * John Polstra <jdp@polstra.com>. 32 */ 33 34 #define _WANT_P_OSREL 35 #include <sys/param.h> 36 #include <sys/mman.h> 37 38 #include <machine/cpufunc.h> 39 #include <machine/specialreg.h> 40 #include <machine/sysarch.h> 41 42 #include <dlfcn.h> 43 #include <err.h> 44 #include <errno.h> 45 #include <fcntl.h> 46 #include <stdarg.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <unistd.h> 51 52 #include "debug.h" 53 #include "rtld.h" 54 #include "rtld_tls.h" 55 56 void 57 md_obj_entry_init(Obj_Entry *obj) 58 { 59 STAILQ_INIT(&obj->tlsdesc_dynargs); 60 } 61 62 void 63 md_obj_entry_fini(Obj_Entry *obj) 64 { 65 struct tlsdesc_dynarg *tda, *t; 66 67 STAILQ_FOREACH_SAFE(tda, &obj->tlsdesc_dynargs, link, t) { 68 free(tda); 69 } 70 } 71 72 /* 73 * Process the special R_X86_64_COPY relocations in the main program. These 74 * copy data from a shared object into a region in the main program's BSS 75 * segment. 76 * 77 * Returns 0 on success, -1 on failure. 78 */ 79 int 80 do_copy_relocations(Obj_Entry *dstobj) 81 { 82 const Elf_Rela *relalim; 83 const Elf_Rela *rela; 84 85 assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */ 86 87 relalim = (const Elf_Rela *)((const char *)dstobj->rela + 88 dstobj->relasize); 89 for (rela = dstobj->rela; rela < relalim; rela++) { 90 if (ELF_R_TYPE(rela->r_info) == R_X86_64_COPY) { 91 void *dstaddr; 92 const Elf_Sym *dstsym; 93 const char *name; 94 size_t size; 95 const void *srcaddr; 96 const Elf_Sym *srcsym; 97 const Obj_Entry *srcobj, *defobj; 98 SymLook req; 99 int res; 100 101 dstaddr = (void *)(dstobj->relocbase + rela->r_offset); 102 dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); 103 name = dstobj->strtab + dstsym->st_name; 104 size = dstsym->st_size; 105 symlook_init(&req, name); 106 req.ventry = fetch_ventry(dstobj, 107 ELF_R_SYM(rela->r_info)); 108 req.flags = SYMLOOK_EARLY; 109 110 for (srcobj = globallist_next(dstobj); srcobj != NULL; 111 srcobj = globallist_next(srcobj)) { 112 res = symlook_obj(&req, srcobj); 113 if (res == 0) { 114 srcsym = req.sym_out; 115 defobj = req.defobj_out; 116 break; 117 } 118 } 119 120 if (srcobj == NULL) { 121 _rtld_error( 122 "Undefined symbol \"%s\" referenced from COPY relocation in %s", 123 name, dstobj->path); 124 return (-1); 125 } 126 127 srcaddr = (const void *)(defobj->relocbase + 128 srcsym->st_value); 129 memcpy(dstaddr, srcaddr, size); 130 } 131 } 132 133 return (0); 134 } 135 136 /* Initialize the special GOT entries. */ 137 void 138 init_pltgot(Obj_Entry *obj) 139 { 140 if (obj->pltgot != NULL) { 141 obj->pltgot[1] = (Elf_Addr)obj; 142 obj->pltgot[2] = (Elf_Addr)&_rtld_bind_start; 143 } 144 } 145 146 static struct tlsdesc_dynarg * 147 reloc_tlsdesc_alloc(Obj_Entry *obj, Elf_Addr tlsoffs) 148 { 149 struct tlsdesc_dynarg *tda; 150 151 tda = xmalloc(sizeof(struct tlsdesc_dynarg)); 152 tda->tlsinfo.ti_module = obj->tlsindex; 153 tda->tlsinfo.ti_offset = tlsoffs; 154 STAILQ_INSERT_TAIL(&obj->tlsdesc_dynargs, tda, link); 155 return (tda); 156 } 157 158 static void 159 reloc_tlsdesc(const Obj_Entry *obj, const Elf_Rela *rela, 160 struct tlsdesc *where, int flags, RtldLockState *lockstate) 161 { 162 const Elf_Sym *def; 163 const Obj_Entry *defobj; 164 Elf_Addr offs; 165 166 dbg("reloc_tlsdesc obj %s rela %p where %p", obj->path, rela, where); 167 offs = 0; 168 if (ELF_R_SYM(rela->r_info) != 0) { 169 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, flags, 170 NULL, lockstate); 171 if (def == NULL) 172 rtld_die(); 173 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 174 _rtld_error("%s: IFUNC for TLSDESC reloc", 175 obj->path); 176 rtld_die(); 177 } 178 offs = def->st_value; 179 obj = defobj; 180 if (def->st_shndx == SHN_UNDEF) { 181 /* Weak undefined thread variable */ 182 where->entry = rtld_tlsdesc_undef; 183 where->addend = rela->r_addend; 184 return; 185 } 186 } 187 offs += rela->r_addend; 188 189 if (obj->tlsoffset != 0) { 190 /* Variable is in initialy allocated TLS segment */ 191 where->entry = rtld_tlsdesc_static; 192 where->offset = offs - obj->tlsoffset; 193 } else { 194 /* TLS offest is unknown at load time, use dynamic resolving */ 195 where->entry = rtld_tlsdesc_dynamic; 196 where->arg = reloc_tlsdesc_alloc(__DECONST(Obj_Entry *, obj), 197 offs); 198 } 199 } 200 201 /* Process the non-PLT relocations. */ 202 int 203 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags, 204 RtldLockState *lockstate) 205 { 206 const Elf_Rela *relalim; 207 const Elf_Rela *rela; 208 SymCache *cache; 209 const Elf_Sym *def; 210 const Obj_Entry *defobj; 211 Elf_Addr *where, symval; 212 Elf32_Addr *where32; 213 int r; 214 215 r = -1; 216 symval = 0; 217 def = NULL; 218 219 /* 220 * The dynamic loader may be called from a thread, we have 221 * limited amounts of stack available so we cannot use alloca(). 222 */ 223 if (obj != obj_rtld) { 224 cache = calloc(obj->dynsymcount, sizeof(SymCache)); 225 /* No need to check for NULL here */ 226 } else 227 cache = NULL; 228 229 relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); 230 for (rela = obj->rela; rela < relalim; rela++) { 231 /* 232 * First, resolve symbol for relocations which 233 * reference symbols. 234 */ 235 switch (ELF_R_TYPE(rela->r_info)) { 236 case R_X86_64_64: 237 case R_X86_64_PC32: 238 case R_X86_64_GLOB_DAT: 239 case R_X86_64_TPOFF64: 240 case R_X86_64_TPOFF32: 241 case R_X86_64_DTPMOD64: 242 case R_X86_64_DTPOFF64: 243 case R_X86_64_DTPOFF32: 244 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 245 flags, cache, lockstate); 246 if (def == NULL) 247 goto done; 248 249 /* 250 * If symbol is IFUNC, only perform relocation 251 * when caller allowed it by passing 252 * SYMLOOK_IFUNC flag. Skip the relocations 253 * otherwise. 254 * 255 * Also error out in case IFUNC relocations 256 * are specified for TLS, which cannot be 257 * usefully interpreted. 258 */ 259 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 260 switch (ELF_R_TYPE(rela->r_info)) { 261 case R_X86_64_64: 262 case R_X86_64_PC32: 263 case R_X86_64_GLOB_DAT: 264 if ((flags & SYMLOOK_IFUNC) == 0) { 265 obj->non_plt_gnu_ifunc = true; 266 continue; 267 } 268 symval = (Elf_Addr)rtld_resolve_ifunc( 269 defobj, def); 270 break; 271 case R_X86_64_TPOFF64: 272 case R_X86_64_TPOFF32: 273 case R_X86_64_DTPMOD64: 274 case R_X86_64_DTPOFF64: 275 case R_X86_64_DTPOFF32: 276 _rtld_error("%s: IFUNC for TLS reloc", 277 obj->path); 278 goto done; 279 } 280 } else { 281 if ((flags & SYMLOOK_IFUNC) != 0) 282 continue; 283 symval = (Elf_Addr)defobj->relocbase + 284 def->st_value; 285 } 286 break; 287 default: 288 if ((flags & SYMLOOK_IFUNC) != 0) 289 continue; 290 break; 291 } 292 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 293 where32 = (Elf32_Addr *)where; 294 295 switch (ELF_R_TYPE(rela->r_info)) { 296 case R_X86_64_NONE: 297 break; 298 case R_X86_64_64: 299 *where = symval + rela->r_addend; 300 break; 301 case R_X86_64_PC32: 302 /* 303 * I don't think the dynamic linker should 304 * ever see this type of relocation. But the 305 * binutils-2.6 tools sometimes generate it. 306 */ 307 *where32 = (Elf32_Addr)(unsigned long)(symval + 308 rela->r_addend - (Elf_Addr)where); 309 break; 310 /* missing: R_X86_64_GOT32 R_X86_64_PLT32 */ 311 case R_X86_64_COPY: 312 /* 313 * These are deferred until all other 314 * relocations have been done. All we do here 315 * is make sure that the COPY relocation is 316 * not in a shared library. They are allowed 317 * only in executable files. 318 */ 319 if (!obj->mainprog) { 320 _rtld_error( 321 "%s: Unexpected R_X86_64_COPY relocation in shared library", 322 obj->path); 323 goto done; 324 } 325 break; 326 case R_X86_64_GLOB_DAT: 327 *where = symval; 328 break; 329 case R_X86_64_TPOFF64: 330 /* 331 * We lazily allocate offsets for static TLS 332 * as we see the first relocation that 333 * references the TLS block. This allows us to 334 * support (small amounts of) static TLS in 335 * dynamically loaded modules. If we run out 336 * of space, we generate an error. 337 */ 338 if (!defobj->tls_static) { 339 if (!allocate_tls_offset(__DECONST(Obj_Entry *, 340 defobj))) { 341 _rtld_error( 342 "%s: No space available for static Thread Local Storage", 343 obj->path); 344 goto done; 345 } 346 } 347 *where = (Elf_Addr)(def->st_value - defobj->tlsoffset + 348 rela->r_addend); 349 break; 350 case R_X86_64_TPOFF32: 351 /* 352 * We lazily allocate offsets for static TLS 353 * as we see the first relocation that 354 * references the TLS block. This allows us to 355 * support (small amounts of) static TLS in 356 * dynamically loaded modules. If we run out 357 * of space, we generate an error. 358 */ 359 if (!defobj->tls_static) { 360 if (!allocate_tls_offset(__DECONST(Obj_Entry *, 361 defobj))) { 362 _rtld_error( 363 "%s: No space available for static Thread Local Storage", 364 obj->path); 365 goto done; 366 } 367 } 368 *where32 = (Elf32_Addr)(def->st_value - 369 defobj->tlsoffset + rela->r_addend); 370 break; 371 case R_X86_64_DTPMOD64: 372 *where += (Elf_Addr)defobj->tlsindex; 373 break; 374 case R_X86_64_DTPOFF64: 375 *where += (Elf_Addr)(def->st_value + rela->r_addend); 376 break; 377 case R_X86_64_DTPOFF32: 378 *where32 += (Elf32_Addr)(def->st_value + 379 rela->r_addend); 380 break; 381 case R_X86_64_RELATIVE: 382 *where = (Elf_Addr)(obj->relocbase + rela->r_addend); 383 break; 384 case R_X86_64_IRELATIVE: 385 obj->irelative_nonplt = true; 386 break; 387 case R_X86_64_TLSDESC: 388 reloc_tlsdesc(obj, rela, (struct tlsdesc *)where, 389 flags, lockstate); 390 break; 391 392 /* 393 * missing: 394 * R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16, 395 * R_X86_64_PC16, R_X86_64_8, R_X86_64_PC8 396 */ 397 default: 398 _rtld_error( 399 "%s: Unsupported relocation type %u in non-PLT relocations", 400 obj->path, (unsigned int)ELF_R_TYPE(rela->r_info)); 401 goto done; 402 } 403 } 404 r = 0; 405 done: 406 free(cache); 407 return (r); 408 } 409 410 /* Process the PLT relocations. */ 411 int 412 reloc_plt(Obj_Entry *obj, int flags, RtldLockState *lockstate) 413 { 414 const Elf_Rela *relalim; 415 const Elf_Rela *rela; 416 417 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 418 obj->pltrelasize); 419 for (rela = obj->pltrela; rela < relalim; rela++) { 420 Elf_Addr *where; 421 422 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 423 switch (ELF_R_TYPE(rela->r_info)) { 424 case R_X86_64_JMP_SLOT: 425 /* Relocate the GOT slot pointing into the PLT. */ 426 *where += (Elf_Addr)obj->relocbase; 427 break; 428 429 case R_X86_64_IRELATIVE: 430 obj->irelative = true; 431 break; 432 433 case R_X86_64_TLSDESC: 434 reloc_tlsdesc(obj, rela, (struct tlsdesc *)where, 435 SYMLOOK_IN_PLT | flags, lockstate); 436 break; 437 438 default: 439 _rtld_error("Unknown relocation type %x in PLT", 440 (unsigned int)ELF_R_TYPE(rela->r_info)); 441 return (-1); 442 } 443 } 444 return (0); 445 } 446 447 /* Relocate the jump slots in an object. */ 448 int 449 reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate) 450 { 451 const Elf_Rela *relalim; 452 const Elf_Rela *rela; 453 454 if (obj->jmpslots_done) 455 return (0); 456 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 457 obj->pltrelasize); 458 for (rela = obj->pltrela; rela < relalim; rela++) { 459 Elf_Addr *where, target; 460 const Elf_Sym *def; 461 const Obj_Entry *defobj; 462 463 switch (ELF_R_TYPE(rela->r_info)) { 464 case R_X86_64_JMP_SLOT: 465 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 466 def = find_symdef(ELF_R_SYM(rela->r_info), obj, 467 &defobj, SYMLOOK_IN_PLT | flags, NULL, lockstate); 468 if (def == NULL) 469 return (-1); 470 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 471 obj->gnu_ifunc = true; 472 continue; 473 } 474 target = (Elf_Addr)(defobj->relocbase + def->st_value + 475 rela->r_addend); 476 reloc_jmpslot(where, target, defobj, obj, 477 (const Elf_Rel *)rela); 478 break; 479 480 case R_X86_64_IRELATIVE: 481 break; 482 483 default: 484 _rtld_error("Unknown relocation type %x in PLT", 485 (unsigned int)ELF_R_TYPE(rela->r_info)); 486 return (-1); 487 } 488 } 489 obj->jmpslots_done = true; 490 return (0); 491 } 492 493 /* Fixup the jump slot at "where" to transfer control to "target". */ 494 Elf_Addr 495 reloc_jmpslot(Elf_Addr *where, Elf_Addr target, 496 const struct Struct_Obj_Entry *obj __unused, 497 const struct Struct_Obj_Entry *refobj __unused, const Elf_Rel *rel __unused) 498 { 499 dbg("reloc_jmpslot: *%p = %p", where, (void *)target); 500 if (!ld_bind_not) 501 *where = target; 502 return (target); 503 } 504 505 static void 506 reloc_iresolve_one(Obj_Entry *obj, const Elf_Rela *rela, 507 RtldLockState *lockstate) 508 { 509 Elf_Addr *where, target, *ptr; 510 511 ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend); 512 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 513 lock_release(rtld_bind_lock, lockstate); 514 target = call_ifunc_resolver(ptr); 515 wlock_acquire(rtld_bind_lock, lockstate); 516 *where = target; 517 } 518 519 int 520 reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate) 521 { 522 const Elf_Rela *relalim; 523 const Elf_Rela *rela; 524 525 if (!obj->irelative) 526 return (0); 527 obj->irelative = false; 528 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 529 obj->pltrelasize); 530 for (rela = obj->pltrela; rela < relalim; rela++) { 531 if (ELF_R_TYPE(rela->r_info) == R_X86_64_IRELATIVE) 532 reloc_iresolve_one(obj, rela, lockstate); 533 } 534 return (0); 535 } 536 537 int 538 reloc_iresolve_nonplt(Obj_Entry *obj, RtldLockState *lockstate) 539 { 540 const Elf_Rela *relalim; 541 const Elf_Rela *rela; 542 543 if (!obj->irelative_nonplt) 544 return (0); 545 obj->irelative_nonplt = false; 546 relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize); 547 for (rela = obj->rela; rela < relalim; rela++) { 548 if (ELF_R_TYPE(rela->r_info) == R_X86_64_IRELATIVE) 549 reloc_iresolve_one(obj, rela, lockstate); 550 } 551 return (0); 552 } 553 554 int 555 reloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate) 556 { 557 const Elf_Rela *relalim; 558 const Elf_Rela *rela; 559 560 if (!obj->gnu_ifunc) 561 return (0); 562 relalim = (const Elf_Rela *)((const char *)obj->pltrela + 563 obj->pltrelasize); 564 for (rela = obj->pltrela; rela < relalim; rela++) { 565 Elf_Addr *where, target; 566 const Elf_Sym *def; 567 const Obj_Entry *defobj; 568 569 switch (ELF_R_TYPE(rela->r_info)) { 570 case R_X86_64_JMP_SLOT: 571 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 572 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, 573 SYMLOOK_IN_PLT | flags, NULL, lockstate); 574 if (def == NULL) 575 return (-1); 576 if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC) 577 continue; 578 lock_release(rtld_bind_lock, lockstate); 579 target = (Elf_Addr)rtld_resolve_ifunc(defobj, def); 580 wlock_acquire(rtld_bind_lock, lockstate); 581 reloc_jmpslot(where, target, defobj, obj, 582 (const Elf_Rel *)rela); 583 break; 584 } 585 } 586 obj->gnu_ifunc = false; 587 return (0); 588 } 589 590 uint32_t cpu_feature, cpu_feature2, cpu_stdext_feature, cpu_stdext_feature2; 591 592 void 593 ifunc_init(Elf_Auxinfo *aux_info[__min_size(AT_COUNT)] __unused) 594 { 595 u_int p[4], cpu_high; 596 597 do_cpuid(1, p); 598 cpu_feature = p[3]; 599 cpu_feature2 = p[2]; 600 do_cpuid(0, p); 601 cpu_high = p[0]; 602 if (cpu_high >= 7) { 603 cpuid_count(7, 0, p); 604 cpu_stdext_feature = p[1]; 605 cpu_stdext_feature2 = p[2]; 606 } 607 } 608 609 int __getosreldate(void); 610 611 void 612 allocate_initial_tls(Obj_Entry *objs) 613 { 614 void *addr; 615 616 /* 617 * Fix the size of the static TLS block by using the maximum 618 * offset allocated so far and adding a bit for dynamic 619 * modules to use. 620 */ 621 tls_static_space = tls_last_offset + ld_static_tls_extra; 622 623 addr = allocate_tls(objs, 0, TLS_TCB_SIZE, TLS_TCB_ALIGN); 624 625 /* 626 * This does not use _tcb_set() as it calls amd64_set_tlsbase() 627 * which is an ifunc and rtld must not use ifuncs. 628 */ 629 if (__getosreldate() >= P_OSREL_TLSBASE) 630 sysarch(AMD64_SET_TLSBASE, &addr); 631 else if ((cpu_stdext_feature & CPUID_STDEXT_FSGSBASE) != 0) 632 wrfsbase((uintptr_t)addr); 633 else 634 sysarch(AMD64_SET_FSBASE, &addr); 635 } 636 637 void * 638 __tls_get_addr(tls_index *ti) 639 { 640 return (tls_get_addr_common(_tcb_get(), ti->ti_module, ti->ti_offset)); 641 } 642 643 size_t 644 calculate_tls_offset(size_t prev_offset, size_t prev_size __unused, size_t size, 645 size_t align, size_t offset) 646 { 647 size_t res; 648 649 /* 650 * res is the smallest integer satisfying res - prev_offset >= size 651 * and (-res) % p_align = p_vaddr % p_align (= p_offset % p_align). 652 */ 653 res = prev_offset + size + align - 1; 654 res -= (res + offset) & (align - 1); 655 return (res); 656 } 657 658 size_t 659 calculate_first_tls_offset(size_t size, size_t align, size_t offset) 660 { 661 return (calculate_tls_offset(0, 0, size, align, offset)); 662 } 663 664 ptrdiff_t 665 rtld_tlsdesc_dynamic_impl(struct tlsdesc_dynarg *tda, struct tcb *tcb) 666 { 667 tls_index *ti; 668 669 ti = &tda->tlsinfo; 670 return ((ptrdiff_t)tls_get_addr_common(tcb, ti->ti_module, 671 ti->ti_offset) - (ptrdiff_t)tcb); 672 } 673