This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCHv2] Increase robustness of internal dlopen() by using RTLD_NOW [BZ #22766]
- From: Carlos O'Donell <carlos at redhat dot com>
- To: Tulio Magno Quites Machado Filho <tuliom at linux dot ibm dot com>, libc-alpha at sourceware dot org, szabolcs dot nagy at arm dot com, Florian Weimer <fweimer at redhat dot com>
- Date: Wed, 25 Apr 2018 21:01:57 -0400
- Subject: Re: [PATCHv2] Increase robustness of internal dlopen() by using RTLD_NOW [BZ #22766]
- Autocrypt: addr=carlos at redhat dot com; prefer-encrypt=mutual; keydata= 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 ibHNRWhRbl/5Vl7TzYVDjJI=
- Openpgp: preference=signencrypt
- References: <72bf4b7b-3129-21a7-af89-24aea13c0b04@redhat.com> <20180425192637.5977-1-tuliom@linux.ibm.com>
On 04/25/2018 03:26 PM, Tulio Magno Quites Machado Filho wrote:
> Carlos O'Donell <carlos@redhat.com> writes:
>
>> On 04/25/2018 07:42 AM, Tulio Magno Quites Machado Filho wrote:
>>> Prevent random runtime crashes due to missing symbols caused by mixed
>>> libnss_* versions.
>>
>> You are arguing that this should fail at the first call into the NSS
>> service, which causes the initial dlopen? That is OK with me.
>
> Yes. I'm agreeing with Szabolcs' proposal [1].
>
> [1] https://sourceware.org/bugzilla/show_bug.cgi?id=22766
>
>> An even further patch would be to load all NSS modules early, and that's
>> something Florian and I have discussed. However, I'm not recommending
>> you do that now, but I wanted to be clear about a direction that this
>> code might take.
>
> Ack. Makes sense.
>
>> We should cleanup more.
>>
>> sysdeps/gnu/unwind-resume.c: handle = __libc_dlopen_mode (LIBGCC_S_SO, RTLD_NOW | __RTLD_DLOPEN);
>> sysdeps/nptl/unwind-forcedunwind.c: handle = __libc_dlopen_mode (LIBGCC_S_SO, RTLD_NOW | __RTLD_DLOPEN);
>
> Done.
>
>> Since we are now using RTLD_NOW:
>>
>> * Switch back to __libc_dlopen (effectively reverting part of
>> Florian's 08c6e95234c, but leave the comments)
>
> Done.
>
>> * Add a big comment in dlfcn.h to explain why RTLD_NOW is needed:
>> * Same comment as in commit 08c6e95234c, plus NSS case.
>
> Done.
>
> --- 8< ---
>
> Prevent random runtime crashes due to missing symbols caused by mixed
> libnss_* versions.
>
> 2018-04-25 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.
>
> Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
OK with the changes below.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
> ---
> include/dlfcn.h | 7 ++++++-
> sysdeps/gnu/unwind-resume.c | 2 +-
> sysdeps/nptl/unwind-forcedunwind.c | 3 ++-
> 3 files changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/include/dlfcn.h b/include/dlfcn.h
> index 12ef913e19..558c9bfe17 100644
> --- a/include/dlfcn.h
> +++ b/include/dlfcn.h
> @@ -31,8 +31,13 @@ extern char **__libc_argv attribute_hidden;
>
> /* Now define the internal interfaces. */
>
> +/* Use RTLD_NOW here because:
> + 1. For consistency between __libgcc_s_init and pthread_cancel_init;
> + 2. It allows libnss_* to provide a fallback code at dlopen() time in order
> + to prevent missing symbols caused by mixed glibc versions. Using
> + RTLD_LAZY here could cause random failures at runtime. */
Suggest:
/* 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);
> diff --git a/sysdeps/gnu/unwind-resume.c b/sysdeps/gnu/unwind-resume.c
> index 7f9a1bf2c7..72a04c7969 100644
> --- a/sysdeps/gnu/unwind-resume.c
> +++ b/sysdeps/gnu/unwind-resume.c
> @@ -39,7 +39,7 @@ __libgcc_s_init (void)
> 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. */
^^^ This should be adjusted to:
/* See include/dlfcn.h. Use of __libc_dlopen requires RTLD_NOW. */
> - handle = __libc_dlopen_mode (LIBGCC_S_SO, RTLD_NOW | __RTLD_DLOPEN);
> + handle = __libc_dlopen (LIBGCC_S_SO);
>
> if (handle == NULL
> || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
> diff --git a/sysdeps/nptl/unwind-forcedunwind.c b/sysdeps/nptl/unwind-forcedunwind.c
> index 67b8e74b53..dbd8d66cda 100644
> --- a/sysdeps/nptl/unwind-forcedunwind.c
> +++ b/sysdeps/nptl/unwind-forcedunwind.c
> @@ -49,7 +49,8 @@ pthread_cancel_init (void)
> return;
> }
>
> - handle = __libc_dlopen_mode (LIBGCC_S_SO, RTLD_NOW | __RTLD_DLOPEN);
> + /* __libgcc_s_init depends on RTLD_NOW being used here. */
Suggest:
/* 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
>
--
Cheers,
Carlos.