Andreas Longwitz
2018-Aug-31 22:32 UTC
Constraints in libmap(32).conf do not work as expected, possible bug in rtld-elf
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
Konstantin Belousov
2018-Sep-02 12:06 UTC
Constraints in libmap(32).conf do not work as expected, possible bug in rtld-elf
On Sat, Sep 01, 2018 at 12:32:07AM +0200, Andreas Longwitz wrote:> 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:I am having problem understanding what do you mean by step1/step2. The refobj reference that you cache in the patch, comes into load_object() as the pointer to the object which initiate the load_object() call. It is NULL for preloaded objects, otherwise it is not. So, could you, please, explain where does it get passed as NULL in your case ? Also, your patch makes the ref_object stuck for all future invocations of the load_object(), so it cannot be correct for this reason alone. Another note is that libmap.conf use that you put it for, is quite the strengthen of the original purpose. You should just add the pathes with your libraries to LD_32_LIBRARY_PATH or configure them into /var/run/ld-elf32.so.hints using 'ldconfig -32'.> > --- 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.