Bug 1148241 - prelink shall use standard LD_LIBRARY_PATH by default
Summary: prelink shall use standard LD_LIBRARY_PATH by default
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Fedora
Classification: Fedora
Component: prelink
Version: 20
Hardware: Unspecified
OS: Linux
unspecified
low
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2014-10-01 03:04 UTC by Alexander Murashkin
Modified: 2014-10-01 05:22 UTC (History)
2 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2014-10-01 05:22:59 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Alexander Murashkin 2014-10-01 03:04:57 UTC
Description of problem:

Prelink fails to prelink binaries and libraries if their dependency found in ld.so.cache is not the same as in /usr/lib.

Prelink shall set LD_LIBRARY_PATH=/usr/lib (or similar) by default.

Version-Release number of selected component (if applicable):

prelink-0.5.0-1.fc20.x86_64

How reproducible:

Install third party library that has the same name as standard library and adds itself to /etc/ld.so.conf.d. For exampe, xorg-x11-drv-nvidia-libs-331.89-2.fc20.x86_64 has

/usr/lib64/nvidia/libGL.so.1

and there is 

/lib64/libGL.so.1

Install binary that has /usr/lib (or similar) in RPATH or RUNPATH, for example

mate-control-center-1.6.2-3.fc20.x86_64

# cat /etc/ld.so.conf.d/nvidia-lib64.conf 
/usr/lib64/nvidia

# readelf --dynamic /usr/bin/mate-display-properties | grep PATH
 0x000000000000000f (RPATH)              Library rpath: [/usr/lib64]

Now run prelink (you might need to remove prelink cache and/or force it) and you will get a scores of messages similar to one below.

/usr/sbin/prelink: Could not prelink /usr/bin/mate-display-properties because it doesn't use /usr/lib64/nvidia/libGL.so.1, but one of its dependencies has been prelinked against it

It happens because 

- the binary has RPATH (or RUNPATH), it is used first, and so /usr/lib64/libGL.so.1 is found. 
- the libraries do not have ...PATH, so /usr/lib64/nvidia/libGL.so.1 in /etc/ld.so.cache is found
- prelink fails as the two found libraries are different

prelink fails to prelink mate-display-properties and other binaries and their dependencies if the dependencies are not used by any successfully prelinked binaries.

As a side effect rpm --verify may fail on libraries that depend on the failed libraries 

rpm -Vf /usr/lib64/libspeexdsp.so.1.5.0
prelink: /usr/lib64/libspeexdsp.so.1.5.0: at least one of file's dependencies has changed since prelinking
S.?......    /usr/lib64/libspeexdsp.so.1.5.0

------------------------------------------------------
Proposal:

The suggestion is to set appropriate LD_LIBRARY_PATH either in prelink itself or in /etc/sysconfig/prelink. In the last case in can be

export LD_LIBRARY_PATH=/usr/lib64

or even

echo /usr/lib$([[ $(uname -m) == x86_64 ]] && echo 64 || :)

My preference is to do it in prelink itself and add option --no-ld-library-path.

For instance, on my Fedora 20 system there are ~4000 /usr/bin ELF executable and ~400 of them have RPATH or RUNPATH. It seems unfeasable to remove RPATH/RUNPATH from all these binaries in forseeble future. Keeping current default unset LD_LIBRARY_PATH in prelink leads to the described problems. 

---------------------------------------------------
Explanation:

Let assume that there is binary B that depends on library libX that in turn depends on library libY. There are three cases - 
(1) there is only one libX instance
(2) there are multiple libX instances and libX path in ld.so.cache points to /usr/lib/libX...
(3) there are multiple libX instances and libX path in ld.so.cache points to /D/libX that is a different library than /usr/lib/libX...

The proposed change impacts prelinking the way described below.

In the cases (1) and (2) the same libX instance will be found during prelinking with or without LD_LIBRARY_PATH=/usr/lib.

In the case (3) there are three subcases

(3A) If RPATH is set to /D it overrides LD_LIBRARY_PATH (so it does not matter if LD_LIBRARY_PATH is set) - prelinking of B (and, possibly, libX and libY) will succeed as B and libY depend on /D/libX.

Assuming that in the case (3) RPATH is not set to /D:

(3B) When RUNPATH is not set to /D

If LD_LIBARY_PATH is not set - prelinking of B (and, possibly, libX and libY) will fail as B depends on /usr/lib/libX but libY depends on /D/libX
 
If LD_LIBARY_PATH is set - prelinking of B (and, probably, libX and libY) will succeed as both B and libY depend on /usr/lib/libX

(3C) When RUNPATH is set to /D

If LD_LIBARY_PATH is not set - prelinking of B (and, possibly, libX and libY) will succeed as B and libY depend on /D/libX

If LD_LIBARY_PATH is set - prelinking of B (and, probably, libX and libY) will succeed as both B and libY depend on /usr/lib/libX, but found library will not be /D/libX.

--------------------------------------------

Conclusion:

In the cases (1), (2), and (3A) setting LD_LIBARY_PATH does not change anything. 

In the case (3B) setting LD_LIBARY_PATH resolves the issue (removes message, improves exec performance, fixes rpm --verigy in many cases). 

In the case (3C) setting LD_LIBARY_PATH still prelinks the binary and dependencies though differently. (3B) benefits overcome possible exec performance loss.

Comment 1 Alexander Murashkin 2014-10-01 03:08:37 UTC
This issue is related to https://access.redhat.com/solutions/25215 and bug 204448

Comment 2 Jakub Jelinek 2014-10-01 05:22:59 UTC
That is nonsense, prelink needs to match what is done normally, and that is certainly not a custom LD_LIBRARY_PATH.  You can pass --ld-library-path to prelink if you for whatever reason need that though.
If mate-display-properties has /usr/lib or /usr/lib64 in DT_RPATH or DT_RUNPATH, you should complain to the package maintainer, that is against Fedora packaging guidelines.


Note You need to log in before you can comment on or make changes to this bug.