diff options
Diffstat (limited to 'libexec/ld.so/loader.c')
| -rw-r--r-- | libexec/ld.so/loader.c | 109 |
1 files changed, 83 insertions, 26 deletions
diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c index 19a58a5e2ae..a597f0cbd72 100644 --- a/libexec/ld.so/loader.c +++ b/libexec/ld.so/loader.c @@ -1,4 +1,4 @@ -/* $OpenBSD: loader.c,v 1.177 2018/12/03 05:29:56 guenther Exp $ */ +/* $OpenBSD: loader.c,v 1.178 2019/05/10 13:29:21 guenther Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -37,6 +37,7 @@ #include <link.h> #include <limits.h> /* NAME_MAX */ #include <dlfcn.h> +#include <tib.h> #include "syscall.h" #include "archdep.h" @@ -48,30 +49,51 @@ /* * Local decls. */ -unsigned long _dl_boot(const char **, char **, const long, long *); +unsigned long _dl_boot(const char **, char **, const long, long *) __boot; void _dl_debug_state(void); -void _dl_setup_env(const char *_argv0, char **_envp); +void _dl_setup_env(const char *_argv0, char **_envp) __boot; void _dl_dtors(void); -void _dl_fixup_user_env(void); -void _dl_call_preinit(elf_object_t *); +void _dl_dopreload(char *_paths) __boot; +void _dl_fixup_user_env(void) __boot; +void _dl_call_preinit(elf_object_t *) __boot; void _dl_call_init_recurse(elf_object_t *object, int initfirst); +void _dl_clean_boot(void); int _dl_pagesz __relro = 4096; int _dl_bindnow __relro = 0; int _dl_debug __relro = 0; int _dl_trust __relro = 0; char **_dl_libpath __relro = NULL; +const char **_dl_argv __relro = NULL; +int _dl_argc __relro = 0; -/* XXX variables which are only used during boot */ -char *_dl_preload __relro = NULL; -char *_dl_tracefmt1 __relro = NULL; -char *_dl_tracefmt2 __relro = NULL; -char *_dl_traceprog __relro = NULL; +char *_dl_preload __boot_data = NULL; +char *_dl_tracefmt1 __boot_data = NULL; +char *_dl_tracefmt2 __boot_data = NULL; +char *_dl_traceprog __boot_data = NULL; + +char **environ = NULL; +char *__progname = NULL; int _dl_traceld; struct r_debug *_dl_debug_map; -void _dl_dopreload(char *paths); +static dl_cb_cb _dl_cb_cb; +const struct dl_cb_0 callbacks_0 = { + .dl_allocate_tib = &_dl_allocate_tib, + .dl_free_tib = &_dl_free_tib, +#if DO_CLEAN_BOOT + .dl_clean_boot = &_dl_clean_boot, +#endif + .dlopen = &dlopen, + .dlclose = &dlclose, + .dlsym = &dlsym, + .dladdr = &dladdr, + .dlctl = &dlctl, + .dlerror = &dlerror, + .dl_iterate_phdr = &dl_iterate_phdr, +}; + /* * Run dtors for a single object. @@ -182,6 +204,18 @@ _dl_dtors(void) _dl_run_all_dtors(); } +#if DO_CLEAN_BOOT +void +_dl_clean_boot(void) +{ + extern char boot_text_start[], boot_text_end[]; + extern char boot_data_start[], boot_data_end[]; + + _dl_munmap(boot_text_start, boot_text_end - boot_text_start); + _dl_munmap(boot_data_start, boot_data_end - boot_data_start); +} +#endif /* DO_CLEAN_BOOT */ + void _dl_dopreload(char *paths) { @@ -208,8 +242,6 @@ _dl_dopreload(char *paths) * grab interesting environment variables, zap bad env vars if * issetugid, and set the exported environ and __progname variables */ -char **environ = NULL; -char *__progname = NULL; void _dl_setup_env(const char *argv0, char **envp) { @@ -429,6 +461,10 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data) if (dl_data[AUX_pagesz] != 0) _dl_pagesz = dl_data[AUX_pagesz]; _dl_malloc_init(); + + _dl_argv = argv; + while (_dl_argv[_dl_argc] != NULL) + _dl_argc++; _dl_setup_env(argv[0], envp); /* @@ -692,17 +728,6 @@ _dl_rtld(elf_object_t *object) object->obj_flags & DF_1_NOW)); /* - * Handle GNU_RELRO - */ - if (object->relro_addr != 0 && object->relro_size != 0) { - Elf_Addr addr = object->relro_addr; - - DL_DEB(("protect RELRO [0x%lx,0x%lx) in %s\n", - addr, addr + object->relro_size, object->load_name)); - _dl_mprotect((void *)addr, object->relro_size, PROT_READ); - } - - /* * Look for W&X segments and make them read-only. */ for (llist = object->load_list; llist != NULL; llist = llist->next) { @@ -733,7 +758,8 @@ _dl_call_preinit(elf_object_t *object) DL_DEB(("doing preinitarray obj %p @%p: [%s]\n", object, object->dyn.preinit_array, object->load_name)); for (i = 0; i < num; i++) - (*object->dyn.preinit_array[i])(); + (*object->dyn.preinit_array[i])(_dl_argc, _dl_argv, + environ, &_dl_cb_cb); } } @@ -744,6 +770,21 @@ _dl_call_init(elf_object_t *object) _dl_call_init_recurse(object, 0); } +static void +_dl_relro(elf_object_t *object) +{ + /* + * Handle GNU_RELRO + */ + if (object->relro_addr != 0 && object->relro_size != 0) { + Elf_Addr addr = object->relro_addr; + + DL_DEB(("protect RELRO [0x%lx,0x%lx) in %s\n", + addr, addr + object->relro_size, object->load_name)); + _dl_mprotect((void *)addr, object->relro_size, PROT_READ); + } +} + void _dl_call_init_recurse(elf_object_t *object, int initfirst) { @@ -765,6 +806,9 @@ _dl_call_init_recurse(elf_object_t *object, int initfirst) if (initfirst && (object->obj_flags & DF_1_INITFIRST) == 0) return; + if (!initfirst) + _dl_relro(object); + if (object->dyn.init) { DL_DEB(("doing ctors obj %p @%p: [%s]\n", object, object->dyn.init, object->load_name)); @@ -778,9 +822,13 @@ _dl_call_init_recurse(elf_object_t *object, int initfirst) DL_DEB(("doing initarray obj %p @%p: [%s]\n", object, object->dyn.init_array, object->load_name)); for (i = 0; i < num; i++) - (*object->dyn.init_array[i])(); + (*object->dyn.init_array[i])(_dl_argc, _dl_argv, + environ, &_dl_cb_cb); } + if (initfirst) + _dl_relro(object); + object->status |= STAT_INIT_DONE; } @@ -864,3 +912,12 @@ _dl_fixup_user_env(void) *((char **)(sym->st_value + ooff)) = __progname; } } + +const void * +_dl_cb_cb(int version) +{ + DL_DEB(("version %d callbacks requested\n", version)); + if (version == 0) + return &callbacks_0; + return NULL; +} |
