This addresses issue #3862 (originally #460 (closed)) by implementing code that parses the search paths in /etc/ld.so.conf
for the private loader on Linux.
The /etc/ld.so.conf
file consists of one or more lines, where a line may be a search path, an include directive to include another configuration file or where a line may start with '#' if it is a comment. The include directives support globbing (see man 3 glob
and man 7 glob
for more information).
Some notes about compatibility:
- Alpine is a musl-based distribution, and the dynamic linker used by Alpine instead may look for
/etc/ld-musl-$(ARCH).path
. For instance, on x86-64, it would look for/etc/ld-musl-x86_64.path
. The format seems to be slightly different from/etc/ld.so.conf
. If the file is not present, musl simply defaults to "/lib:/usr/local/lib:/usr/lib". See also: https://www.musl-libc.org/doc/1.0.0/manual.html - Android uses bionic as its libc and instead looks for
/system/etc/ld.config.txt
. See also: https://android.googlesource.com/platform/bionic/+/master/linker/ld.config.format.md - While the FreeBSD man pages do seem to mention the existence of
/etc/ld.so.conf
, the default seems to be that the dynamic linker on FreeBSD looks for theldconfig_paths
andldconfig32_paths
keys in/etc/defaults/rc.conf
. - Mac OS X does not seem to have
/etc/ld.so.conf
either, butman dyld
seems to provide some useful hints.
We probably want to open new issues referring to #3862 and #460 (closed) for the other cases.
This PR implements the following:
- The
strncasecmp
function to match theinclude
directive. On second thought,strncmp
may work well enough, but it doesn't hurt to be case-insensitive. - The
fnmatch
function, which is required to implementglob
. Thefnmatch
lets us match a given string against a pattern including character ranges (e.g.[a-z]
), the any character (denoted as?
) and wildcards (denoted as '*'). Furthermore, multiple wildcards may be present. - The
glob
function which usesfnmatch
function and the Unix-specific directory iterator code that is currently present in DynamoRIO to match all found filenames against a given pattern. - The
getdelim
andgetline
functions which help us parse the config files line-by-line. - The
privload_parse_ld_conf
function which parses/etc/ld.so.conf
and any included config files and constructs an array of search paths by piggybacking on theglob
function, which can be used to append search paths to an array of search paths. - Finally, the
privload_locate
function has been extended to use theprivload_parse_ld_conf
, and otherwise falls back to the fixed array of system paths (see compatibility notes).
While the ld.so.conf
parsing itself is straight-forward on any POSIX system due to the existence of glob
and getline
, DynamoRIO originally did not provide these functions as the private loader cannot rely on libc, and it would be helpful to have a thorough review of the implementation of these functions.
I have tested this on:
- My desktop running Gentoo where
libgcc_s.so.1
is located in/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.0
by running:./bin64/drrun -c ./api/bin/libempty.so -- ls
. Before these changes, it was necessary to specify the correct path using theLD_LIBRARY_PATH
environment variable. - Ubuntu 20.04 LTS by running:
./bin64/drrun -c /api/bin/libempty.so -- ls
to be sure that there are no regressions introduced by this PR.