Increase robustness of internal dlopen() by using RTLD_NOW [BZ #22766]
Prevent random runtime crashes due to missing symbols caused by mixed libnss_* versions. [BZ #22766] * include/dlfcn.h [__libc_dl_open]: Replace RTLD_LAZY with RTLD_NOW. * sysdeps/gnu/unwind-resume.c (__lib_gcc_s_init): Replace __libc_dlopen_mode() using RTLD_NOW with __libc_dlopen. * sysdeps/nptl/unwind-forcedunwind.c: Likewise. Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
This commit is contained in:
parent
7d80f48e93
commit
81b49e9692
|
@ -1,3 +1,11 @@
|
||||||
|
2018-04-26 Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||||
|
|
||||||
|
[BZ #22766]
|
||||||
|
* include/dlfcn.h [__libc_dl_open]: Replace RTLD_LAZY with RTLD_NOW.
|
||||||
|
* sysdeps/gnu/unwind-resume.c (__lib_gcc_s_init): Replace
|
||||||
|
__libc_dlopen_mode() using RTLD_NOW with __libc_dlopen.
|
||||||
|
* sysdeps/nptl/unwind-forcedunwind.c: Likewise.
|
||||||
|
|
||||||
2018-04-25 Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
2018-04-25 Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/getdirentries.c (getdirentries): Build iff
|
* sysdeps/unix/sysv/linux/getdirentries.c (getdirentries): Build iff
|
||||||
|
|
|
@ -31,8 +31,29 @@ extern char **__libc_argv attribute_hidden;
|
||||||
|
|
||||||
/* Now define the internal interfaces. */
|
/* Now define the internal interfaces. */
|
||||||
|
|
||||||
|
/* Use RTLD_NOW here because:
|
||||||
|
1. In pthread_cancel_init we want to use RTLD_NOW to reduce the stack usage
|
||||||
|
of future cancellation operations, particularly when the target thread
|
||||||
|
is running with a small stack. Likewise for consistency we do the same
|
||||||
|
thing in __libgcc_s_init. RTLD_NOW will rarely make a difference for
|
||||||
|
__libgcc_s_init because unwinding is already in progress, so libgcc_s.so
|
||||||
|
has already been loaded if its unwinder is used (Bug 22636).
|
||||||
|
2. It allows us to provide robust fallback code at dlopen time for
|
||||||
|
incorrectly configured systems that mix old libnss_* modules with newly
|
||||||
|
installed libraries e.g. old libnss_nis.so.2 with new libnsl.so.1. Using
|
||||||
|
RTLD_LAZY here causes a failure at the time the symbol is called and at
|
||||||
|
that point it is much harder to safely return an error (Bug 22766).
|
||||||
|
|
||||||
|
The use of RTLD_NOW also impacts gconv module loading, backtracing
|
||||||
|
(where the unwinder form libgcc_s.so is used), and IDNA functions
|
||||||
|
(which load libidn), all of which load their respective DSOs on
|
||||||
|
demand, and so should not impact program startup. That is to say
|
||||||
|
that the DSOs are loaded as part of an API call and therefore we
|
||||||
|
will be calling that family of API functions shortly so RTLD_NOW or
|
||||||
|
RTLD_LAZY is not a big difference in performance, but RTLD_NOW has
|
||||||
|
better error handling semantics for the library. */
|
||||||
#define __libc_dlopen(name) \
|
#define __libc_dlopen(name) \
|
||||||
__libc_dlopen_mode (name, RTLD_LAZY | __RTLD_DLOPEN)
|
__libc_dlopen_mode (name, RTLD_NOW | __RTLD_DLOPEN)
|
||||||
extern void *__libc_dlopen_mode (const char *__name, int __mode);
|
extern void *__libc_dlopen_mode (const char *__name, int __mode);
|
||||||
extern void *__libc_dlsym (void *__map, const char *__name);
|
extern void *__libc_dlsym (void *__map, const char *__name);
|
||||||
extern void *__libc_dlvsym (void *map, const char *name, const char *version);
|
extern void *__libc_dlvsym (void *map, const char *name, const char *version);
|
||||||
|
|
|
@ -35,11 +35,8 @@ __libgcc_s_init (void)
|
||||||
void *resume, *personality;
|
void *resume, *personality;
|
||||||
void *handle;
|
void *handle;
|
||||||
|
|
||||||
/* Use RTLD_NOW here for consistency with pthread_cancel_init.
|
/* See include/dlfcn.h. Use of __libc_dlopen requires RTLD_NOW. */
|
||||||
RTLD_NOW will rarely make a difference here because unwinding is
|
handle = __libc_dlopen (LIBGCC_S_SO);
|
||||||
already in progress, so libgcc_s.so has already been loaded if
|
|
||||||
its unwinder is used. */
|
|
||||||
handle = __libc_dlopen_mode (LIBGCC_S_SO, RTLD_NOW | __RTLD_DLOPEN);
|
|
||||||
|
|
||||||
if (handle == NULL
|
if (handle == NULL
|
||||||
|| (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
|
|| (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
|
||||||
|
|
|
@ -49,7 +49,8 @@ pthread_cancel_init (void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle = __libc_dlopen_mode (LIBGCC_S_SO, RTLD_NOW | __RTLD_DLOPEN);
|
/* See include/dlfcn.h. Use of __libc_dlopen requires RTLD_NOW. */
|
||||||
|
handle = __libc_dlopen (LIBGCC_S_SO);
|
||||||
|
|
||||||
if (handle == NULL
|
if (handle == NULL
|
||||||
|| (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
|
|| (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
|
||||||
|
|
Loading…
Reference in New Issue