DT_RUNPATH settings for all libraries

John Moser john.r.moser at gmail.com
Fri Jan 17 02:01:12 UTC 2014

Can we move to a DT_RUNPATH scheme for all libraries as below?


This change alone does almost nothing:  with the system files arranged
as they are now, there is no change in how linking works.


This change allows us to switch around libraries and to use different
versions of the same library.  This allows for increased compatibility.

For example:  every version of libfoo.so.2 should be
compatible--libfoo.so.2.15 should link properly with a program compiled
for libfoo.so.2.0.  On occasion and for various reasons, this sometimes
doesn't happen; it become useful to have different versions of the same
library installed, yet they conflict.  We have conflicting lib* packages.


On load, ld.so links dynamic libraries in the following order:

1.  DT_RPATH if DT_RUNPATH does not exist
2.  LD_LIBRARY_PATH environment if not SUID/SGID
4.  ld.so.cache file from ldconfig
5.  /lib and then /usr/lib

This means that a binary (a main executable file, including a shared
object that may execute as a main executable file) specifying dynamic
linking to libfoo.so.2 will currently link against the first one of the

1. $LD_LIBRARY_PATH/libfoo.so.2
2. The library specified in ld.so.cache
3. /lib/libfoo.so.2
4. /usr/lib/libfoo.so.2

A binary with DT_RPATH set will pre-empt $LD_LIBRARY_PATH, which breaks
that entire functionality.  We don't want that.

A binary with DT_RUNPATH set will insert a new step.  If DT_RUNPATH
contains "/var/lib/cat1:/var/lib/cat2" then the above checks the
following instead:

1. $LD_LIBRARY_PATH/libfoo.so.2
2. /var/lib/cat1/libfoo.so.2
3. /var/lib/cat2/libfoo.so.2
4. The library specified in ld.so.cache
5. /lib/libfoo.so.2
6. /usr/lib/libfoo.so.2

In this way, placing a different library at (2) or (3), or a symlink to
such, will cause that library to load instead.


Section 5.1 of the Filesystem Hierarchy Standard v2.2 ends in the
following stipulation:

    Applications must generally not add directories to the top level
    of /var. Such directories should only be added if they have some
    system-wide implication, and in consultation with the FHS mailing

I have investigated /var/lib, /var/cache, and /var/run and determined
that none of these is particularly suitable for this proposal.  /var/lib
looks close; however, the system is managing these contents without
concern for what the application expects to see there.  /var/run is for
the system state since boot, not persistent.  /var/cache is just the
wrong application.

Leveraging the above, I propose that the DT_RUNPATH of each application
be set as follows:


For x86_64:


In the future, it may become possible to install conflicting libraries
to support binaries mutually non-conflicting save for dependencies on
conflicting libraries.  To do so, a symlink to the conflicting library
wold be installed in the proper /var/sys/$PACKAGE/lib[64] directory.

The ability to do this depends on this proposal.  It also depends on
rewiring dpkg and apt to recognize and manage conflicts as alternatives,
or to package conflicting libraries as alternatives and improve the
dpkg-alternatives system to recognize when the majority of installed
packages in a system rely on package X and a minority rely on package Y.
 After all, somehow you need to decide which is "the main package" and
which is "installed for compatibility", and for what, and how to handle

The change proposed is harmless, non-standards-breaking, and compatible
with Debian, Ubuntu, Mint, and ELF-based distributions in general.  It
is heavily influenced by NixOS, although the particular mechanism comes
from a side project I never got started much (I don't like how NixOS
does it).  It is expandable to achieve similar goals to NixOS by setting


('default' is of course a misnomer; it's not straight 'lib' because you
may also mess with $PATH and put a bin and sbin in there, but that's a
big stretch)

Other ways to achieve the main goals of NixOS--running i.e. postgresql 7
8 9 and 10 at the same time--would be to use lxc, which is probably the
right way to do that.  Between that and other factors, I haven't
proposed that.


More information about the Ubuntu-devel-discuss mailing list