From: Sam Hartman <firstname.lastname@example.org>
Subject: gssapi mechanism glue dlcloses objects potentially after they are already unloaded
Date: Wed, 16 May 2012 20:41:37 -0400
moonshot has consistently gotten a linker error on Linux at process exit
time. I traced it with a debugger today and figured out what seems to be
exit calls the library finalization functions for loaded libraries.
That calls gssint_mechglue_fini. If PROGRAM_EXITING() returns false
(which it always does) that calls freeMechList() which indirectly calls
dlclose on loaded objects.
Unfortunately, moonshot depends circularly on libgssapi_krb5. The linker
chooses to break this dependency by finalizing moonshot first.
Then when we call dlclose, we get:
Inconsistency detected by ld.so: dl-close.c: 743: _dl_close: Assertion
`map->l_i nit_called' failed!
This is arguably a linker bug.
A few observations:
1) It would be nice to have a better definition of PROGRAM_EXITING for
2) There are reasonably good reasons for GSS mechanisms to call into
libgssapi_krb5 even though they are loaded by it.
Finally, I suspect that gssint_mechglue_fini may tend to be useless if a
mechanism that calls into the mechglue is loaded. Consider what
happens. The cases where fini matters is where the gss library would
like to be unloaded. So, an application dlopens a plugin that loads
gssapi_krb5. That eventually opens moonshot, which creates a second
reference to libgssapi_krb5.
The application dlcloses the plugin, removing one reference to
libgssapi_krb5. The linker really needs to garbage collect or otherwise
walk the graph in order to determine that it can get rid of the
moonshot-gssapi subgraph. So on Linux, it looks a lot like this code
crashes at process exit and is likely to be useless otherwise.
Download (untitled) 1.6k
We decided to start using RTLD_NODELETE when loading plugin modules,
mostly for OpenSSL-related reasons. I think that should fix this
problem; I would be interested in test results.
Of course, this change also makes it even more pointless to dlclose() GSS
modules from the libgssapi_krb5 finalizer. But we need to at least free
the struct plugin_file_handle to avoid a memory leak on repeated loading
and unloading of libgssapi_krb5, and there is also Windows to consider.
Download (untitled) 480b