]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Increase robustness of internal dlopen() by using RTLD_NOW [BZ #22766]
authorTulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Thu, 26 Apr 2018 13:41:43 +0000 (10:41 -0300)
committerTulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Thu, 26 Apr 2018 13:41:43 +0000 (10:41 -0300)
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>
ChangeLog
include/dlfcn.h
sysdeps/gnu/unwind-resume.c
sysdeps/nptl/unwind-forcedunwind.c

index b0dae54e60f0f2d3526901089d128497780c447c..a0308095aafbf139f3d2678a280e05241e8baa4a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
 
        * sysdeps/unix/sysv/linux/getdirentries.c (getdirentries): Build iff
index 12ef913e1965d57117e76fdcdb1bd14d9c35ce07..694e71c83bd813cd042ba464d4bc04bf4f0cefbc 100644 (file)
@@ -31,8 +31,29 @@ extern char **__libc_argv attribute_hidden;
 
 /* 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) \
-  __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_dlsym   (void *__map, const char *__name);
 extern void *__libc_dlvsym (void *map, const char *name, const char *version);
index 7f9a1bf2c745c8adf2973a24d22aeff398068496..9283d925decb31f6cccbdde5fa117bcb5b983910 100644 (file)
@@ -35,11 +35,8 @@ __libgcc_s_init (void)
   void *resume, *personality;
   void *handle;
 
-  /* Use RTLD_NOW here for consistency with pthread_cancel_init.
-     RTLD_NOW will rarely make a difference here because unwinding is
-     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);
+  /* See include/dlfcn.h. Use of __libc_dlopen requires RTLD_NOW.  */
+  handle = __libc_dlopen (LIBGCC_S_SO);
 
   if (handle == NULL
       || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
index 67b8e74b5367c1a21b290c3164f3448fe283d25d..0621c8002f08e7eb0d75118d75528d17ef48ca46 100644 (file)
@@ -49,7 +49,8 @@ pthread_cancel_init (void)
       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
       || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL