Bug#416266: embedding perl, libltdl and RTLD_GLOBAL

Josip Rodin joy at debbugs.entuzijast.net
Wed Dec 9 11:23:41 UTC 2009


Alan, what do you think about the below? The *advise example is right out
of libtool documentation :)

I've noticed this local commit:
http://github.com/alandekok/freeradius-server/commit/4df74f9b1497fc4c88f9159a680707041c70a23d

Maybe it's about a similar issue?

On Mon, Nov 30, 2009 at 12:08:20PM +0200, Niko Tyni wrote:
> I've been looking at the "libltdl and RTLD_GLOBAL" issue with embedding
> perl in a dlopen'd plugin.
> 
> An instance of this with freeradius is #416266 (recently reassigned to
> perl), and I see #327585 against openldap is another one.
> 
> To recap, the problem is that lt_dlopen() from the Debian system libltdl
> has called dlopen(3) with RTLD_LOCAL instead of RTLD_GLOBAL ever since
> #195821 was fixed. As the compiled XS modules aren't linked against
> libperl, its symbols aren't exposed to them, resulting in errors like
> '/usr/lib/perl/5.10/auto/Data/Dumper/Dumper.so: undefined symbol: Perl_sv_cmp'.
> 
> Observations:
> 
> - this problem isn't specific to perl and can easily be triggered with the
>   freeradius rlm_python module too [1]
> 
> - it's clearly possible to dlopen() compiled Perl modules from a dlopen'd
>   module if you don't use libltdl, see apache2+libapache2-mod-perl2 for
>   an example
> 
> - the XS modules are actually plugins in a private directory, not generic
>   shared libraries. Having unresolved symbols in a plugin without
>   a corresponding NEEDED entry seems to be very common, see for
>   example /usr/lib/apache2/modules, /usr/lib/python2.5/lib-dynload/,
>   /usr/lib/cdebconf etc.
> 
> - as noted in #327585, linking the XS shared objects against libperl
>   is potentially a problem on *i386, where /usr/bin/perl is statically
>   linked with libperl.a for performance reasons. (I don't have any data
>   about these performance reasons myself, I'm relying on hearsay and
>   /usr/share/doc/perl/README.Debian.gz here.)
> 
>   While this does seem to work in a quick and limited test of mine,
>   it would bring in both libperl.a and libperl.so for all uses of
>   /usr/bin/perl that need XS modules, and I'm not sure which version of
>   the functions would get used later. If the PIC versions win, we'd be
>   giving away the performance benefit we got from static linking in the
>   first place.
> 
>   At the very least, it would add 1.5M to the size of the perl-base
>   package on i386 AFAICS. I'm not sure how much the memory footprint of
>   the /usr/bin/perl invocations would increase.
> 
>   Also note that we currently ship /usr/lib/libperl.a on all the
>   architectures, so everything that applies to the i386 /usr/bin/perl
>   case applies to anybody using the static library on the other archs too.
> 
>   Given that i386 is still our most popular architecture, the other
>   proposed options don't seem very appealing either:
>     * only link the modules against libperl.so on the other architectures
>       (no fix for i386)
>     * link /usr/bin/perl dynamically on i386 too
>       (reduced performance in the very common case
>        for the benefit of a very uncommon case)
> 
> - it turns out libltdl nowadays does have an interface where you can
>   specify RTLD_GLOBAL. From the libtool Changelog.2007:
> 
>     2007-05-08  Gary V. Vaughan  <gary at gnu.org>
> 
>         Without this patch, lt_dlopen always opens modules with symbol
>         visibility set according to the underlying implementation.
>         Here, we add lt_dlopenadvise() to allow callers to request,
>         among other things, local or global symbol visibility from the
>         underlying dlloader:
> 
>   Indeed, the attached proof of concept makes the freeradius problem go away
>   for me, and I expect openldap could work with something similar. (FWIW,
>   note that the trivial my_dlopenextglobal() function was adapted from the
>   libtool documentation, so it might be considered to be under the GFDL.)
> 
> Josip: based on the above, I think #416266 should be fixed in freeradius
> and not in perl. If you agree, please reassign back yourself.
> 
> [1]: add python to the instantiate{} block in radiusd.conf
> and something like
> 
> # cat /etc/freeradius/modules/python
> python {
>                 mod_instantiate = radiusd_test
>                 func_instantiate = instantiate
> }
> # cat /usr/local/lib/python2.5/site-packages/radiusd_test.py 
> import sys
> import socket
> 
> def instantiate(test):
>     sys.stderr.write("hello, world!")
> 
> and you get 
> 
> rlm_python:EXCEPT:<type 'exceptions.ImportError'>: /usr/lib/python2.5/lib-dynload/_socket.so: undefined symbol: PyExc_ValueError
> rlm_python:python_load_function: failed to import python function 'radiusd_test.instantiate'
> -- 
> Niko Tyni   ntyni at debian.org

> >From 260797d463e6d94254520160236af864c54c5589 Mon Sep 17 00:00:00 2001
> From: Niko Tyni <ntyni at debian.org>
> Date: Sun, 29 Nov 2009 22:10:30 +0200
> Subject: [PATCH] Switch to lt_dlopenadvise() to get RTLD_GLOBAL set.
> 
> Proof of concept for fixing http://bugs.debian.org/416266
> ---
>  src/main/modules.c |   17 ++++++++++++++++-
>  1 files changed, 16 insertions(+), 1 deletions(-)
> 
> diff --git a/src/main/modules.c b/src/main/modules.c
> index ea1c256..7a93b0e 100644
> --- a/src/main/modules.c
> +++ b/src/main/modules.c
> @@ -391,6 +391,21 @@ int detach_modules(void)
>  }
>  
>  
> +static lt_dlhandle my_dlopenextglobal (const char *filename)
> +{
> +	lt_dlhandle handle = 0;
> +	lt_dladvise advise;
> +
> +	if (!lt_dladvise_init (&advise) && !lt_dladvise_ext (&advise)
> +	    && !lt_dladvise_global (&advise))
> +		handle = lt_dlopenadvise (filename, advise);
> +
> +	lt_dladvise_destroy (&advise);
> +
> +	return handle;
> +}
> +
> +
>  /*
>   *	Find a module on disk or in memory, and link to it.
>   */
> @@ -411,7 +426,7 @@ static module_entry_t *linkto_module(const char *module_name,
>  	/*
>  	 *	Keep the handle around so we can dlclose() it.
>  	 */
> -	handle = lt_dlopenext(module_name);
> +	handle = my_dlopenextglobal(module_name);
>  	if (handle == NULL) {
>  		cf_log_err(cf_sectiontoitem(cs),
>  			   "Failed to link to module '%s': %s\n",
> -- 
> 1.6.5.2
> 


-- 
     2. That which causes joy or happiness.






More information about the Perl-maintainers mailing list