The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=7e2f38311e62b1a3ba4a023042f2dc36e27cdd06

commit 7e2f38311e62b1a3ba4a023042f2dc36e27cdd06
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2025-01-18 02:26:16 +0000
Commit:     Konstantin Belousov <k...@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 ***

Reply via email to