Constraints in libmap(32).conf do not work as expected, possible bug in rtld-elf
Andreas Longwitz
longwitz at incore.de
Fri Aug 31 22:32:18 UTC 2018
On a FreeBSD 10.4-STABLE r337823 (amd64) server I have to run some old
php52 scripts from an FreeBSD 8.4-STABLE r284383 (i386) server. I have
copied the old php software to /usr/local/php52, installed the ports
misc/compat8x and misc/compat9x and have copied all missing 32-bit
libraries from the old machine to /usr/local/lib32. With the following
libmap32.conf everything works fine:
## php52
/usr/local/lib /usr/local/lib32
/usr/local/lib/mysql /usr/local/lib32/mysql
Two examples:
-> ldd /usr/local/php52/bin/php
/usr/local/php52/bin/php:
libcrypt.so.5 => /usr/lib32/libcrypt.so.5 (0x28273000)
librt.so.1 => /usr/lib32/librt.so.1 (0x28292000)
libm.so.5 => /usr/lib32/libm.so.5 (0x28298000)
libxml2.so.5 => /usr/local/lib32/libxml2.so.5 (0x282c2000)
libz.so.5 => /usr/local/lib32/compat/libz.so.5 (0x283ec000)
libiconv.so.3 => /usr/local/lib32/libiconv.so.3 (0x283fe000)
libc.so.7 => /usr/lib32/libc.so.7 (0x284f2000)
libthr.so.3 => /usr/lib32/libthr.so.3 (0x2866c000)
-> ldd /usr/local/php52/lib/php/20060613/mysql.so
/usr/local/php52/lib/php/20060613/mysql.so:
libmysqlclient.so.16 =>
/usr/local/lib32/mysql/libmysqlclient.so.16 (0x28206000)
libc.so.7 => /usr/lib32/libc.so.7 (0x28070000)
libcrypt.so.5 => /usr/lib32/libcrypt.so.5 (0x2835e000)
libm.so.5 => /usr/lib32/libm.so.5 (0x2837d000)
libz.so.5 => /usr/local/lib32/compat/libz.so.5 (0x283a7000)
librt.so.1 => /usr/lib32/librt.so.1 (0x283b9000)
libthr.so.3 => /usr/lib32/libthr.so.3 (0x283bf000)
Because I like to use constraints in libmap32.conf I chenged the file to
## php52
[/usr/local/php52/]
/usr/local/lib /usr/local/lib32
[/usr/local/php52/lib/php/20060613/mysql.so]
/usr/local/lib/mysql /usr/local/lib32/mysql
The same examples as above shows that libmap does not work anymore:
-> ldd /usr/local/php52/bin/php
/usr/local/php52/bin/php:
libcrypt.so.5 => /usr/lib32/libcrypt.so.5 (0x28273000)
librt.so.1 => /usr/lib32/librt.so.1 (0x28292000)
libm.so.5 => /usr/lib32/libm.so.5 (0x28298000)
libxml2.so.5 => not found (0)
libz.so.5 => /usr/local/lib32/compat/libz.so.5 (0x282c2000)
libiconv.so.3 => not found (0)
libc.so.7 => /usr/lib32/libc.so.7 (0x282d4000)
libthr.so.3 => /usr/lib32/libthr.so.3 (0x2844e000)
-> ldd /usr/local/php52/lib/php/20060613/mysql.so
/usr/local/php52/lib/php/20060613/mysql.so:
libmysqlclient.so.16 => not found (0)
libc.so.7 => /usr/lib32/libc.so.7 (0x28070000)
The constraints in libmap.conf are handled in rtld-elf with the help of
contexts, and especially a "$DEFAULT$" context is used for all entries
in libmap.conf before the first constraint statement. Now when rtld-elf
loads a program the mapping rules from libmap.conf are applied. In a
first step rtld-elf does a direct mapping using the correct context. But
in a second step called "Searching for ..." rtld-elf uses always the
"$DEFAULT$" context, which in the last example is empty. Therfore
rtld-elf does never find a library in his searching step and cannot load
programs where searching for libraries is necessary.
I cannot see any reason why rtld-elf should change the context between
step1 and step2, The following patch provokes that rtld-elf uses the
context from step1 in step2 too:
--- rtld.c.orig 2018-03-20 16:56:48.000000000 +0100
+++ rtld.c 2018-08-31 23:17:18.051206000 +0200
@@ -186,6 +186,7 @@
static Obj_Entry obj_rtld; /* The dynamic linker shared object */
static unsigned int obj_count; /* Number of objects in obj_list */
static unsigned int obj_loads; /* Number of loads of objects (gen count) */
+static char *save_refobj_path;
static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */
STAILQ_HEAD_INITIALIZER(list_global);
@@ -1499,6 +1500,7 @@
if (libmap_disable || !objgiven ||
(name = lm_find(refobj->path, xname)) == NULL)
name = (char *)xname;
+ save_refobj_path = refobj->path;
dbg(" Searching for \"%s\"", name);
@@ -2831,7 +2833,7 @@
char *res;
len = strcspn(path, ":;");
- trans = lm_findn(NULL, path, len);
+ trans = lm_findn(save_refobj_path, path, len);
if (trans)
res = callback(trans, strlen(trans), arg);
else
This patch solves the described problem for me.
Andreas Longwitz
More information about the freebsd-stable
mailing list