Changeset View
Standalone View
libexec/rtld-elf/rtld.c
Show First 20 Lines • Show All 342 Lines • ▼ Show 20 Lines | |||||
static inline const char * | static inline const char * | ||||
_LD(const char *var) | _LD(const char *var) | ||||
{ | { | ||||
static char buffer[128]; | static char buffer[128]; | ||||
strlcpy(buffer, ld_env_prefix, sizeof(buffer)); | strlcpy(buffer, ld_env_prefix, sizeof(buffer)); | ||||
strlcat(buffer, var, sizeof(buffer)); | strlcat(buffer, var, sizeof(buffer)); | ||||
return (buffer); | return (buffer); | ||||
} | } | ||||
kib: Wouldn't this case break after your changes ? | |||||
Done Inline ActionsDo you mean LD_SOFT_* won't be handled properly? I haven't tested those variants, so not sure if we want the fallback behaviour there too. arichardson: Do you mean LD_SOFT_* won't be handled properly?
The get_ld_env() helper checks whatever _LD… | |||||
Not Done Inline ActionsMay be LD_SOFT should be somehow integrated into get_ld_env. Right now it looks like as two levels of archeology put one over another. kib: May be LD_SOFT should be somehow integrated into get_ld_env. Right now it looks like as two… | |||||
Done Inline ActionsI agree it would be nice to merge the LD_SOFT prefix here. However that is determined dynamically on startup based on auxargs so we can't do it using the pre-processor. In the common case where we don't need this (i.e. all non-ARM architectures) we can avoid the strlcpy. I think cleaning up ld_env_prefix should probably be a separate commit. arichardson: I agree it would be nice to merge the LD_SOFT prefix here. However that is determined… | |||||
#else | #else | ||||
#define _LD(x) LD_ x | #define _LD(x) LD_ x | ||||
#endif | #endif | ||||
/* Check LD_{32,64}_<VAR> and if that is not set fall back to LD_<VAR>. */ | |||||
Done Inline Actions32,64 looks more normal jrtc27: 32,64 looks more normal | |||||
#define get_ld_env(var) _get_ld_env(_LD(var), LD_FALLBACK_ var) | |||||
static char * | |||||
Done Inline Actionsstyle: char * kib: style: `char *` | |||||
_get_ld_env(const char *preferred, const char *fallback) | |||||
Done Inline ActionsBoth are prefixed. jrtc27: Both are prefixed. | |||||
{ | |||||
char *result; | |||||
result = getenv(preferred); | |||||
if (result == NULL && fallback != NULL) | |||||
result = getenv(fallback); | |||||
return (result); | |||||
} | |||||
/* | /* | ||||
* Main entry point for dynamic linking. The first argument is the | * Main entry point for dynamic linking. The first argument is the | ||||
* stack pointer. The stack is expected to be laid out as described | * stack pointer. The stack is expected to be laid out as described | ||||
* in the SVR4 ABI specification, Intel 386 Processor Supplement. | * in the SVR4 ABI specification, Intel 386 Processor Supplement. | ||||
* Specifically, the stack pointer points to a word containing | * Specifically, the stack pointer points to a word containing | ||||
* ARGC. Following that in the stack is a null-terminated sequence | * ARGC. Following that in the stack is a null-terminated sequence | ||||
* of pointers to argument strings. Then comes a null-terminated | * of pointers to argument strings. Then comes a null-terminated | ||||
* sequence of pointers to environment strings. Finally, there is a | * sequence of pointers to environment strings. Finally, there is a | ||||
▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | if (phdr == obj_rtld.phdr) { | ||||
} | } | ||||
} else { | } else { | ||||
_rtld_error("No binary"); | _rtld_error("No binary"); | ||||
rtld_die(); | rtld_die(); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
ld_bind_now = getenv(_LD("BIND_NOW")); | ld_bind_now = get_ld_env("BIND_NOW"); | ||||
/* | /* | ||||
* If the process is tainted, then we un-set the dangerous environment | * If the process is tainted, then we un-set the dangerous environment | ||||
* variables. The process will be marked as tainted until setuid(2) | * 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 | * is called. If any child process calls setuid(2) we do not want any | ||||
* future processes to honor the potentially un-safe variables. | * future processes to honor the potentially un-safe variables. | ||||
*/ | */ | ||||
if (!trust) { | if (!trust) { | ||||
if (unsetenv(_LD("PRELOAD")) || unsetenv(_LD("LIBMAP")) || | if (unsetenv(_LD("PRELOAD")) || unsetenv(_LD("LIBMAP")) || | ||||
unsetenv(_LD("LIBRARY_PATH")) || unsetenv(_LD("LIBRARY_PATH_FDS")) || | unsetenv(_LD("LIBRARY_PATH")) || unsetenv(_LD("LIBRARY_PATH_FDS")) || | ||||
unsetenv(_LD("LIBMAP_DISABLE")) || unsetenv(_LD("BIND_NOT")) || | unsetenv(_LD("LIBMAP_DISABLE")) || unsetenv(_LD("BIND_NOT")) || | ||||
unsetenv(_LD("DEBUG")) || unsetenv(_LD("ELF_HINTS_PATH")) || | unsetenv(_LD("DEBUG")) || unsetenv(_LD("ELF_HINTS_PATH")) || | ||||
unsetenv(_LD("LOADFLTR")) || unsetenv(_LD("LIBRARY_PATH_RPATH"))) { | unsetenv(_LD("LOADFLTR")) || unsetenv(_LD("LIBRARY_PATH_RPATH"))) { | ||||
_rtld_error("environment corrupt; aborting"); | _rtld_error("environment corrupt; aborting"); | ||||
rtld_die(); | rtld_die(); | ||||
} | } | ||||
} | } | ||||
ld_debug = getenv(_LD("DEBUG")); | ld_debug = get_ld_env("DEBUG"); | ||||
if (ld_bind_now == NULL) | if (ld_bind_now == NULL) | ||||
ld_bind_not = getenv(_LD("BIND_NOT")) != NULL; | ld_bind_not = get_ld_env("BIND_NOT") != NULL; | ||||
libmap_disable = getenv(_LD("LIBMAP_DISABLE")) != NULL; | libmap_disable = get_ld_env("LIBMAP_DISABLE") != NULL; | ||||
libmap_override = getenv(_LD("LIBMAP")); | libmap_override = get_ld_env("LIBMAP"); | ||||
ld_library_path = getenv(_LD("LIBRARY_PATH")); | ld_library_path = get_ld_env("LIBRARY_PATH"); | ||||
ld_library_dirs = getenv(_LD("LIBRARY_PATH_FDS")); | ld_library_dirs = get_ld_env("LIBRARY_PATH_FDS"); | ||||
ld_preload = getenv(_LD("PRELOAD")); | ld_preload = get_ld_env("PRELOAD"); | ||||
ld_elf_hints_path = getenv(_LD("ELF_HINTS_PATH")); | ld_elf_hints_path = get_ld_env("ELF_HINTS_PATH"); | ||||
ld_loadfltr = getenv(_LD("LOADFLTR")) != NULL; | ld_loadfltr = get_ld_env("LOADFLTR") != NULL; | ||||
library_path_rpath = getenv(_LD("LIBRARY_PATH_RPATH")); | library_path_rpath = get_ld_env("LIBRARY_PATH_RPATH"); | ||||
if (library_path_rpath != NULL) { | if (library_path_rpath != NULL) { | ||||
if (library_path_rpath[0] == 'y' || | if (library_path_rpath[0] == 'y' || | ||||
library_path_rpath[0] == 'Y' || | library_path_rpath[0] == 'Y' || | ||||
library_path_rpath[0] == '1') | library_path_rpath[0] == '1') | ||||
ld_library_path_rpath = true; | ld_library_path_rpath = true; | ||||
else | else | ||||
ld_library_path_rpath = false; | ld_library_path_rpath = false; | ||||
} | } | ||||
dangerous_ld_env = libmap_disable || (libmap_override != NULL) || | dangerous_ld_env = libmap_disable || (libmap_override != NULL) || | ||||
(ld_library_path != NULL) || (ld_preload != NULL) || | (ld_library_path != NULL) || (ld_preload != NULL) || | ||||
(ld_elf_hints_path != NULL) || ld_loadfltr; | (ld_elf_hints_path != NULL) || ld_loadfltr; | ||||
ld_tracing = getenv(_LD("TRACE_LOADED_OBJECTS")); | ld_tracing = get_ld_env("TRACE_LOADED_OBJECTS"); | ||||
ld_utrace = getenv(_LD("UTRACE")); | ld_utrace = get_ld_env("UTRACE"); | ||||
if ((ld_elf_hints_path == NULL) || strlen(ld_elf_hints_path) == 0) | if ((ld_elf_hints_path == NULL) || strlen(ld_elf_hints_path) == 0) | ||||
ld_elf_hints_path = ld_elf_hints_default; | ld_elf_hints_path = ld_elf_hints_default; | ||||
if (ld_debug != NULL && *ld_debug != '\0') | if (ld_debug != NULL && *ld_debug != '\0') | ||||
debug = 1; | debug = 1; | ||||
dbg("%s is initialized, base address = %p", __progname, | dbg("%s is initialized, base address = %p", __progname, | ||||
(caddr_t) aux_info[AT_BASE]->a_un.a_ptr); | (caddr_t) aux_info[AT_BASE]->a_un.a_ptr); | ||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | if (obj->z_interpose && obj != obj_main) { | ||||
if (rtld_verify_versions(&list_main) == -1 && !ld_tracing) | if (rtld_verify_versions(&list_main) == -1 && !ld_tracing) | ||||
rtld_die(); | rtld_die(); | ||||
if (ld_tracing) { /* We're done */ | if (ld_tracing) { /* We're done */ | ||||
trace_loaded_objects(obj_main); | trace_loaded_objects(obj_main); | ||||
exit(0); | exit(0); | ||||
} | } | ||||
if (getenv(_LD("DUMP_REL_PRE")) != NULL) { | if (get_ld_env("DUMP_REL_PRE") != NULL) { | ||||
dump_relocations(obj_main); | dump_relocations(obj_main); | ||||
exit (0); | exit (0); | ||||
} | } | ||||
/* | /* | ||||
* Processing tls relocations requires having the tls offsets | * Processing tls relocations requires having the tls offsets | ||||
* initialized. Prepare offsets before starting initial | * initialized. Prepare offsets before starting initial | ||||
* relocation processing. | * relocation processing. | ||||
Show All 11 Lines | if (relocate_objects(obj_main, | ||||
ld_bind_now != NULL && *ld_bind_now != '\0', | ld_bind_now != NULL && *ld_bind_now != '\0', | ||||
&obj_rtld, SYMLOOK_EARLY, NULL) == -1) | &obj_rtld, SYMLOOK_EARLY, NULL) == -1) | ||||
rtld_die(); | rtld_die(); | ||||
dbg("doing copy relocations"); | dbg("doing copy relocations"); | ||||
if (do_copy_relocations(obj_main) == -1) | if (do_copy_relocations(obj_main) == -1) | ||||
rtld_die(); | rtld_die(); | ||||
if (getenv(_LD("DUMP_REL_POST")) != NULL) { | if (get_ld_env("DUMP_REL_POST") != NULL) { | ||||
dump_relocations(obj_main); | dump_relocations(obj_main); | ||||
exit (0); | exit (0); | ||||
} | } | ||||
ifunc_init(aux); | ifunc_init(aux); | ||||
/* | /* | ||||
* Setup TLS for main thread. This must be done after the | * Setup TLS for main thread. This must be done after the | ||||
▲ Show 20 Lines • Show All 3,885 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void | static void | ||||
trace_loaded_objects(Obj_Entry *obj) | trace_loaded_objects(Obj_Entry *obj) | ||||
{ | { | ||||
const char *fmt1, *fmt2, *fmt, *main_local, *list_containers; | const char *fmt1, *fmt2, *fmt, *main_local, *list_containers; | ||||
int c; | int c; | ||||
if ((main_local = getenv(_LD("TRACE_LOADED_OBJECTS_PROGNAME"))) == NULL) | if ((main_local = get_ld_env("TRACE_LOADED_OBJECTS_PROGNAME")) == NULL) | ||||
main_local = ""; | main_local = ""; | ||||
if ((fmt1 = getenv(_LD("TRACE_LOADED_OBJECTS_FMT1"))) == NULL) | if ((fmt1 = get_ld_env("TRACE_LOADED_OBJECTS_FMT1")) == NULL) | ||||
fmt1 = "\t%o => %p (%x)\n"; | fmt1 = "\t%o => %p (%x)\n"; | ||||
if ((fmt2 = getenv(_LD("TRACE_LOADED_OBJECTS_FMT2"))) == NULL) | if ((fmt2 = get_ld_env("TRACE_LOADED_OBJECTS_FMT2")) == NULL) | ||||
fmt2 = "\t%o (%x)\n"; | fmt2 = "\t%o (%x)\n"; | ||||
list_containers = getenv(_LD("TRACE_LOADED_OBJECTS_ALL")); | list_containers = get_ld_env("TRACE_LOADED_OBJECTS_ALL"); | ||||
for (; obj != NULL; obj = TAILQ_NEXT(obj, next)) { | for (; obj != NULL; obj = TAILQ_NEXT(obj, next)) { | ||||
Needed_Entry *needed; | Needed_Entry *needed; | ||||
const char *name, *path; | const char *name, *path; | ||||
bool is_lib; | bool is_lib; | ||||
if (obj->marker) | if (obj->marker) | ||||
continue; | continue; | ||||
▲ Show 20 Lines • Show All 1,209 Lines • Show Last 20 Lines |
Wouldn't this case break after your changes ?