Bug Summary

File:src/libexec/ld.so/loader.c
Warning:line 715, column 3
Value stored to 'fails' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name loader.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/libexec/ld.so/obj -resource-dir /usr/local/lib/clang/13.0.0 -D DO_CLEAN_BOOT -I /usr/src/libexec/ld.so -I /usr/src/libexec/ld.so/amd64 -D DEF_WEAK(x)=asm("") -D DEF_STRONG(x)=asm("") -D strsep=_dl_strsep -D strlcat=_dl_strlcat -D strlen=_dl_strlen -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/libexec/ld.so/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fno-builtin -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/libexec/ld.so/loader.c
1/* $OpenBSD: loader.c,v 1.195 2022/01/08 06:49:41 guenther Exp $ */
2
3/*
4 * Copyright (c) 1998 Per Fogelstrom, Opsycon AB
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29#define _DYN_LOADER
30
31#include <sys/types.h>
32#include <sys/mman.h>
33#include <sys/exec.h>
34#ifdef __i386__
35# include <machine/vmparam.h>
36#endif
37#include <string.h>
38#include <link.h>
39#include <limits.h> /* NAME_MAX */
40#include <dlfcn.h>
41#include <tib.h>
42
43#include "syscall.h"
44#include "util.h"
45#include "resolve.h"
46#include "path.h"
47#include "sod.h"
48
49/*
50 * Local decls.
51 */
52unsigned long _dl_boot(const char **, char **, const long, long *) __boot__attribute__((section(".boot.text")));
53void _dl_debug_state(void);
54void _dl_setup_env(const char *_argv0, char **_envp) __boot__attribute__((section(".boot.text")));
55void _dl_dtors(void);
56void _dl_dopreload(char *_paths) __boot__attribute__((section(".boot.text")));
57void _dl_fixup_user_env(void) __boot__attribute__((section(".boot.text")));
58void _dl_call_preinit(elf_object_t *) __boot__attribute__((section(".boot.text")));
59void _dl_call_init_recurse(elf_object_t *object, int initfirst);
60void _dl_clean_boot(void);
61static inline void unprotect_if_textrel(elf_object_t *_object);
62static inline void reprotect_if_textrel(elf_object_t *_object);
63static void _dl_rreloc(elf_object_t *_object);
64
65int _dl_pagesz __relro__attribute__((section(".data.rel.ro"))) = 4096;
66int _dl_bindnow __relro__attribute__((section(".data.rel.ro"))) = 0;
67int _dl_debug __relro__attribute__((section(".data.rel.ro"))) = 0;
68int _dl_trust __relro__attribute__((section(".data.rel.ro"))) = 0;
69char **_dl_libpath __relro__attribute__((section(".data.rel.ro"))) = NULL((void*)0);
70const char **_dl_argv __relro__attribute__((section(".data.rel.ro"))) = NULL((void*)0);
71int _dl_argc __relro__attribute__((section(".data.rel.ro"))) = 0;
72
73char *_dl_preload __boot_data__attribute__((section(".boot.data"))) = NULL((void*)0);
74char *_dl_tracefmt1 __boot_data__attribute__((section(".boot.data"))) = NULL((void*)0);
75char *_dl_tracefmt2 __boot_data__attribute__((section(".boot.data"))) = NULL((void*)0);
76char *_dl_traceprog __boot_data__attribute__((section(".boot.data"))) = NULL((void*)0);
77void *_dl_exec_hint __boot_data__attribute__((section(".boot.data"))) = NULL((void*)0);
78
79char **environ = NULL((void*)0);
80char *__progname = NULL((void*)0);
81
82int _dl_traceld;
83struct r_debug *_dl_debug_map;
84
85static dl_cb_cb _dl_cb_cb;
86const struct dl_cb_0 callbacks_0 = {
87 .dl_allocate_tib = &_dl_allocate_tib,
88 .dl_free_tib = &_dl_free_tib,
89#if DO_CLEAN_BOOT1
90 .dl_clean_boot = &_dl_clean_boot,
91#endif
92 .dlopen = &dlopen,
93 .dlclose = &dlclose,
94 .dlsym = &dlsym,
95 .dladdr = &dladdr,
96 .dlctl = &dlctl,
97 .dlerror = &dlerror,
98 .dl_iterate_phdr = &dl_iterate_phdr,
99};
100
101
102/*
103 * Run dtors for a single object.
104 */
105void
106_dl_run_dtors(elf_object_t *obj)
107{
108 if (obj->dynDyn.u.fini_array) {
109 int num = obj->dynDyn.u.fini_arraysz / sizeof(Elf_AddrElf64_Addr);
110 int i;
111
112 DL_DEB(("doing finiarray obj %p @%p: [%s]\n",do { if (_dl_debug) _dl_printf ("doing finiarray obj %p @%p: [%s]\n"
, obj, obj->Dyn.u.fini_array, obj->load_name) ; } while
(0)
113 obj, obj->dyn.fini_array, obj->load_name))do { if (_dl_debug) _dl_printf ("doing finiarray obj %p @%p: [%s]\n"
, obj, obj->Dyn.u.fini_array, obj->load_name) ; } while
(0)
;
114 for (i = num; i > 0; i--)
115 (*obj->dynDyn.u.fini_array[i-1])();
116 }
117
118 if (obj->dynDyn.u.fini) {
119 DL_DEB(("doing dtors obj %p @%p: [%s]\n",do { if (_dl_debug) _dl_printf ("doing dtors obj %p @%p: [%s]\n"
, obj, obj->Dyn.u.fini, obj->load_name) ; } while (0)
120 obj, obj->dyn.fini, obj->load_name))do { if (_dl_debug) _dl_printf ("doing dtors obj %p @%p: [%s]\n"
, obj, obj->Dyn.u.fini, obj->load_name) ; } while (0)
;
121 (*obj->dynDyn.u.fini)();
122 }
123}
124
125/*
126 * Run dtors for all objects that are eligible.
127 */
128void
129_dl_run_all_dtors(void)
130{
131 elf_object_t *node;
132 int fini_complete;
133 int skip_initfirst;
134 int initfirst_skipped;
135
136 fini_complete = 0;
137 skip_initfirst = 1;
138 initfirst_skipped = 0;
139
140 while (fini_complete == 0) {
141 fini_complete = 1;
142 for (node = _dl_objects;
143 node != NULL((void*)0);
144 node = node->next) {
145 if ((node->dynDyn.u.fini || node->dynDyn.u.fini_array) &&
146 (OBJECT_REF_CNT(node)((node->refcount + node->opencount + node->grprefcount
))
== 0) &&
147 (node->status & STAT_INIT_DONE0x004) &&
148 ((node->status & STAT_FINI_DONE0x008) == 0)) {
149 if (skip_initfirst &&
150 (node->obj_flags & DF_1_INITFIRST0x00000020))
151 initfirst_skipped = 1;
152 else
153 node->status |= STAT_FINI_READY0x010;
154 }
155 }
156 for (node = _dl_objects;
157 node != NULL((void*)0);
158 node = node->next ) {
159 if ((node->dynDyn.u.fini || node->dynDyn.u.fini_array) &&
160 (OBJECT_REF_CNT(node)((node->refcount + node->opencount + node->grprefcount
))
== 0) &&
161 (node->status & STAT_INIT_DONE0x004) &&
162 ((node->status & STAT_FINI_DONE0x008) == 0) &&
163 (!skip_initfirst ||
164 (node->obj_flags & DF_1_INITFIRST0x00000020) == 0)) {
165 struct object_vector vec = node->child_vec;
166 int i;
167
168 for (i = 0; i < vec.len; i++)
169 vec.vec[i]->status &= ~STAT_FINI_READY0x010;
170 }
171 }
172
173
174 for (node = _dl_objects;
175 node != NULL((void*)0);
176 node = node->next ) {
177 if (node->status & STAT_FINI_READY0x010) {
178 fini_complete = 0;
179 node->status |= STAT_FINI_DONE0x008;
180 node->status &= ~STAT_FINI_READY0x010;
181 _dl_run_dtors(node);
182 }
183 }
184
185 if (fini_complete && initfirst_skipped)
186 fini_complete = initfirst_skipped = skip_initfirst = 0;
187 }
188}
189
190/*
191 * Routine to walk through all of the objects except the first
192 * (main executable).
193 *
194 * Big question, should dlopen()ed objects be unloaded before or after
195 * the destructor for the main application runs?
196 */
197void
198_dl_dtors(void)
199{
200 _dl_thread_kern_stop();
201
202 /* ORDER? */
203 _dl_unload_dlopen();
204
205 DL_DEB(("doing dtors\n"))do { if (_dl_debug) _dl_printf ("doing dtors\n") ; } while (0
)
;
206
207 _dl_objects->opencount--;
208 _dl_notify_unload_shlib(_dl_objects);
209
210 _dl_run_all_dtors();
211}
212
213#if DO_CLEAN_BOOT1
214void
215_dl_clean_boot(void)
216{
217 extern char boot_text_start[], boot_text_end[];
218#if 0 /* XXX breaks boehm-gc?!? */
219 extern char boot_data_start[], boot_data_end[];
220#endif
221
222 _dl_munmap(boot_text_start, boot_text_end - boot_text_start);
223#if 0 /* XXX breaks boehm-gc?!? */
224 _dl_munmap(boot_data_start, boot_data_end - boot_data_start);
225#endif
226}
227#endif /* DO_CLEAN_BOOT */
228
229void
230_dl_dopreload(char *paths)
231{
232 char *cp, *dp;
233 elf_object_t *shlib;
234 int count;
235
236 dp = paths = _dl_strdup(paths);
237 if (dp == NULL((void*)0))
238 _dl_oom();
239
240 /* preallocate child_vec for the LD_PRELOAD objects */
241 count = 1;
242 while (*dp++ != '\0')
243 if (*dp == ':')
244 count++;
245 object_vec_grow(&_dl_objects->child_vec, count);
246
247 dp = paths;
248 while ((cp = _dl_strsep(&dp, ":")) != NULL((void*)0)) {
249 shlib = _dl_load_shlib(cp, _dl_objects, OBJTYPE_LIB3,
250 _dl_objects->obj_flags);
251 if (shlib == NULL((void*)0))
252 _dl_die("can't preload library '%s'", cp);
253 _dl_add_object(shlib);
254 _dl_link_child(shlib, _dl_objects);
255 }
256 _dl_free(paths);
257 return;
258}
259
260/*
261 * grab interesting environment variables, zap bad env vars if
262 * issetugid, and set the exported environ and __progname variables
263 */
264void
265_dl_setup_env(const char *argv0, char **envp)
266{
267 static char progname_storage[NAME_MAX255+1] = "";
268
269 /*
270 * Don't allow someone to change the search paths if he runs
271 * a suid program without credentials high enough.
272 */
273 _dl_trust = !_dl_issetugid();
274 if (!_dl_trust) { /* Zap paths if s[ug]id... */
275 _dl_unsetenv("LD_DEBUG", envp);
276 _dl_unsetenv("LD_LIBRARY_PATH", envp);
277 _dl_unsetenv("LD_PRELOAD", envp);
278 _dl_unsetenv("LD_BIND_NOW", envp);
279 } else {
280 /*
281 * Get paths to various things we are going to use.
282 */
283 _dl_debug = _dl_getenv("LD_DEBUG", envp) != NULL((void*)0);
284 _dl_libpath = _dl_split_path(_dl_getenv("LD_LIBRARY_PATH",
285 envp));
286 _dl_preload = _dl_getenv("LD_PRELOAD", envp);
287 _dl_bindnow = _dl_getenv("LD_BIND_NOW", envp) != NULL((void*)0);
288 }
289
290 /* these are usable even in setugid processes */
291 _dl_traceld = _dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL((void*)0);
292 _dl_tracefmt1 = _dl_getenv("LD_TRACE_LOADED_OBJECTS_FMT1", envp);
293 _dl_tracefmt2 = _dl_getenv("LD_TRACE_LOADED_OBJECTS_FMT2", envp);
294 _dl_traceprog = _dl_getenv("LD_TRACE_LOADED_OBJECTS_PROGNAME", envp);
295
296 environ = envp;
297
298 _dl_trace_setup(envp);
299
300 if (argv0 != NULL((void*)0)) { /* NULL ptr if argc = 0 */
301 const char *p = _dl_strrchr(argv0, '/');
302
303 if (p == NULL((void*)0))
304 p = argv0;
305 else
306 p++;
307 _dl_strlcpy(progname_storage, p, sizeof(progname_storage));
308 }
309 __progname = progname_storage;
310}
311
312int
313_dl_load_dep_libs(elf_object_t *object, int flags, int booting)
314{
315 elf_object_t *dynobj;
316 Elf_DynElf64_Dyn *dynp;
317 unsigned int loop;
318 int libcount;
319 int depflags;
320
321 dynobj = object;
322 while (dynobj) {
323 DL_DEB(("examining: '%s'\n", dynobj->load_name))do { if (_dl_debug) _dl_printf ("examining: '%s'\n", dynobj->
load_name) ; } while (0)
;
324 libcount = 0;
325
326 /* propagate DF_1_NOW to deplibs (can be set by dynamic tags) */
327 depflags = flags | (dynobj->obj_flags & DF_1_NOW0x00000001);
328
329 for (dynp = dynobj->load_dyn; dynp->d_tag; dynp++) {
330 if (dynp->d_tag == DT_NEEDED1) {
331 libcount++;
332 }
333 }
334
335 if ( libcount != 0) {
336 struct listent {
337 Elf_DynElf64_Dyn *dynp;
338 elf_object_t *depobj;
339 } *liblist;
340 int *randomlist;
341
342 liblist = _dl_reallocarray(NULL((void*)0), libcount,
343 sizeof(struct listent));
344 randomlist = _dl_reallocarray(NULL((void*)0), libcount,
345 sizeof(int));
346
347 if (liblist == NULL((void*)0) || randomlist == NULL((void*)0))
348 _dl_oom();
349
350 for (dynp = dynobj->load_dyn, loop = 0; dynp->d_tag;
351 dynp++)
352 if (dynp->d_tag == DT_NEEDED1)
353 liblist[loop++].dynp = dynp;
354
355 /* Randomize these */
356 for (loop = 0; loop < libcount; loop++)
357 randomlist[loop] = loop;
358
359 for (loop = 1; loop < libcount; loop++) {
360 unsigned int rnd;
361 int cur;
362 rnd = _dl_arc4random();
363 rnd = rnd % (loop+1);
364 cur = randomlist[rnd];
365 randomlist[rnd] = randomlist[loop];
366 randomlist[loop] = cur;
367 }
368
369 for (loop = 0; loop < libcount; loop++) {
370 elf_object_t *depobj;
371 const char *libname;
372 libname = dynobj->dynDyn.u.strtab;
373 libname +=
374 liblist[randomlist[loop]].dynp->d_un.d_val;
375 DL_DEB(("loading: %s required by %s\n", libname,do { if (_dl_debug) _dl_printf ("loading: %s required by %s\n"
, libname, dynobj->load_name) ; } while (0)
376 dynobj->load_name))do { if (_dl_debug) _dl_printf ("loading: %s required by %s\n"
, libname, dynobj->load_name) ; } while (0)
;
377 depobj = _dl_load_shlib(libname, dynobj,
378 OBJTYPE_LIB3, depflags);
379 if (depobj == 0) {
380 if (booting) {
381 _dl_die(
382 "can't load library '%s'",
383 libname);
384 }
385 DL_DEB(("dlopen: failed to open %s\n",do { if (_dl_debug) _dl_printf ("dlopen: failed to open %s\n"
, libname) ; } while (0)
386 libname))do { if (_dl_debug) _dl_printf ("dlopen: failed to open %s\n"
, libname) ; } while (0)
;
387 _dl_free(liblist);
388 _dl_free(randomlist);
389 return (1);
390 }
391 liblist[randomlist[loop]].depobj = depobj;
392 }
393
394 object_vec_grow(&dynobj->child_vec, libcount);
395 for (loop = 0; loop < libcount; loop++) {
396 _dl_add_object(liblist[loop].depobj);
397 _dl_link_child(liblist[loop].depobj, dynobj);
398 }
399 _dl_free(liblist);
400 _dl_free(randomlist);
401 }
402 dynobj = dynobj->next;
403 }
404
405 _dl_cache_grpsym_list_setup(object);
406
407 return(0);
408}
409
410
411/* do any RWX -> RX fixups for executable PLTs and apply GNU_RELRO */
412static inline void
413_dl_self_relro(long loff)
414{
415 Elf_EhdrElf64_Ehdr *ehdp;
416 Elf_PhdrElf64_Phdr *phdp;
417 int i;
418
419 ehdp = (Elf_EhdrElf64_Ehdr *)loff;
420 phdp = (Elf_PhdrElf64_Phdr *)(loff + ehdp->e_phoff);
421 for (i = 0; i < ehdp->e_phnum; i++, phdp++) {
422 switch (phdp->p_type) {
423#if defined(__alpha__) || defined(__hppa__) || defined(__powerpc__) || \
424 defined(__sparc64__)
425 case PT_LOAD1:
426 if ((phdp->p_flags & (PF_X0x1 | PF_W0x2)) != (PF_X0x1 | PF_W0x2))
427 break;
428 _dl_mprotect((void *)(phdp->p_vaddr + loff),
429 phdp->p_memsz, PROT_READ0x01);
430 break;
431#endif
432 case PT_GNU_RELRO0x6474e552:
433 _dl_mprotect((void *)(phdp->p_vaddr + loff),
434 phdp->p_memsz, PROT_READ0x01);
435 break;
436 }
437 }
438}
439
440
441#define PFLAGS(X)((((X) & 0x4) ? 0x01 : 0) | (((X) & 0x2) ? 0x02 : 0) |
(((X) & 0x1) ? 0x04 : 0))
((((X) & PF_R0x4) ? PROT_READ0x01 : 0) | \
442 (((X) & PF_W0x2) ? PROT_WRITE0x02 : 0) | \
443 (((X) & PF_X0x1) ? PROT_EXEC0x04 : 0))
444
445/*
446 * This is the dynamic loader entrypoint. When entering here, depending
447 * on architecture type, the stack and registers are set up according
448 * to the architectures ABI specification. The first thing required
449 * to do is to dig out all information we need to accomplish our task.
450 */
451unsigned long
452_dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
453{
454 struct elf_object *exe_obj; /* Pointer to executable object */
455 struct elf_object *dyn_obj; /* Pointer to ld.so object */
456 struct r_debug **map_link; /* Where to put pointer for gdb */
457 struct r_debug *debug_map;
458 struct load_list *next_load, *load_list = NULL((void*)0);
459 Elf_DynElf64_Dyn *dynp;
460 Elf_PhdrElf64_Phdr *phdp;
461 Elf_EhdrElf64_Ehdr *ehdr;
462 char *us = NULL((void*)0);
463 unsigned int loop;
464 int failed;
465 struct dep_node *n;
466 Elf_AddrElf64_Addr minva, maxva, exe_loff, exec_end, cur_exec_end;
467 Elf_AddrElf64_Addr relro_addr = 0, relro_size = 0;
468 Elf_PhdrElf64_Phdr *ptls = NULL((void*)0);
469 int align;
470
471 if (dl_data[AUX_pagesz] != 0)
472 _dl_pagesz = dl_data[AUX_pagesz];
473 _dl_malloc_init();
474
475 _dl_argv = argv;
476 while (_dl_argv[_dl_argc] != NULL((void*)0))
477 _dl_argc++;
478 _dl_setup_env(argv[0], envp);
479
480 /*
481 * Make read-only the GOT and PLT and variables initialized
482 * during the ld.so setup above.
483 */
484 _dl_self_relro(dyn_loff);
485
486 align = _dl_pagesz - 1;
487
488#define ROUND_PG(x)(((x) + align) & ~(align)) (((x) + align) & ~(align))
489#define TRUNC_PG(x)((x) & ~(align)) ((x) & ~(align))
490
491 if (_dl_bindnow) {
492 /* Lazy binding disabled, so disable kbind */
493 _dl_kbind(NULL((void*)0), 0, 0);
494 }
495
496 DL_DEB(("ld.so loading: '%s'\n", __progname))do { if (_dl_debug) _dl_printf ("ld.so loading: '%s'\n", __progname
) ; } while (0)
;
497
498 /* init this in runtime, not statically */
499 TAILQ_INIT(&_dlopened_child_list)do { (&_dlopened_child_list)->tqh_first = ((void*)0); (
&_dlopened_child_list)->tqh_last = &(&_dlopened_child_list
)->tqh_first; } while (0)
;
500
501 exe_obj = NULL((void*)0);
502 _dl_loading_object = NULL((void*)0);
503
504 minva = ELF_NO_ADDR((__uint64_t) ~0);
505 maxva = exe_loff = exec_end = 0;
506
507 /*
508 * Examine the user application and set up object information.
509 */
510 phdp = (Elf_PhdrElf64_Phdr *)dl_data[AUX_phdr];
511 for (loop = 0; loop < dl_data[AUX_phnum]; loop++) {
512 switch (phdp->p_type) {
513 case PT_PHDR6:
514 exe_loff = (Elf_AddrElf64_Addr)dl_data[AUX_phdr] - phdp->p_vaddr;
515 us += exe_loff;
516 DL_DEB(("exe load offset: 0x%lx\n", exe_loff))do { if (_dl_debug) _dl_printf ("exe load offset: 0x%lx\n", exe_loff
) ; } while (0)
;
517 break;
518 case PT_DYNAMIC2:
519 minva = TRUNC_PG(minva)((minva) & ~(align));
520 maxva = ROUND_PG(maxva)(((maxva) + align) & ~(align));
521 exe_obj = _dl_finalize_object(argv[0] ? argv[0] : "",
522 (Elf_DynElf64_Dyn *)(phdp->p_vaddr + exe_loff),
523 (Elf_PhdrElf64_Phdr *)dl_data[AUX_phdr],
524 dl_data[AUX_phnum], OBJTYPE_EXE2, minva + exe_loff,
525 exe_loff);
526 _dl_add_object(exe_obj);
527 break;
528 case PT_INTERP3:
529 us += phdp->p_vaddr;
530 break;
531 case PT_LOAD1:
532 if (phdp->p_vaddr < minva)
533 minva = phdp->p_vaddr;
534 if (phdp->p_vaddr > maxva)
535 maxva = phdp->p_vaddr + phdp->p_memsz;
536
537 next_load = _dl_calloc(1, sizeof(struct load_list));
538 if (next_load == NULL((void*)0))
539 _dl_oom();
540 next_load->next = load_list;
541 load_list = next_load;
542 next_load->start = (char *)TRUNC_PG(phdp->p_vaddr)((phdp->p_vaddr) & ~(align)) + exe_loff;
543 next_load->size = (phdp->p_vaddr & align) + phdp->p_filesz;
544 next_load->prot = PFLAGS(phdp->p_flags)((((phdp->p_flags) & 0x4) ? 0x01 : 0) | (((phdp->p_flags
) & 0x2) ? 0x02 : 0) | (((phdp->p_flags) & 0x1) ? 0x04
: 0))
;
545 cur_exec_end = (Elf_AddrElf64_Addr)next_load->start + next_load->size;
546 if ((next_load->prot & PROT_EXEC0x04) != 0 &&
547 cur_exec_end > exec_end)
548 exec_end = cur_exec_end;
549 break;
550 case PT_TLS7:
551 if (phdp->p_filesz > phdp->p_memsz)
552 _dl_die("invalid tls data");
553 ptls = phdp;
554 break;
555 case PT_GNU_RELRO0x6474e552:
556 relro_addr = phdp->p_vaddr + exe_loff;
557 relro_size = phdp->p_memsz;
558 break;
559 }
560 phdp++;
561 }
562 exe_obj->load_list = load_list;
563 exe_obj->obj_flags |= DF_1_GLOBAL0x00000002;
564 exe_obj->load_size = maxva - minva;
565 exe_obj->relro_addr = relro_addr;
566 exe_obj->relro_size = relro_size;
567 _dl_set_sod(exe_obj->load_name, &exe_obj->sod);
568
569#ifdef __i386__
570 if (exec_end > I386_MAX_EXE_ADDR)
571 _dl_exec_hint = (void *)ROUND_PG(exec_end-I386_MAX_EXE_ADDR)(((exec_end-I386_MAX_EXE_ADDR) + align) & ~(align));
572 DL_DEB(("_dl_exec_hint: 0x%lx\n", _dl_exec_hint))do { if (_dl_debug) _dl_printf ("_dl_exec_hint: 0x%lx\n", _dl_exec_hint
) ; } while (0)
;
573#endif
574
575 /* TLS bits in the base executable */
576 if (ptls != NULL((void*)0) && ptls->p_memsz)
577 _dl_set_tls(exe_obj, ptls, exe_loff, NULL((void*)0));
578
579 n = _dl_malloc(sizeof *n);
580 if (n == NULL((void*)0))
581 _dl_oom();
582 n->data = exe_obj;
583 TAILQ_INSERT_TAIL(&_dlopened_child_list, n, next_sib)do { (n)->next_sib.tqe_next = ((void*)0); (n)->next_sib
.tqe_prev = (&_dlopened_child_list)->tqh_last; *(&
_dlopened_child_list)->tqh_last = (n); (&_dlopened_child_list
)->tqh_last = &(n)->next_sib.tqe_next; } while (0)
;
584 exe_obj->opencount++;
585
586 if (_dl_preload != NULL((void*)0))
587 _dl_dopreload(_dl_preload);
588
589 _dl_load_dep_libs(exe_obj, exe_obj->obj_flags, 1);
590
591 /*
592 * Now add the dynamic loader itself last in the object list
593 * so we can use the _dl_ code when serving dl.... calls.
594 * Intentionally left off the exe child_vec.
595 */
596 dynp = (Elf_DynElf64_Dyn *)((void *)_DYNAMIC);
597 ehdr = (Elf_EhdrElf64_Ehdr *)dl_data[AUX_base];
598 dyn_obj = _dl_finalize_object(us, dynp,
599 (Elf_PhdrElf64_Phdr *)((char *)dl_data[AUX_base] + ehdr->e_phoff),
600 ehdr->e_phnum, OBJTYPE_LDR1, dl_data[AUX_base], dyn_loff);
601 _dl_add_object(dyn_obj);
602
603 dyn_obj->refcount++;
604 _dl_link_grpsym(dyn_obj);
605
606 dyn_obj->status |= STAT_RELOC_DONE0x001;
607 _dl_set_sod(dyn_obj->load_name, &dyn_obj->sod);
608
609 /* calculate the offsets for static TLS allocations */
610 _dl_allocate_tls_offsets();
611
612 /*
613 * Make something to help gdb when poking around in the code.
614 * Do this poking at the .dynamic section now, before relocation
615 * renders it read-only
616 */
617 map_link = NULL((void*)0);
618#ifdef __mips__
619 if (exe_obj->Dyn.info[DT_MIPS_RLD_MAP - DT_LOPROC0x70000000 + DT_NUM(36 + 1)] != 0)
620 map_link = (struct r_debug **)(exe_obj->Dyn.info[
621 DT_MIPS_RLD_MAP - DT_LOPROC0x70000000 + DT_NUM(36 + 1)] + exe_loff);
622#endif
623 if (map_link == NULL((void*)0)) {
624 for (dynp = exe_obj->load_dyn; dynp->d_tag; dynp++) {
625 if (dynp->d_tag == DT_DEBUG21) {
626 map_link = (struct r_debug **)&dynp->d_un.d_ptr;
627 break;
628 }
629 }
630 if (dynp->d_tag != DT_DEBUG21)
631 DL_DEB(("failed to mark DTDEBUG\n"))do { if (_dl_debug) _dl_printf ("failed to mark DTDEBUG\n") ;
} while (0)
;
632 }
633 if (map_link) {
634 debug_map = _dl_malloc(sizeof(*debug_map));
635 if (debug_map == NULL((void*)0))
636 _dl_oom();
637 debug_map->r_version = 1;
638 debug_map->r_map = (struct link_map *)_dl_objects;
639 debug_map->r_brk = (Elf_AddrElf64_Addr)_dl_debug_state;
640 debug_map->r_state = RT_CONSISTENT;
641 debug_map->r_ldbase = dyn_loff;
642 _dl_debug_map = debug_map;
643#ifdef __mips__
644 relro_addr = exe_obj->relro_addr;
645 if (dynp->d_tag == DT_DEBUG21 &&
646 ((Elf_AddrElf64_Addr)map_link + sizeof(*map_link) <= relro_addr ||
647 (Elf_AddrElf64_Addr)map_link >= relro_addr + exe_obj->relro_size)) {
648 _dl_mprotect(map_link, sizeof(*map_link),
649 PROT_READ0x01|PROT_WRITE0x02);
650 *map_link = _dl_debug_map;
651 _dl_mprotect(map_link, sizeof(*map_link),
652 PROT_READ0x01|PROT_EXEC0x04);
653 } else
654#endif
655 *map_link = _dl_debug_map;
656 }
657
658
659 /*
660 * Everything should be in place now for doing the relocation
661 * and binding. Call _dl_rtld to do the job. Fingers crossed.
662 */
663
664 failed = 0;
665 if (!_dl_traceld)
666 failed = _dl_rtld(_dl_objects);
667
668 if (_dl_debug || _dl_traceld) {
669 if (_dl_traceld)
670 _dl_pledge("stdio rpath", NULL((void*)0));
671 _dl_show_objects();
672 }
673
674 DL_DEB(("dynamic loading done, %s.\n",do { if (_dl_debug) _dl_printf ("dynamic loading done, %s.\n"
, (failed == 0) ? "success":"failed") ; } while (0)
675 (failed == 0) ? "success":"failed"))do { if (_dl_debug) _dl_printf ("dynamic loading done, %s.\n"
, (failed == 0) ? "success":"failed") ; } while (0)
;
676
677 if (failed != 0)
678 _dl_die("relocation failed");
679
680 if (_dl_traceld)
681 _dl_exit(0);
682
683 _dl_loading_object = NULL((void*)0);
684
685 /* set up the TIB for the initial thread */
686 _dl_allocate_first_tib();
687
688 _dl_fixup_user_env();
689
690 _dl_debug_state();
691
692 /*
693 * Do not run init code if run from ldd.
694 */
695 if (_dl_objects->next != NULL((void*)0)) {
696 _dl_call_preinit(_dl_objects);
697 _dl_call_init(_dl_objects);
698 }
699
700 DL_DEB(("entry point: 0x%lx\n", dl_data[AUX_entry]))do { if (_dl_debug) _dl_printf ("entry point: 0x%lx\n", dl_data
[AUX_entry]) ; } while (0)
;
701
702 /*
703 * Return the entry point.
704 */
705 return(dl_data[AUX_entry]);
706}
707
708int
709_dl_rtld(elf_object_t *object)
710{
711 struct load_list *llist;
712 int fails = 0;
713
714 if (object->next)
715 fails += _dl_rtld(object->next);
Value stored to 'fails' is never read
716
717 if (object->status & STAT_RELOC_DONE0x001)
718 return 0;
719
720 /*
721 * Do relocation information first, then GOT.
722 */
723 unprotect_if_textrel(object);
724 _dl_rreloc(object);
725 fails =_dl_md_reloc(object, DT_REL17, DT_RELSZ18);
726 fails += _dl_md_reloc(object, DT_RELA7, DT_RELASZ8);
727 reprotect_if_textrel(object);
728
729 /*
730 * We do lazy resolution by default, doing eager resolution if
731 * - the object requests it with -znow, OR
732 * - LD_BIND_NOW is set and this object isn't being ltraced
733 *
734 * Note that -znow disables ltrace for the object: on at least
735 * amd64 'ld' doesn't generate the trampoline for lazy relocation
736 * when -znow is used.
737 */
738 fails += _dl_md_reloc_got(object, !(object->obj_flags & DF_1_NOW0x00000001) &&
739 !(_dl_bindnow && !object->traced));
740
741 /*
742 * Look for W&X segments and make them read-only.
743 */
744 for (llist = object->load_list; llist != NULL((void*)0); llist = llist->next) {
745 if ((llist->prot & PROT_WRITE0x02) && (llist->prot & PROT_EXEC0x04)) {
746 _dl_mprotect(llist->start, llist->size,
747 llist->prot & ~PROT_WRITE0x02);
748 }
749 }
750
751 if (fails == 0)
752 object->status |= STAT_RELOC_DONE0x001;
753
754 return (fails);
755}
756
757void
758_dl_call_preinit(elf_object_t *object)
759{
760 if (object->dynDyn.u.preinit_array) {
761 int num = object->dynDyn.u.preinit_arraysz / sizeof(Elf_AddrElf64_Addr);
762 int i;
763
764 DL_DEB(("doing preinitarray obj %p @%p: [%s]\n",do { if (_dl_debug) _dl_printf ("doing preinitarray obj %p @%p: [%s]\n"
, object, object->Dyn.u.preinit_array, object->load_name
) ; } while (0)
765 object, object->dyn.preinit_array, object->load_name))do { if (_dl_debug) _dl_printf ("doing preinitarray obj %p @%p: [%s]\n"
, object, object->Dyn.u.preinit_array, object->load_name
) ; } while (0)
;
766 for (i = 0; i < num; i++)
767 (*object->dynDyn.u.preinit_array[i])(_dl_argc, _dl_argv,
768 environ, &_dl_cb_cb);
769 }
770}
771
772void
773_dl_call_init(elf_object_t *object)
774{
775 _dl_call_init_recurse(object, 1);
776 _dl_call_init_recurse(object, 0);
777}
778
779static void
780_dl_relro(elf_object_t *object)
781{
782 /*
783 * Handle GNU_RELRO
784 */
785 if (object->relro_addr != 0 && object->relro_size != 0) {
786 Elf_AddrElf64_Addr addr = object->relro_addr;
787
788 DL_DEB(("protect RELRO [0x%lx,0x%lx) in %s\n",do { if (_dl_debug) _dl_printf ("protect RELRO [0x%lx,0x%lx) in %s\n"
, addr, addr + object->relro_size, object->load_name) ;
} while (0)
789 addr, addr + object->relro_size, object->load_name))do { if (_dl_debug) _dl_printf ("protect RELRO [0x%lx,0x%lx) in %s\n"
, addr, addr + object->relro_size, object->load_name) ;
} while (0)
;
790 _dl_mprotect((void *)addr, object->relro_size, PROT_READ0x01);
791 }
792}
793
794void
795_dl_call_init_recurse(elf_object_t *object, int initfirst)
796{
797 struct object_vector vec;
798 int visited_flag = initfirst ? STAT_VISIT_INITFIRST0x100 : STAT_VISIT_INIT0x200;
799 int i;
800
801 object->status |= visited_flag;
802
803 for (vec = object->child_vec, i = 0; i < vec.len; i++) {
804 if (vec.vec[i]->status & visited_flag)
805 continue;
806 _dl_call_init_recurse(vec.vec[i], initfirst);
807 }
808
809 if (object->status & STAT_INIT_DONE0x004)
810 return;
811
812 if (initfirst && (object->obj_flags & DF_1_INITFIRST0x00000020) == 0)
813 return;
814
815 if (!initfirst)
816 _dl_relro(object);
817
818 if (object->dynDyn.u.init) {
819 DL_DEB(("doing ctors obj %p @%p: [%s]\n",do { if (_dl_debug) _dl_printf ("doing ctors obj %p @%p: [%s]\n"
, object, object->Dyn.u.init, object->load_name) ; } while
(0)
820 object, object->dyn.init, object->load_name))do { if (_dl_debug) _dl_printf ("doing ctors obj %p @%p: [%s]\n"
, object, object->Dyn.u.init, object->load_name) ; } while
(0)
;
821 (*object->dynDyn.u.init)();
822 }
823
824 if (object->dynDyn.u.init_array) {
825 int num = object->dynDyn.u.init_arraysz / sizeof(Elf_AddrElf64_Addr);
826 int i;
827
828 DL_DEB(("doing initarray obj %p @%p: [%s]\n",do { if (_dl_debug) _dl_printf ("doing initarray obj %p @%p: [%s]\n"
, object, object->Dyn.u.init_array, object->load_name) ;
} while (0)
829 object, object->dyn.init_array, object->load_name))do { if (_dl_debug) _dl_printf ("doing initarray obj %p @%p: [%s]\n"
, object, object->Dyn.u.init_array, object->load_name) ;
} while (0)
;
830 for (i = 0; i < num; i++)
831 (*object->dynDyn.u.init_array[i])(_dl_argc, _dl_argv,
832 environ, &_dl_cb_cb);
833 }
834
835 if (initfirst)
836 _dl_relro(object);
837
838 object->status |= STAT_INIT_DONE0x004;
839}
840
841char *
842_dl_getenv(const char *var, char **env)
843{
844 const char *ep;
845
846 while ((ep = *env++)) {
847 const char *vp = var;
848
849 while (*vp && *vp == *ep) {
850 vp++;
851 ep++;
852 }
853 if (*vp == '\0' && *ep++ == '=')
854 return((char *)ep);
855 }
856 return(NULL((void*)0));
857}
858
859void
860_dl_unsetenv(const char *var, char **env)
861{
862 char *ep;
863
864 while ((ep = *env)) {
865 const char *vp = var;
866
867 while (*vp && *vp == *ep) {
868 vp++;
869 ep++;
870 }
871 if (*vp == '\0' && *ep++ == '=') {
872 char **P;
873
874 for (P = env;; ++P)
875 if (!(*P = *(P + 1)))
876 break;
877 } else
878 env++;
879 }
880}
881
882static inline void
883fixup_sym(struct elf_object *dummy_obj, const char *name, void *addr)
884{
885 struct sym_res sr;
886
887 sr = _dl_find_symbol(name, SYM_SEARCH_ALL0x00|SYM_NOWARNNOTFOUND0x00|SYM_PLT0x20,
888 NULL((void*)0), dummy_obj);
889 if (sr.sym != NULL((void*)0)) {
890 void *p = (void *)(sr.sym->st_value + sr.obj->obj_base);
891 if (p != addr) {
892 DL_DEB(("setting %s %p@%s[%p] from %p\n", name,do { if (_dl_debug) _dl_printf ("setting %s %p@%s[%p] from %p\n"
, name, p, sr.obj->load_name, (void *)sr.obj, addr) ; } while
(0)
893 p, sr.obj->load_name, (void *)sr.obj, addr))do { if (_dl_debug) _dl_printf ("setting %s %p@%s[%p] from %p\n"
, name, p, sr.obj->load_name, (void *)sr.obj, addr) ; } while
(0)
;
894 *(void **)p = *(void **)addr;
895 }
896 }
897}
898
899/*
900 * _dl_fixup_user_env()
901 *
902 * Set the user environment so that programs can use the environment
903 * while running constructors. Specifically, MALLOC_OPTIONS= for malloc()
904 */
905void
906_dl_fixup_user_env(void)
907{
908 struct elf_object dummy_obj;
909
910 dummy_obj.dynDyn.u.symbolic = 0;
911 dummy_obj.load_name = "ld.so";
912 fixup_sym(&dummy_obj, "environ", &environ);
913 fixup_sym(&dummy_obj, "__progname", &__progname);
914}
915
916const void *
917_dl_cb_cb(int version)
918{
919 DL_DEB(("version %d callbacks requested\n", version))do { if (_dl_debug) _dl_printf ("version %d callbacks requested\n"
, version) ; } while (0)
;
920 if (version == 0)
921 return &callbacks_0;
922 return NULL((void*)0);
923}
924
925static inline void
926unprotect_if_textrel(elf_object_t *object)
927{
928 struct load_list *ll;
929
930 if (__predict_false(object->dyn.textrel == 1)__builtin_expect(((object->Dyn.u.textrel == 1) != 0), 0)) {
931 for (ll = object->load_list; ll != NULL((void*)0); ll = ll->next) {
932 if ((ll->prot & PROT_WRITE0x02) == 0)
933 _dl_mprotect(ll->start, ll->size,
934 PROT_READ0x01 | PROT_WRITE0x02);
935 }
936 }
937}
938
939static inline void
940reprotect_if_textrel(elf_object_t *object)
941{
942 struct load_list *ll;
943
944 if (__predict_false(object->dyn.textrel == 1)__builtin_expect(((object->Dyn.u.textrel == 1) != 0), 0)) {
945 for (ll = object->load_list; ll != NULL((void*)0); ll = ll->next) {
946 if ((ll->prot & PROT_WRITE0x02) == 0)
947 _dl_mprotect(ll->start, ll->size, ll->prot);
948 }
949 }
950}
951
952static void
953_dl_rreloc(elf_object_t *object)
954{
955 const Elf_RelrElf64_Relr *reloc, *rend;
956 Elf_AddrElf64_Addr loff = object->obj_base;
957
958 reloc = object->dynDyn.u.relr;
959 rend = (const Elf_RelrElf64_Relr *)((char *)reloc + object->dynDyn.u.relrsz);
960
961 while (reloc < rend) {
962 Elf_AddrElf64_Addr *where;
963
964 where = (Elf_AddrElf64_Addr *)(*reloc + loff);
965 *where++ += loff;
966
967 for (reloc++; reloc < rend && (*reloc & 1); reloc++) {
968 Elf_AddrElf64_Addr bits = *reloc >> 1;
969
970 Elf_AddrElf64_Addr *here = where;
971 while (bits != 0) {
972 if (bits & 1) {
973 *here += loff;
974 }
975 bits >>= 1;
976 here++;
977 }
978 where += (8 * sizeof *reloc) - 1;
979 }
980 }
981}
982