From 180958291462f38154916103a6a4bdeb852e6cc3 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 26 Oct 2009 02:32:16 -0400 Subject: 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 --- libsandbox/wrappers.c | 54 +++++++++++++++++++++++++++++++-------------------- 1 file 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); -- cgit v1.2.3-65-gdbad