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 ***