git: 7e2f38311e62 - main - rtld-elf/rtld.c: apply clang-format
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 21 Jan 2025 01:51:00 UTC
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=7e2f38311e62b1a3ba4a023042f2dc36e27cdd06 commit 7e2f38311e62b1a3ba4a023042f2dc36e27cdd06 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2025-01-18 02:26:16 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2025-01-21 01:44:12 +0000 rtld-elf/rtld.c: apply clang-format Discussed with: emaste, imp Sponsored by: The FreeBSD Foundation Differential revision: https://reviews.freebsd.org/D48509 --- libexec/rtld-elf/rtld.c | 5914 ++++++++++++++++++++++++----------------------- 1 file changed, 2993 insertions(+), 2921 deletions(-) diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 70230a8e0199..8ec883227908 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -39,13 +39,13 @@ */ #include <sys/param.h> -#include <sys/mount.h> +#include <sys/ktrace.h> #include <sys/mman.h> +#include <sys/mount.h> #include <sys/stat.h> #include <sys/sysctl.h> #include <sys/uio.h> #include <sys/utsname.h> -#include <sys/ktrace.h> #include <dlfcn.h> #include <err.h> @@ -58,20 +58,19 @@ #include <unistd.h> #include "debug.h" -#include "rtld.h" #include "libmap.h" +#include "notes.h" +#include "rtld.h" +#include "rtld_libc.h" +#include "rtld_malloc.h" #include "rtld_paths.h" -#include "rtld_tls.h" #include "rtld_printf.h" -#include "rtld_malloc.h" +#include "rtld_tls.h" #include "rtld_utrace.h" -#include "notes.h" -#include "rtld_libc.h" /* Types. */ typedef void (*func_ptr_type)(void); -typedef void * (*path_enum_proc) (const char *path, size_t len, void *arg); - +typedef void *(*path_enum_proc)(const char *path, size_t len, void *arg); /* Variables that cannot be static: */ extern struct r_debug r_debug; /* For GDB */ @@ -138,7 +137,7 @@ static void objlist_put_after(Objlist *, Obj_Entry *, Obj_Entry *); static void objlist_remove(Objlist *, Obj_Entry *); static int open_binary_fd(const char *argv0, bool search_in_path, const char **binpath_res); -static int parse_args(char* argv[], int argc, bool *use_pathp, int *fdp, +static int parse_args(char *argv[], int argc, bool *use_pathp, int *fdp, const char **argv0, bool *dir_ignore); static int parse_integer(const char *); static void *path_enumerate(const char *, path_enum_proc, const char *, void *); @@ -174,15 +173,15 @@ static void unlink_object(Obj_Entry *); static void unload_object(Obj_Entry *, RtldLockState *lockstate); static void unref_dag(Obj_Entry *); static void ref_dag(Obj_Entry *); -static char *origin_subst_one(Obj_Entry *, char *, const char *, - const char *, bool); +static char *origin_subst_one(Obj_Entry *, char *, const char *, const char *, + bool); static char *origin_subst(Obj_Entry *, const char *); static bool obj_resolve_origin(Obj_Entry *obj); static void preinit_main(void); -static int rtld_verify_versions(const Objlist *); -static int rtld_verify_object_versions(Obj_Entry *); +static int rtld_verify_versions(const Objlist *); +static int rtld_verify_object_versions(Obj_Entry *); static void object_add_name(Obj_Entry *, const char *); -static int object_match_name(const Obj_Entry *, const char *); +static int object_match_name(const Obj_Entry *, const char *); static void ld_utrace_log(int, void *, void *, size_t, int, const char *); static void rtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info); @@ -198,45 +197,49 @@ int __sys_openat(int, const char *, int, ...); /* * Data declarations. */ -struct r_debug r_debug __exported; /* for GDB; */ -static bool libmap_disable; /* Disable libmap */ -static bool ld_loadfltr; /* Immediate filters processing */ -static const char *libmap_override;/* Maps to use in addition to libmap.conf */ -static bool trust; /* False for setuid and setgid programs */ -static bool dangerous_ld_env; /* True if environment variables have been - used to affect the libraries loaded */ -bool ld_bind_not; /* Disable PLT update */ -static const char *ld_bind_now; /* Environment variable for immediate binding */ +struct r_debug r_debug __exported; /* for GDB; */ +static bool libmap_disable; /* Disable libmap */ +static bool ld_loadfltr; /* Immediate filters processing */ +static const char *libmap_override; /* Maps to use in addition to libmap.conf */ +static bool trust; /* False for setuid and setgid programs */ +static bool dangerous_ld_env; /* True if environment variables have been + used to affect the libraries loaded */ +bool ld_bind_not; /* Disable PLT update */ +static const char *ld_bind_now; /* Environment variable for immediate binding */ static const char *ld_debug; /* Environment variable for debugging */ static bool ld_dynamic_weak = true; /* True if non-weak definition overrides weak definition */ -static const char *ld_library_path;/* Environment variable for search path */ -static const char *ld_library_dirs;/* Environment variable for library descriptors */ -static const char *ld_preload; /* Environment variable for libraries to - load first */ -static const char *ld_preload_fds;/* Environment variable for libraries represented by - descriptors */ -static const char *ld_elf_hints_path; /* Environment variable for alternative hints path */ -static const char *ld_tracing; /* Called from ldd to print libs */ -static const char *ld_utrace; /* Use utrace() to log events. */ -static struct obj_entry_q obj_list; /* Queue of all loaded objects */ -static Obj_Entry *obj_main; /* The main program shared object */ -static Obj_Entry obj_rtld; /* The dynamic linker shared object */ -static unsigned int obj_count; /* Number of objects in obj_list */ -static unsigned int obj_loads; /* Number of loads of objects (gen count) */ -size_t ld_static_tls_extra = /* Static TLS extra space (bytes) */ - RTLD_STATIC_TLS_EXTRA; - -static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */ - STAILQ_HEAD_INITIALIZER(list_global); -static Objlist list_main = /* Objects loaded at program startup */ - STAILQ_HEAD_INITIALIZER(list_main); -static Objlist list_fini = /* Objects needing fini() calls */ - STAILQ_HEAD_INITIALIZER(list_fini); - -Elf_Sym sym_zero; /* For resolving undefined weak refs. */ - -#define GDB_STATE(s,m) r_debug.r_state = s; r_debug_state(&r_debug,m); +static const char *ld_library_path; /* Environment variable for search path */ +static const char + *ld_library_dirs; /* Environment variable for library descriptors */ +static const char *ld_preload; /* Environment variable for libraries to + load first */ +static const char *ld_preload_fds; /* Environment variable for libraries + represented by descriptors */ +static const char + *ld_elf_hints_path; /* Environment variable for alternative hints path */ +static const char *ld_tracing; /* Called from ldd to print libs */ +static const char *ld_utrace; /* Use utrace() to log events. */ +static struct obj_entry_q obj_list; /* Queue of all loaded objects */ +static Obj_Entry *obj_main; /* The main program shared object */ +static Obj_Entry obj_rtld; /* The dynamic linker shared object */ +static unsigned int obj_count; /* Number of objects in obj_list */ +static unsigned int obj_loads; /* Number of loads of objects (gen count) */ +size_t ld_static_tls_extra = /* Static TLS extra space (bytes) */ + RTLD_STATIC_TLS_EXTRA; + +static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */ + STAILQ_HEAD_INITIALIZER(list_global); +static Objlist list_main = /* Objects loaded at program startup */ + STAILQ_HEAD_INITIALIZER(list_main); +static Objlist list_fini = /* Objects needing fini() calls */ + STAILQ_HEAD_INITIALIZER(list_fini); + +Elf_Sym sym_zero; /* For resolving undefined weak refs. */ + +#define GDB_STATE(s, m) \ + r_debug.r_state = s; \ + r_debug_state(&r_debug, m); extern Elf_Dyn _DYNAMIC; #pragma weak _DYNAMIC @@ -251,7 +254,7 @@ void *dlvsym(void *, const char *, const char *) __exported; int dladdr(const void *, Dl_info *) __exported; void dllockinit(void *, void *(*)(void *), void (*)(void *), void (*)(void *), void (*)(void *), void (*)(void *), void (*)(void *)) __exported; -int dlinfo(void *, int , void *) __exported; +int dlinfo(void *, int, void *) __exported; int _dl_iterate_phdr_locked(__dl_iterate_hdr_callback, void *) __exported; int dl_iterate_phdr(__dl_iterate_hdr_callback, void *) __exported; int _rtld_addr_phdr(const void *, struct dl_phdr_info *) __exported; @@ -290,12 +293,12 @@ char **main_argv; /* * Globals to control TLS allocation. */ -size_t tls_last_offset; /* Static TLS offset of last module */ -size_t tls_last_size; /* Static TLS size of last module */ -size_t tls_static_space; /* Static TLS space allocated */ +size_t tls_last_offset; /* Static TLS offset of last module */ +size_t tls_last_size; /* Static TLS size of last module */ +size_t tls_static_space; /* Static TLS space allocated */ static size_t tls_static_max_align; -Elf_Addr tls_dtv_generation = 1; /* Used to detect when dtv size changes */ -int tls_max_index = 1; /* Largest module index allocated */ +Elf_Addr tls_dtv_generation = 1; /* Used to detect when dtv size changes */ +int tls_max_index = 1; /* Largest module index allocated */ static bool ld_library_path_rpath = false; bool ld_fast_sigblock = false; @@ -316,16 +319,16 @@ static void (*rtld_exit_ptr)(void); * the currently-loaded objects. Keep this as a macro since it calls * alloca and we want that to occur within the scope of the caller. */ -#define donelist_init(dlp) \ - ((dlp)->objs = alloca(obj_count * sizeof (dlp)->objs[0]), \ - assert((dlp)->objs != NULL), \ - (dlp)->num_alloc = obj_count, \ - (dlp)->num_used = 0) +#define donelist_init(dlp) \ + ((dlp)->objs = alloca(obj_count * sizeof(dlp)->objs[0]), \ + assert((dlp)->objs != NULL), (dlp)->num_alloc = obj_count, \ + (dlp)->num_used = 0) -#define LD_UTRACE(e, h, mb, ms, r, n) do { \ - if (ld_utrace != NULL) \ - ld_utrace_log(e, h, mb, ms, r, n); \ -} while (0) +#define LD_UTRACE(e, h, mb, ms, r, n) \ + do { \ + if (ld_utrace != NULL) \ + ld_utrace_log(e, h, mb, ms, r, n); \ + } while (0) static void ld_utrace_log(int event, void *handle, void *mapbase, size_t mapsize, @@ -347,19 +350,15 @@ ld_utrace_log(int event, void *handle, void *mapbase, size_t mapsize, } struct ld_env_var_desc { - const char * const n; + const char *const n; const char *val; - const bool unsecure:1; - const bool can_update:1; - const bool debug:1; - bool owned:1; + const bool unsecure : 1; + const bool can_update : 1; + const bool debug : 1; + bool owned : 1; }; -#define LD_ENV_DESC(var, unsec, ...) \ - [LD_##var] = { \ - .n = #var, \ - .unsecure = unsec, \ - __VA_ARGS__ \ - } +#define LD_ENV_DESC(var, unsec, ...) \ + [LD_##var] = { .n = #var, .unsecure = unsec, __VA_ARGS__ } static struct ld_env_var_desc ld_env_vars[] = { LD_ENV_DESC(BIND_NOW, false), @@ -494,506 +493,524 @@ rtld_trunc_page(uintptr_t x) func_ptr_type _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) { - Elf_Auxinfo *aux, *auxp, *auxpf, *aux_info[AT_COUNT]; - Objlist_Entry *entry; - Obj_Entry *last_interposer, *obj, *preload_tail; - const Elf_Phdr *phdr; - Objlist initlist; - RtldLockState lockstate; - struct stat st; - Elf_Addr *argcp; - char **argv, **env, **envp, *kexecpath; - const char *argv0, *binpath, *library_path_rpath, *static_tls_extra; - struct ld_env_var_desc *lvd; - caddr_t imgentry; - char buf[MAXPATHLEN]; - int argc, fd, i, mib[4], old_osrel, osrel, phnum, rtld_argc; - size_t sz; + Elf_Auxinfo *aux, *auxp, *auxpf, *aux_info[AT_COUNT]; + Objlist_Entry *entry; + Obj_Entry *last_interposer, *obj, *preload_tail; + const Elf_Phdr *phdr; + Objlist initlist; + RtldLockState lockstate; + struct stat st; + Elf_Addr *argcp; + char **argv, **env, **envp, *kexecpath; + const char *argv0, *binpath, *library_path_rpath, *static_tls_extra; + struct ld_env_var_desc *lvd; + caddr_t imgentry; + char buf[MAXPATHLEN]; + int argc, fd, i, mib[4], old_osrel, osrel, phnum, rtld_argc; + size_t sz; #ifdef __powerpc__ - int old_auxv_format = 1; + int old_auxv_format = 1; #endif - bool dir_enable, dir_ignore, direct_exec, explicit_fd, search_in_path; - - /* - * On entry, the dynamic linker itself has not been relocated yet. - * Be very careful not to reference any global data until after - * init_rtld has returned. It is OK to reference file-scope statics - * and string constants, and to call static and global functions. - */ - - /* Find the auxiliary vector on the stack. */ - argcp = sp; - argc = *sp++; - argv = (char **) sp; - sp += argc + 1; /* Skip over arguments and NULL terminator */ - env = (char **) sp; - while (*sp++ != 0) /* Skip over environment, and NULL terminator */ - ; - aux = (Elf_Auxinfo *) sp; - - /* Digest the auxiliary vector. */ - for (i = 0; i < AT_COUNT; i++) - aux_info[i] = NULL; - for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { - if (auxp->a_type < AT_COUNT) - aux_info[auxp->a_type] = auxp; + bool dir_enable, dir_ignore, direct_exec, explicit_fd, search_in_path; + + /* + * On entry, the dynamic linker itself has not been relocated yet. + * Be very careful not to reference any global data until after + * init_rtld has returned. It is OK to reference file-scope statics + * and string constants, and to call static and global functions. + */ + + /* Find the auxiliary vector on the stack. */ + argcp = sp; + argc = *sp++; + argv = (char **)sp; + sp += argc + 1; /* Skip over arguments and NULL terminator */ + env = (char **)sp; + while (*sp++ != 0) /* Skip over environment, and NULL terminator */ + ; + aux = (Elf_Auxinfo *)sp; + + /* Digest the auxiliary vector. */ + for (i = 0; i < AT_COUNT; i++) + aux_info[i] = NULL; + for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { + if (auxp->a_type < AT_COUNT) + aux_info[auxp->a_type] = auxp; #ifdef __powerpc__ - if (auxp->a_type == 23) /* AT_STACKPROT */ - old_auxv_format = 0; + if (auxp->a_type == 23) /* AT_STACKPROT */ + old_auxv_format = 0; #endif - } + } #ifdef __powerpc__ - if (old_auxv_format) { - /* Remap from old-style auxv numbers. */ - aux_info[23] = aux_info[21]; /* AT_STACKPROT */ - aux_info[21] = aux_info[19]; /* AT_PAGESIZESLEN */ - aux_info[19] = aux_info[17]; /* AT_NCPUS */ - aux_info[17] = aux_info[15]; /* AT_CANARYLEN */ - aux_info[15] = aux_info[13]; /* AT_EXECPATH */ - aux_info[13] = NULL; /* AT_GID */ - - aux_info[20] = aux_info[18]; /* AT_PAGESIZES */ - aux_info[18] = aux_info[16]; /* AT_OSRELDATE */ - aux_info[16] = aux_info[14]; /* AT_CANARY */ - aux_info[14] = NULL; /* AT_EGID */ - } + if (old_auxv_format) { + /* Remap from old-style auxv numbers. */ + aux_info[23] = aux_info[21]; /* AT_STACKPROT */ + aux_info[21] = aux_info[19]; /* AT_PAGESIZESLEN */ + aux_info[19] = aux_info[17]; /* AT_NCPUS */ + aux_info[17] = aux_info[15]; /* AT_CANARYLEN */ + aux_info[15] = aux_info[13]; /* AT_EXECPATH */ + aux_info[13] = NULL; /* AT_GID */ + + aux_info[20] = aux_info[18]; /* AT_PAGESIZES */ + aux_info[18] = aux_info[16]; /* AT_OSRELDATE */ + aux_info[16] = aux_info[14]; /* AT_CANARY */ + aux_info[14] = NULL; /* AT_EGID */ + } #endif - /* Initialize and relocate ourselves. */ - assert(aux_info[AT_BASE] != NULL); - init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr, aux_info); - - dlerror_dflt_init(); - - __progname = obj_rtld.path; - argv0 = argv[0] != NULL ? argv[0] : "(null)"; - environ = env; - main_argc = argc; - main_argv = argv; - - if (aux_info[AT_BSDFLAGS] != NULL && - (aux_info[AT_BSDFLAGS]->a_un.a_val & ELF_BSDF_SIGFASTBLK) != 0) - ld_fast_sigblock = true; - - trust = !issetugid(); - direct_exec = false; - - md_abi_variant_hook(aux_info); - rtld_init_env_vars(env); - - fd = -1; - if (aux_info[AT_EXECFD] != NULL) { - fd = aux_info[AT_EXECFD]->a_un.a_val; - } else { - assert(aux_info[AT_PHDR] != NULL); - phdr = (const Elf_Phdr *)aux_info[AT_PHDR]->a_un.a_ptr; - if (phdr == obj_rtld.phdr) { - if (!trust) { - _rtld_error("Tainted process refusing to run binary %s", - argv0); - rtld_die(); - } - direct_exec = true; - - dbg("opening main program in direct exec mode"); - if (argc >= 2) { - rtld_argc = parse_args(argv, argc, &search_in_path, &fd, - &argv0, &dir_ignore); - explicit_fd = (fd != -1); - binpath = NULL; - if (!explicit_fd) - fd = open_binary_fd(argv0, search_in_path, &binpath); - if (fstat(fd, &st) == -1) { - _rtld_error("Failed to fstat FD %d (%s): %s", fd, - explicit_fd ? "user-provided descriptor" : argv0, - rtld_strerror(errno)); - rtld_die(); - } + /* Initialize and relocate ourselves. */ + assert(aux_info[AT_BASE] != NULL); + init_rtld((caddr_t)aux_info[AT_BASE]->a_un.a_ptr, aux_info); - /* - * Rough emulation of the permission checks done by - * execve(2), only Unix DACs are checked, ACLs are - * ignored. Preserve the semantic of disabling owner - * to execute if owner x bit is cleared, even if - * others x bit is enabled. - * mmap(2) does not allow to mmap with PROT_EXEC if - * binary' file comes from noexec mount. We cannot - * set a text reference on the binary. - */ - dir_enable = false; - if (st.st_uid == geteuid()) { - if ((st.st_mode & S_IXUSR) != 0) - dir_enable = true; - } else if (st.st_gid == getegid()) { - if ((st.st_mode & S_IXGRP) != 0) - dir_enable = true; - } else if ((st.st_mode & S_IXOTH) != 0) { - dir_enable = true; - } - if (!dir_enable && !dir_ignore) { - _rtld_error("No execute permission for binary %s", - argv0); - rtld_die(); - } + dlerror_dflt_init(); - /* - * For direct exec mode, argv[0] is the interpreter - * name, we must remove it and shift arguments left - * before invoking binary main. Since stack layout - * places environment pointers and aux vectors right - * after the terminating NULL, we must shift - * environment and aux as well. - */ - main_argc = argc - rtld_argc; - for (i = 0; i <= main_argc; i++) - argv[i] = argv[i + rtld_argc]; - *argcp -= rtld_argc; - environ = env = envp = argv + main_argc + 1; - dbg("move env from %p to %p", envp + rtld_argc, envp); - do { - *envp = *(envp + rtld_argc); - } while (*envp++ != NULL); - aux = auxp = (Elf_Auxinfo *)envp; - auxpf = (Elf_Auxinfo *)(envp + rtld_argc); - dbg("move aux from %p to %p", auxpf, aux); - /* XXXKIB insert place for AT_EXECPATH if not present */ - for (;; auxp++, auxpf++) { - *auxp = *auxpf; - if (auxp->a_type == AT_NULL) - break; - } - /* Since the auxiliary vector has moved, redigest it. */ - for (i = 0; i < AT_COUNT; i++) - aux_info[i] = NULL; - for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { - if (auxp->a_type < AT_COUNT) - aux_info[auxp->a_type] = auxp; + __progname = obj_rtld.path; + argv0 = argv[0] != NULL ? argv[0] : "(null)"; + environ = env; + main_argc = argc; + main_argv = argv; + + if (aux_info[AT_BSDFLAGS] != NULL && + (aux_info[AT_BSDFLAGS]->a_un.a_val & ELF_BSDF_SIGFASTBLK) != 0) + ld_fast_sigblock = true; + + trust = !issetugid(); + direct_exec = false; + + md_abi_variant_hook(aux_info); + rtld_init_env_vars(env); + + fd = -1; + if (aux_info[AT_EXECFD] != NULL) { + fd = aux_info[AT_EXECFD]->a_un.a_val; + } else { + assert(aux_info[AT_PHDR] != NULL); + phdr = (const Elf_Phdr *)aux_info[AT_PHDR]->a_un.a_ptr; + if (phdr == obj_rtld.phdr) { + if (!trust) { + _rtld_error( + "Tainted process refusing to run binary %s", + argv0); + rtld_die(); + } + direct_exec = true; + + dbg("opening main program in direct exec mode"); + if (argc >= 2) { + rtld_argc = parse_args(argv, argc, + &search_in_path, &fd, &argv0, &dir_ignore); + explicit_fd = (fd != -1); + binpath = NULL; + if (!explicit_fd) + fd = open_binary_fd(argv0, + search_in_path, &binpath); + if (fstat(fd, &st) == -1) { + _rtld_error( + "Failed to fstat FD %d (%s): %s", + fd, + explicit_fd ? + "user-provided descriptor" : + argv0, + rtld_strerror(errno)); + rtld_die(); + } + + /* + * Rough emulation of the permission checks done + * by execve(2), only Unix DACs are checked, + * ACLs are ignored. Preserve the semantic of + * disabling owner to execute if owner x bit is + * cleared, even if others x bit is enabled. + * mmap(2) does not allow to mmap with PROT_EXEC + * if binary' file comes from noexec mount. We + * cannot set a text reference on the binary. + */ + dir_enable = false; + if (st.st_uid == geteuid()) { + if ((st.st_mode & S_IXUSR) != 0) + dir_enable = true; + } else if (st.st_gid == getegid()) { + if ((st.st_mode & S_IXGRP) != 0) + dir_enable = true; + } else if ((st.st_mode & S_IXOTH) != 0) { + dir_enable = true; + } + if (!dir_enable && !dir_ignore) { + _rtld_error( + "No execute permission for binary %s", + argv0); + rtld_die(); + } + + /* + * For direct exec mode, argv[0] is the + * interpreter name, we must remove it and shift + * arguments left before invoking binary main. + * Since stack layout places environment + * pointers and aux vectors right after the + * terminating NULL, we must shift environment + * and aux as well. + */ + main_argc = argc - rtld_argc; + for (i = 0; i <= main_argc; i++) + argv[i] = argv[i + rtld_argc]; + *argcp -= rtld_argc; + environ = env = envp = argv + main_argc + 1; + dbg("move env from %p to %p", envp + rtld_argc, + envp); + do { + *envp = *(envp + rtld_argc); + } while (*envp++ != NULL); + aux = auxp = (Elf_Auxinfo *)envp; + auxpf = (Elf_Auxinfo *)(envp + rtld_argc); + dbg("move aux from %p to %p", auxpf, aux); + /* XXXKIB insert place for AT_EXECPATH if not + * present */ + for (;; auxp++, auxpf++) { + *auxp = *auxpf; + if (auxp->a_type == AT_NULL) + break; + } + /* Since the auxiliary vector has moved, + * redigest it. */ + for (i = 0; i < AT_COUNT; i++) + aux_info[i] = NULL; + for (auxp = aux; auxp->a_type != AT_NULL; + auxp++) { + if (auxp->a_type < AT_COUNT) + aux_info[auxp->a_type] = auxp; + } + + /* Point AT_EXECPATH auxv and aux_info to the + * binary path. */ + if (binpath == NULL) { + aux_info[AT_EXECPATH] = NULL; + } else { + if (aux_info[AT_EXECPATH] == NULL) { + aux_info[AT_EXECPATH] = xmalloc( + sizeof(Elf_Auxinfo)); + aux_info[AT_EXECPATH]->a_type = + AT_EXECPATH; + } + aux_info[AT_EXECPATH]->a_un.a_ptr = + __DECONST(void *, binpath); + } + } else { + _rtld_error("No binary"); + rtld_die(); + } } + } - /* Point AT_EXECPATH auxv and aux_info to the binary path. */ - if (binpath == NULL) { - aux_info[AT_EXECPATH] = NULL; - } else { - if (aux_info[AT_EXECPATH] == NULL) { - aux_info[AT_EXECPATH] = xmalloc(sizeof(Elf_Auxinfo)); - aux_info[AT_EXECPATH]->a_type = AT_EXECPATH; - } - aux_info[AT_EXECPATH]->a_un.a_ptr = __DECONST(void *, - binpath); + ld_bind_now = ld_get_env_var(LD_BIND_NOW); + + /* + * If the process is tainted, then we un-set the dangerous environment + * variables. The process will be marked as tainted until setuid(2) + * is called. If any child process calls setuid(2) we do not want any + * future processes to honor the potentially un-safe variables. + */ + if (!trust) { + for (i = 0; i < (int)nitems(ld_env_vars); i++) { + lvd = &ld_env_vars[i]; + if (lvd->unsecure) + lvd->val = NULL; } - } else { - _rtld_error("No binary"); - rtld_die(); - } - } - } - - ld_bind_now = ld_get_env_var(LD_BIND_NOW); - - /* - * If the process is tainted, then we un-set the dangerous environment - * variables. The process will be marked as tainted until setuid(2) - * is called. If any child process calls setuid(2) we do not want any - * future processes to honor the potentially un-safe variables. - */ - if (!trust) { - for (i = 0; i < (int)nitems(ld_env_vars); i++) { - lvd = &ld_env_vars[i]; - if (lvd->unsecure) - lvd->val = NULL; - } - } - - ld_debug = ld_get_env_var(LD_DEBUG); - if (ld_bind_now == NULL) - ld_bind_not = ld_get_env_var(LD_BIND_NOT) != NULL; - ld_dynamic_weak = ld_get_env_var(LD_DYNAMIC_WEAK) == NULL; - libmap_disable = ld_get_env_var(LD_LIBMAP_DISABLE) != NULL; - libmap_override = ld_get_env_var(LD_LIBMAP); - ld_library_path = ld_get_env_var(LD_LIBRARY_PATH); - ld_library_dirs = ld_get_env_var(LD_LIBRARY_PATH_FDS); - ld_preload = ld_get_env_var(LD_PRELOAD); - ld_preload_fds = ld_get_env_var(LD_PRELOAD_FDS); - ld_elf_hints_path = ld_get_env_var(LD_ELF_HINTS_PATH); - ld_loadfltr = ld_get_env_var(LD_LOADFLTR) != NULL; - library_path_rpath = ld_get_env_var(LD_LIBRARY_PATH_RPATH); - if (library_path_rpath != NULL) { - if (library_path_rpath[0] == 'y' || - library_path_rpath[0] == 'Y' || - library_path_rpath[0] == '1') - ld_library_path_rpath = true; - else - ld_library_path_rpath = false; - } - static_tls_extra = ld_get_env_var(LD_STATIC_TLS_EXTRA); - if (static_tls_extra != NULL && static_tls_extra[0] != '\0') { - sz = parse_integer(static_tls_extra); - if (sz >= RTLD_STATIC_TLS_EXTRA && sz <= SIZE_T_MAX) - ld_static_tls_extra = sz; - } - dangerous_ld_env = libmap_disable || libmap_override != NULL || - ld_library_path != NULL || ld_preload != NULL || - ld_elf_hints_path != NULL || ld_loadfltr || !ld_dynamic_weak || - static_tls_extra != NULL; - ld_tracing = ld_get_env_var(LD_TRACE_LOADED_OBJECTS); - ld_utrace = ld_get_env_var(LD_UTRACE); - - set_ld_elf_hints_path(); - if (ld_debug != NULL && *ld_debug != '\0') - debug = 1; - dbg("%s is initialized, base address = %p", __progname, - (caddr_t) aux_info[AT_BASE]->a_un.a_ptr); - dbg("RTLD dynamic = %p", obj_rtld.dynamic); - dbg("RTLD pltgot = %p", obj_rtld.pltgot); - - dbg("initializing thread locks"); - lockdflt_init(); - - /* - * Load the main program, or process its program header if it is - * already loaded. - */ - if (fd != -1) { /* Load the main program. */ - dbg("loading main program"); - obj_main = map_object(fd, argv0, NULL); - close(fd); - if (obj_main == NULL) - rtld_die(); - max_stack_flags = obj_main->stack_flags; - } else { /* Main program already loaded. */ - dbg("processing main program's program header"); - assert(aux_info[AT_PHDR] != NULL); - phdr = (const Elf_Phdr *) aux_info[AT_PHDR]->a_un.a_ptr; - assert(aux_info[AT_PHNUM] != NULL); - phnum = aux_info[AT_PHNUM]->a_un.a_val; - assert(aux_info[AT_PHENT] != NULL); - assert(aux_info[AT_PHENT]->a_un.a_val == sizeof(Elf_Phdr)); - assert(aux_info[AT_ENTRY] != NULL); - imgentry = (caddr_t) aux_info[AT_ENTRY]->a_un.a_ptr; - if ((obj_main = digest_phdr(phdr, phnum, imgentry, argv0)) == NULL) - rtld_die(); - } - - if (aux_info[AT_EXECPATH] != NULL && fd == -1) { - kexecpath = aux_info[AT_EXECPATH]->a_un.a_ptr; - dbg("AT_EXECPATH %p %s", kexecpath, kexecpath); - if (kexecpath[0] == '/') - obj_main->path = kexecpath; - else if (getcwd(buf, sizeof(buf)) == NULL || - strlcat(buf, "/", sizeof(buf)) >= sizeof(buf) || - strlcat(buf, kexecpath, sizeof(buf)) >= sizeof(buf)) - obj_main->path = xstrdup(argv0); - else - obj_main->path = xstrdup(buf); - } else { - dbg("No AT_EXECPATH or direct exec"); - obj_main->path = xstrdup(argv0); - } - dbg("obj_main path %s", obj_main->path); - obj_main->mainprog = true; - - if (aux_info[AT_STACKPROT] != NULL && - aux_info[AT_STACKPROT]->a_un.a_val != 0) - stack_prot = aux_info[AT_STACKPROT]->a_un.a_val; + } + + ld_debug = ld_get_env_var(LD_DEBUG); + if (ld_bind_now == NULL) + ld_bind_not = ld_get_env_var(LD_BIND_NOT) != NULL; + ld_dynamic_weak = ld_get_env_var(LD_DYNAMIC_WEAK) == NULL; + libmap_disable = ld_get_env_var(LD_LIBMAP_DISABLE) != NULL; + libmap_override = ld_get_env_var(LD_LIBMAP); + ld_library_path = ld_get_env_var(LD_LIBRARY_PATH); + ld_library_dirs = ld_get_env_var(LD_LIBRARY_PATH_FDS); + ld_preload = ld_get_env_var(LD_PRELOAD); + ld_preload_fds = ld_get_env_var(LD_PRELOAD_FDS); + ld_elf_hints_path = ld_get_env_var(LD_ELF_HINTS_PATH); + ld_loadfltr = ld_get_env_var(LD_LOADFLTR) != NULL; + library_path_rpath = ld_get_env_var(LD_LIBRARY_PATH_RPATH); + if (library_path_rpath != NULL) { + if (library_path_rpath[0] == 'y' || + library_path_rpath[0] == 'Y' || + library_path_rpath[0] == '1') + ld_library_path_rpath = true; + else + ld_library_path_rpath = false; + } + static_tls_extra = ld_get_env_var(LD_STATIC_TLS_EXTRA); + if (static_tls_extra != NULL && static_tls_extra[0] != '\0') { + sz = parse_integer(static_tls_extra); + if (sz >= RTLD_STATIC_TLS_EXTRA && sz <= SIZE_T_MAX) + ld_static_tls_extra = sz; + } + dangerous_ld_env = libmap_disable || libmap_override != NULL || + ld_library_path != NULL || ld_preload != NULL || + ld_elf_hints_path != NULL || ld_loadfltr || !ld_dynamic_weak || + static_tls_extra != NULL; + ld_tracing = ld_get_env_var(LD_TRACE_LOADED_OBJECTS); + ld_utrace = ld_get_env_var(LD_UTRACE); + + set_ld_elf_hints_path(); + if (ld_debug != NULL && *ld_debug != '\0') + debug = 1; + dbg("%s is initialized, base address = %p", __progname, + (caddr_t)aux_info[AT_BASE]->a_un.a_ptr); + dbg("RTLD dynamic = %p", obj_rtld.dynamic); + dbg("RTLD pltgot = %p", obj_rtld.pltgot); + + dbg("initializing thread locks"); + lockdflt_init(); + + /* + * Load the main program, or process its program header if it is + * already loaded. + */ + if (fd != -1) { /* Load the main program. */ + dbg("loading main program"); + obj_main = map_object(fd, argv0, NULL); + close(fd); + if (obj_main == NULL) + rtld_die(); + max_stack_flags = obj_main->stack_flags; + } else { /* Main program already loaded. */ + dbg("processing main program's program header"); + assert(aux_info[AT_PHDR] != NULL); + phdr = (const Elf_Phdr *)aux_info[AT_PHDR]->a_un.a_ptr; + assert(aux_info[AT_PHNUM] != NULL); + phnum = aux_info[AT_PHNUM]->a_un.a_val; + assert(aux_info[AT_PHENT] != NULL); + assert(aux_info[AT_PHENT]->a_un.a_val == sizeof(Elf_Phdr)); + assert(aux_info[AT_ENTRY] != NULL); + imgentry = (caddr_t)aux_info[AT_ENTRY]->a_un.a_ptr; + if ((obj_main = digest_phdr(phdr, phnum, imgentry, argv0)) == + NULL) + rtld_die(); + } + + if (aux_info[AT_EXECPATH] != NULL && fd == -1) { + kexecpath = aux_info[AT_EXECPATH]->a_un.a_ptr; + dbg("AT_EXECPATH %p %s", kexecpath, kexecpath); + if (kexecpath[0] == '/') + obj_main->path = kexecpath; + else if (getcwd(buf, sizeof(buf)) == NULL || + strlcat(buf, "/", sizeof(buf)) >= sizeof(buf) || + strlcat(buf, kexecpath, sizeof(buf)) >= sizeof(buf)) + obj_main->path = xstrdup(argv0); + else + obj_main->path = xstrdup(buf); + } else { + dbg("No AT_EXECPATH or direct exec"); + obj_main->path = xstrdup(argv0); + } + dbg("obj_main path %s", obj_main->path); + obj_main->mainprog = true; + + if (aux_info[AT_STACKPROT] != NULL && + aux_info[AT_STACKPROT]->a_un.a_val != 0) + stack_prot = aux_info[AT_STACKPROT]->a_un.a_val; #ifndef COMPAT_libcompat - /* - * Get the actual dynamic linker pathname from the executable if - * possible. (It should always be possible.) That ensures that - * gdb will find the right dynamic linker even if a non-standard - * one is being used. - */ - if (obj_main->interp != NULL && - strcmp(obj_main->interp, obj_rtld.path) != 0) { - free(obj_rtld.path); - obj_rtld.path = xstrdup(obj_main->interp); - __progname = obj_rtld.path; - } + /* + * Get the actual dynamic linker pathname from the executable if + * possible. (It should always be possible.) That ensures that + * gdb will find the right dynamic linker even if a non-standard + * one is being used. + */ + if (obj_main->interp != NULL && + strcmp(obj_main->interp, obj_rtld.path) != 0) { + free(obj_rtld.path); + obj_rtld.path = xstrdup(obj_main->interp); + __progname = obj_rtld.path; + } #endif - if (!digest_dynamic(obj_main, 0)) - rtld_die(); - dbg("%s valid_hash_sysv %d valid_hash_gnu %d dynsymcount %d", - obj_main->path, obj_main->valid_hash_sysv, obj_main->valid_hash_gnu, - obj_main->dynsymcount); - - linkmap_add(obj_main); - linkmap_add(&obj_rtld); - - /* Link the main program into the list of objects. */ - TAILQ_INSERT_HEAD(&obj_list, obj_main, next); - obj_count++; - obj_loads++; - - /* Initialize a fake symbol for resolving undefined weak references. */ - sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); - sym_zero.st_shndx = SHN_UNDEF; - sym_zero.st_value = -(uintptr_t)obj_main->relocbase; - - if (!libmap_disable) - libmap_disable = (bool)lm_init(libmap_override); - - if (aux_info[AT_KPRELOAD] != NULL && - aux_info[AT_KPRELOAD]->a_un.a_ptr != NULL) { - dbg("loading kernel vdso"); - if (load_kpreload(aux_info[AT_KPRELOAD]->a_un.a_ptr) == -1) - rtld_die(); - } - - dbg("loading LD_PRELOAD_FDS libraries"); - if (load_preload_objects(ld_preload_fds, true) == -1) - rtld_die(); + if (!digest_dynamic(obj_main, 0)) + rtld_die(); + dbg("%s valid_hash_sysv %d valid_hash_gnu %d dynsymcount %d", + obj_main->path, obj_main->valid_hash_sysv, obj_main->valid_hash_gnu, + obj_main->dynsymcount); - dbg("loading LD_PRELOAD libraries"); - if (load_preload_objects(ld_preload, false) == -1) - rtld_die(); - preload_tail = globallist_curr(TAILQ_LAST(&obj_list, obj_entry_q)); + linkmap_add(obj_main); + linkmap_add(&obj_rtld); - dbg("loading needed objects"); - if (load_needed_objects(obj_main, ld_tracing != NULL ? RTLD_LO_TRACE : - 0) == -1) - rtld_die(); + /* Link the main program into the list of objects. */ + TAILQ_INSERT_HEAD(&obj_list, obj_main, next); + obj_count++; + obj_loads++; - /* Make a list of all objects loaded at startup. */ - last_interposer = obj_main; - TAILQ_FOREACH(obj, &obj_list, next) { - if (obj->marker) - continue; - if (obj->z_interpose && obj != obj_main) { - objlist_put_after(&list_main, last_interposer, obj); - last_interposer = obj; - } else { - objlist_push_tail(&list_main, obj); + /* Initialize a fake symbol for resolving undefined weak references. */ + sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); + sym_zero.st_shndx = SHN_UNDEF; + sym_zero.st_value = -(uintptr_t)obj_main->relocbase; + + if (!libmap_disable) + libmap_disable = (bool)lm_init(libmap_override); + + if (aux_info[AT_KPRELOAD] != NULL && + aux_info[AT_KPRELOAD]->a_un.a_ptr != NULL) { + dbg("loading kernel vdso"); + if (load_kpreload(aux_info[AT_KPRELOAD]->a_un.a_ptr) == -1) + rtld_die(); } - obj->refcount++; - } - dbg("checking for required versions"); - if (rtld_verify_versions(&list_main) == -1 && !ld_tracing) - rtld_die(); + dbg("loading LD_PRELOAD_FDS libraries"); + if (load_preload_objects(ld_preload_fds, true) == -1) *** 6242 LINES SKIPPED ***