diff options
author | Philip Guenther <guenther@cvs.openbsd.org> | 2019-06-02 01:03:02 +0000 |
---|---|---|
committer | Philip Guenther <guenther@cvs.openbsd.org> | 2019-06-02 01:03:02 +0000 |
commit | 4a80a8ec4a5d6d7d4690398d18ba3e11a49f0d8d (patch) | |
tree | ba6f9621a1170d5b6b13543f937687973ef87a85 /lib/libc/dlfcn | |
parent | a8565da1091ea7a7792ae6d3d19d0fa477404ab6 (diff) |
Complete the ld.so boot cleanup: move most libc initialization from
_csu_finish() to _libc_preinit(), which is an .init_array function
in shared libc (and mark it INITFIRST) or a .preinit_array function
in static libc, grabbing the _dl_cb callback there from ld.so. Then
in _csu_finish(), invoke the dl_clean_boot() callback to free ld.so's
startup bits before main() gets control.
Other cleanups this permits:
- move various startup structures into .data.rel.ro
- the dl* stubs in libc can be strong and call the callbacks provided
via _dl_cb
- no longer need to conditionalize dlctl() calls on presence of _DYNAMIC
original concept and full diff ok kettenis@
ok deraadt@
Diffstat (limited to 'lib/libc/dlfcn')
-rw-r--r-- | lib/libc/dlfcn/dlfcn_stubs.c | 43 | ||||
-rw-r--r-- | lib/libc/dlfcn/init.c | 83 |
2 files changed, 86 insertions, 40 deletions
diff --git a/lib/libc/dlfcn/dlfcn_stubs.c b/lib/libc/dlfcn/dlfcn_stubs.c index e04a2aa0706..78d728f66cb 100644 --- a/lib/libc/dlfcn/dlfcn_stubs.c +++ b/lib/libc/dlfcn/dlfcn_stubs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dlfcn_stubs.c,v 1.14 2016/09/06 18:49:34 guenther Exp $ */ +/* $OpenBSD: dlfcn_stubs.c,v 1.15 2019/06/02 01:03:01 guenther Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -28,34 +28,19 @@ #include <sys/types.h> #include <stddef.h> +#include <stdio.h> #include <link.h> +#include <dlfcn.h> +#include <tib.h> #include "init.h" -/* - * All functions here are just stubs that will be overridden - * by the real functions in ld.so when dynamic loading is - * performed at exec. The symbols here are provided as a link - * helper so we can link a program using the dl functions - * without getting any unresolved references. - */ - -void *dlopen(const char *libname, int how) __attribute__((weak)); -int dlclose(void *handle) __attribute__((weak)); -void *dlsym(void *handle, const char *name) __attribute__((weak)); -int dlctl(void *handle, int command, void *data) __attribute__((weak)); -char *dlerror(void) __attribute__((weak)); - -struct dl_info; -int dladdr(const void *addr, struct dl_info *info) __attribute__((weak)); - -int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *date) __attribute__((weak)); - -#include <stdio.h> void * dlopen(const char *libname, int how) { + if (_dl_cb != NULL && _dl_cb->dlopen != NULL) + return _dl_cb->dlopen(libname, how); printf("Wrong dl symbols!\n"); return NULL; } @@ -63,6 +48,8 @@ dlopen(const char *libname, int how) int dlclose(void *handle) { + if (_dl_cb != NULL && _dl_cb->dlclose != NULL) + return _dl_cb->dlclose(handle); printf("Wrong dl symbols!\n"); return 0; } @@ -70,6 +57,8 @@ dlclose(void *handle) void * dlsym(void *handle, const char *name) { + if (_dl_cb != NULL && _dl_cb->dlsym != NULL) + return _dl_cb->dlsym(handle, name); printf("Wrong dl symbols!\n"); return NULL; } @@ -77,12 +66,17 @@ dlsym(void *handle, const char *name) int dlctl(void *handle, int command, void *data) { + if (_dl_cb != NULL && _dl_cb->dlctl != NULL) + return _dl_cb->dlctl(handle, command, data); return -1; } +DEF_WEAK(dlctl); char * dlerror(void) { + if (_dl_cb != NULL && _dl_cb->dlerror != NULL) + return _dl_cb->dlerror(); return "Wrong dl symbols!\n"; } @@ -90,6 +84,8 @@ int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *data) { + if (_dl_cb != NULL && _dl_cb->dl_iterate_phdr != NULL) + return _dl_cb->dl_iterate_phdr(callback, data); #ifndef PIC if (_static_phdr_info.dlpi_phdr != NULL) return callback(&_static_phdr_info, sizeof(_static_phdr_info), @@ -97,14 +93,18 @@ dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), #endif /* !PIC */ return -1; } +DEF_WEAK(dl_iterate_phdr); int dladdr(const void *addr, struct dl_info *info) { + if (_dl_cb != NULL && _dl_cb->dladdr != NULL) + return _dl_cb->dladdr(addr, info); printf("Wrong dl symbols!\n"); return -1; } +#if 0 /* Thread Local Storage argument structure */ typedef struct { unsigned long int ti_module; @@ -131,3 +131,4 @@ ___tls_get_addr(tls_index *ti) } #endif /* __i386 */ #endif /* arch with TLS support enabled */ +#endif diff --git a/lib/libc/dlfcn/init.c b/lib/libc/dlfcn/init.c index 3c387a60d6b..270f54aada5 100644 --- a/lib/libc/dlfcn/init.c +++ b/lib/libc/dlfcn/init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init.c,v 1.6 2017/12/01 23:30:05 guenther Exp $ */ +/* $OpenBSD: init.c,v 1.7 2019/06/02 01:03:01 guenther Exp $ */ /* * Copyright (c) 2014,2015 Philip Guenther <guenther@openbsd.org> * @@ -57,7 +57,7 @@ char *__progname __attribute__((weak)) = NULL; #ifndef PIC -struct dl_phdr_info _static_phdr_info = { .dlpi_name = "a.out" }; +struct dl_phdr_info _static_phdr_info __relro = { .dlpi_name = "a.out" }; static inline void early_static_init(char **_argv, char **_envp); static inline void setup_static_tib(Elf_Phdr *_phdr, int _phnum); @@ -66,13 +66,12 @@ static inline void setup_static_tib(Elf_Phdr *_phdr, int _phnum); extern Elf_Ehdr __executable_start[] __attribute__((weak)); #endif /* PIC */ -/* - * extract useful bits from the auxiliary vector and either - * a) register ld.so's cleanup in dynamic links, or - * b) init __progname, environ, and the TIB in static links. - */ -char *** -_csu_finish(char **argv, char **envp, void (*cleanup)(void)) +/* provide definitions for these */ +const dl_cb *_dl_cb __relro = NULL; + +void _libc_preinit(int, char **, char **, dl_cb_cb *) __dso_hidden; +void +_libc_preinit(int argc, char **argv, char **envp, dl_cb_cb *cb) { AuxInfo *aux; #ifndef PIC @@ -80,10 +79,13 @@ _csu_finish(char **argv, char **envp, void (*cleanup)(void)) int phnum = 0; /* static libc in a static link? */ - if (cleanup == NULL) + if (cb == NULL) early_static_init(argv, envp); #endif /* !PIC */ + if (cb != NULL) + _dl_cb = cb(DL_CB_CUR); + /* Extract useful bits from the auxiliary vector */ while (*envp++ != NULL) ; @@ -98,30 +100,73 @@ _csu_finish(char **argv, char **envp, void (*cleanup)(void)) break; case AUX_phdr: phdr = (void *)aux->au_v; - _static_phdr_info.dlpi_phdr = phdr; break; case AUX_phnum: phnum = aux->au_v; - _static_phdr_info.dlpi_phnum = phnum; break; #endif /* !PIC */ } } #ifndef PIC - if (cleanup == NULL && phdr == NULL && __executable_start != NULL) { + if (cb == NULL && phdr == NULL && __executable_start != NULL) { /* * Static non-PIE processes don't get an AUX vector, * so find the phdrs through the ELF header */ + _static_phdr_info.dlpi_addr = (Elf_Addr)__executable_start; phdr = (void *)((char *)__executable_start + __executable_start->e_phoff); phnum = __executable_start->e_phnum; } + _static_phdr_info.dlpi_phdr = phdr; + _static_phdr_info.dlpi_phnum = phnum; + /* static libc in a static link? */ - if (cleanup == NULL) + if (cb == NULL) setup_static_tib(phdr, phnum); #endif /* !PIC */ +} + +/* ARM just had to be different... */ +#ifndef __arm__ +# define TYPE "@" +#else +# define TYPE "%" +#endif + +#ifdef __LP64__ +# define VALUE_ALIGN ".balign 8" +# define VALUE_DIRECTIVE ".quad" +#else +# define VALUE_ALIGN ".balign 4" +# ifdef __hppa__ + /* hppa just had to be different: func pointers prefix with 'P%' */ +# define VALUE_DIRECTIVE ".int P%" +# else +# define VALUE_DIRECTIVE ".int" +# endif +#endif + +#define ADD_TO_ARRAY(func, which) \ + __asm( " .section ."#which",\"a\","TYPE#which"\n " \ + VALUE_ALIGN"\n "VALUE_DIRECTIVE" "#func"\n .previous") + +#ifdef PIC +ADD_TO_ARRAY(_libc_preinit, init_array); +#else +ADD_TO_ARRAY(_libc_preinit, preinit_array); +#endif + +/* + * In dynamic links, invoke ld.so's dl_clean_boot() callback, if any, + * and register its cleanup. + */ +char *** +_csu_finish(char **argv, char **envp, void (*cleanup)(void)) +{ + if (_dl_cb != NULL && _dl_cb->dl_clean_boot != NULL) + _dl_cb->dl_clean_boot(); if (cleanup != NULL) atexit(cleanup); @@ -163,12 +208,12 @@ early_static_init(char **argv, char **envp) #define ELF_ROUND(x,malign) (((x) + (malign)-1) & ~((malign)-1)) /* for static binaries, the location and size of the TLS image */ -static void *static_tls; -static size_t static_tls_fsize; +static void *static_tls __relro; +static size_t static_tls_fsize __relro; -size_t _static_tls_size = 0; -int _static_tls_align; -int _static_tls_align_offset; +size_t _static_tls_size __relro = 0; +int _static_tls_align __relro; +int _static_tls_align_offset __relro; static inline void setup_static_tib(Elf_Phdr *phdr, int phnum) |