diff options
author | Mike Frysinger <vapier@gentoo.org> | 2009-10-26 02:32:16 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2009-10-26 02:45:04 -0400 |
commit | 180958291462f38154916103a6a4bdeb852e6cc3 (patch) | |
tree | b2d1a521f50905b620349bf373722469ce233446 | |
parent | tests: add reverse lookup funcs (diff) | |
download | sandbox-180958291462f38154916103a6a4bdeb852e6cc3.tar.gz sandbox-180958291462f38154916103a6a4bdeb852e6cc3.tar.bz2 sandbox-180958291462f38154916103a6a4bdeb852e6cc3.zip |
libsandbox: rewrite RTLD_NEXT handling
The commit 0a539b142f24 tried to fix RTLD_NEXT issues seen under certain
kernel/glibc combos, but in reality all it did was force dlopening of the
C library for every symbol lookup. So rewrite the code to handle things
on the fly as needed -- if RTLD_NEXT returned a bum symbol, load the C
library and try again.
URL: http://bugs.gentoo.org/202765
URL: http://bugs.gentoo.org/206678
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r-- | libsandbox/wrappers.c | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/libsandbox/wrappers.c b/libsandbox/wrappers.c index 6094f51..f587614 100644 --- a/libsandbox/wrappers.c +++ b/libsandbox/wrappers.c @@ -19,33 +19,33 @@ # define USE_RTLD_NEXT #endif -static void *libc_handle = NULL; +static void *libc_handle; + +static void load_libc_handle(void) +{ + save_errno(); /* #260765 */ + libc_handle = dlopen(LIBC_VERSION, RTLD_LAZY); + restore_errno(); + + if (!libc_handle) { + fprintf(stderr, "libsandbox: Can't dlopen libc: %s\n", + dlerror()); + exit(EXIT_FAILURE); + } +} static void *get_dlsym(const char *symname, const char *symver) { - void *symaddr = NULL; + void *symaddr; -#if defined(USE_RTLD_NEXT) - libc_handle = RTLD_NEXT; + if (!libc_handle) { +#ifdef USE_RTLD_NEXT + libc_handle = RTLD_NEXT; + try_again: ; +#else + load_libc_handle(); #endif - - /* Checking for -1UL is significant on hardened! - * USE_RTLD_NEXT returns it as a sign of being unusable. - * However using !x or NULL checks does NOT pick it up! - * That is also why we need to save/restore errno #260765. - */ -#define INVALID_LIBC_HANDLE(x) (!x || NULL == x || (void *)-1UL == x) - if (INVALID_LIBC_HANDLE(libc_handle)) { - save_errno(); - libc_handle = dlopen(LIBC_VERSION, RTLD_LAZY); - restore_errno(); - if (INVALID_LIBC_HANDLE(libc_handle)) { - fprintf(stderr, "libsandbox: Can't dlopen libc: %s\n", - dlerror()); - exit(EXIT_FAILURE); - } } -#undef INVALID_LIBC_HANDLE if (NULL == symver) symaddr = dlsym(libc_handle, symname); @@ -53,6 +53,18 @@ static void *get_dlsym(const char *symname, const char *symver) symaddr = dlvsym(libc_handle, symname, symver); if (!symaddr) { +#ifdef USE_RTLD_NEXT + /* Maybe RTLD_NEXT is broken for some screwed up reason as + * can be seen with some specific glibc/kernel versions. + * Recover dynamically so that we can be deployed easily + * via binpkgs and upgrades #202765 #206678 + */ + if (libc_handle == RTLD_NEXT) { + load_libc_handle(); + goto try_again; + } +#endif + fprintf(stderr, "libsandbox: Can't resolve %s: %s\n", symname, dlerror()); exit(EXIT_FAILURE); |