Summary:
--------
gen_ld_script is removing a vital unversioned symlink from some packages, and
this breaks libtool lt_dlopenext consumers at runtime.

Details:
--------
While examining bug #486640, I discovered a concerning interaction [1] between
libtool's lt_dlopenext and gen_ld_script.

I don't have a good handle on how many packages are affected, but it would be
an code that uses lt_dlopenext to try and find a library.

For our example, we're using the fact that sys-power/nut wants to use libusb
from dev-libs/libusb-compat.

dev-libs/libusb-compat has these files:
/usr/lib64/libusb.so  (from gen_ld_script)
/lib64/libusb-0.1.so.4.4.4
/lib64/libusb-0.1.so.4 (symlink to 4.4.4)

lt_dlopenext is given the basename of a library to find. In this case, the
(modified) code tries both libusb and libusb-0.1, with slightly different 
failures:

1. lt_dlopenext cannot parse linker scripts at all, so the libusb.so from
   gen_ld_script cannot be opened.
2. lt_dlopenext only tries to append .so, it doesn't add version specifiers.

If I manually add a symlink:
/lib64/libusb-0.1.so -> /lib64/libusb-0.1.so.4
then lt_dlopenext succeeds.

This led me to looking at the libusb-compat in more detail.
Before gen_ld_script runs, it has the library and two symlinks in /usr/lib64:
/usr/lib64/libusb-0.1.so.4.4.4
/usr/lib64/libusb-0.1.so.4 (symlink)
/usr/lib64/libusb.so (symlink)
At this stage, lt_dlopenext works still.

Now after gen_ld_script, the unversioned symlink is replaced by a linker
script. The versioned symlink and base file have moved to /lib64.

Since lt_dlopenext cannot handle the linker script, and the unversioned symlink
is gone, we now get a failure.

Proposed Fix:
-------------
I would like to propose that gen_ld_script does NOT remove the unversioned
symlinks, but instead moves them along with the versioned symlinks.

Questions:
----------
How can we sanely get all user systems updated for this subtle bug?

Comments:
---------
In bug #4411, comment 43, vapier noted:
> any package that does dlopen("libfoo.so") without the version info like 
> ".so.X" is broken.
In this case, the lt_dlopenext consumer is explicitly testing multiple versions
of libusb at runtime, and picking the correct interface: it doesn't need to
depend on a specific version. This is also because the lt_dlopenext interface
does NOT accepted files versioned after the .so: it needs the filename with no
extensions.

[1] I do half-expect vapier, flameeyes or patrick to shoot me down, and tell me
the package is doing something wrong, but I've also got a chance of this
actually being a system breakage.

-- 
Robin Hugh Johnson
Gentoo Linux: Developer, Infrastructure Lead
E-Mail     : robb...@gentoo.org
GnuPG FP   : 11ACBA4F 4778E3F6 E4EDF38E B27B944E 34884E85

Reply via email to