Fix some DLL hell: use dladdr() to find plugin dir

Normally one would dlopen() a shared object's basename, not its absolute
path.  However, lib/krb5/plugin.c, in an effort to be zero-conf-ish,
wants to readdir() to find plugins to load, and in the process it ends
up defeating the RTLD's search-the-caller's-rpath.

This commit partially addresses this by allowing the use of $ORIGIN in
plugin_dir values and using them for the default (except on OS X).

This allows multiple Heimdal versions installed on the same host, but
with different plugin ABIs, to co-exist.  A step forward for doing make
check on hosts where Heimdal is installed.

For now we hardcode $ORIGIN/../lib/plugin/krb5 (linux, Solaris, *BSD),
or $ORIGIN (Windows; for assemblies objects need to be in the same
directory) and we eval $ORIGIN by using dladdr() (Linux, Solaris) or
GetModuleHandleEx() (Win32, via a dladdr() wrapper in libroken) to find
the path to libkrb5 whose dirname to use as $ORIGIN.  For Windows,
because we need the plugins to be in the same directory as libkrb5, we
require a prefix on plugin DLLs ("plugin_krb5_") to distinguish them
from other objects.

We should add a special token to mean "look in $ORIGIN, sure, but
dlopen() the plugin basenames only (so the RTLD can search the rpath)".
This commit is contained in:
Nicolas Williams
2013-09-04 22:23:13 -05:00
parent 3e0fd6449e
commit 3e74e2e3bb
7 changed files with 110 additions and 4 deletions

View File

@@ -303,6 +303,10 @@ static const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg }
/* MSVC doesn't provide a <dlfcn.h>, but we implement it in lib/roken. */
#define HAVE_DLOPEN 1
/* Define to 1 if you have the `dladdr' function. */
/* MSVC doesn't provide a <dlfcn.h>, but we implement it in lib/roken. */
#define HAVE_DLADDR 1
/* Define to 1 if you have the `dn_expand' function. */
/* #undef HAVE_DN_EXPAND */