[Bug 1842730]
Cvs-commit
1842730 at bugs.launchpad.net
Wed Nov 27 20:21:18 UTC 2019
The master branch has been updated by Florian Weimer
<fw at sourceware.org>:
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=f63b73814f74032c0e5d0a83300e3d864ef905e5
commit f63b73814f74032c0e5d0a83300e3d864ef905e5
Author: Florian Weimer <fweimer at redhat.com>
Date: Wed Nov 13 15:44:56 2019 +0100
Remove all loaded objects if dlopen fails, ignoring NODELETE [BZ #20839]
This introduces a “pending NODELETE” state in the link map, which is
flipped to the persistent NODELETE state late in dlopen, via
activate_nodelete. During initial relocation, symbol binding
records pending NODELETE state only. dlclose ignores pending NODELETE
state. Taken together, this results that a partially completed dlopen
is rolled back completely because new NODELETE mappings are unloaded.
Tested on x86_64-linux-gnu and i386-linux-gnu.
Change-Id: Ib2a3d86af6f92d75baca65431d74783ee0dbc292
--
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to glibc in Ubuntu.
https://bugs.launchpad.net/bugs/1842730
Title:
glibc: dlopen crash after a previously failed call to dlopen
Status in GLibC:
Fix Released
Status in glibc package in Ubuntu:
New
Bug description:
Environment
===========
Ubuntu 18.04.3 LTS
Linux 4.15.0-60-generic #67-Ubuntu SMP Thu Aug 22 16:55:30 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
libc6:amd64 2.27-3ubuntu1
gcc 4:7.4.0-1ubuntu2.3
Steps to reproduce the crash
============================
(note: all libraries are linked with --no-as-needed to keep them as
DT_NEEDED entries in the dynamic section, even though they are
unused.)
1) create an empty library libNOTFOUND.so
2) create an empty library libB.so, linked to libNOTFOUND.so
3) create an empty library libA.so, linked to glibc's librt.so
4) create an empty library libPLUGIN.so, linked to libA.so and libB.so, set DT_RUNPATH to '$ORIGIN'
5) create an empty library libMAIN.so
6) create an executable, linked to libMAIN.so and libdl.so, set DT_RUNPATH to '$ORIGIN', this program calls:
a) dlopen("<absolute path to>/libPLUGIN.so")
b) dlopen("<absolute path to>/libMAIN.so")
Behaviour
=========
a) dlopen("<absolute path to>/libPLUGIN.so") fails because it cannot find libNOTFOUND.so via default search methods. This is wanted and OK!
b) dlopen("<absolute path to>/libMAIN.so") raises SIGSEGV somewhere deep inside the dynamic linking code of glibc (backtrace attached). Expected result: returns a valid handle to libMAIN.so.
Comments
========
Attached is a simple test script which does all the steps from above
and also shows the workaround: Ensure that librt.so is loaded and
fully initialized before the failing call to
dlopen("<...>/libPLUGIN.so") happens. This can be done either via
LD_PRELOAD or by linking the executable to librt.so.
You can also replace librt.so with libpthread.so to reproduce this
behaviour. Any other library I tried instead of librt.so (e.g.
libm.so) does not trigger this bug.
I also attached a trace with LD_DEBUG=all. Here you can see that glibc
tries to relocate librt.so while it loads libMAIN.so. I would expect
that librt.so is loaded/relocated when libPLUGIN.so is dlopen'ed or
that it is neither loaded nor relocated because libPLUGIN.so has unmet
dependencies.
This example is a stripped down version of a real scenario where an
application was misconfigured.
To manage notifications about this bug go to:
https://bugs.launchpad.net/glibc/+bug/1842730/+subscriptions
More information about the foundations-bugs
mailing list