Constraints in libmap(32).conf do not work as expected, possible bug in rtld-elf

Andreas Longwitz longwitz at
Tue Sep 11 20:48:12 UTC 2018

Thanks very much for answer !

Now I use the following libmap32.conf:

## php52
/usr/local/lib/mysql    /usr/local/lib32/mysql
/usr/local/lib          /usr/local/lib32

> 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 ?

Ok, I try to explain better:

step1 means: call of lm_find() in rtld.c (line 1500) and first argument
is refobj->path, which is used in libmap.c to find the correct entry in
the lmp_list.

step2 means: call of lm_findn() in rtld.c (line 2834) when called from
search_library_path(). In this case the first argument is NULL and in
libmap.c this means "$DEFAULT" entry in the lmp_list. Please notice that
after reading libmap32.conf in lm_init() the entry $DEFAULT in the
lmp_list does not exist, when all mappings are defined with constraints.

> 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.

I do not think so. The patch only caches refobj->path from step1 to use
the same path in step2. I have updated my patch a little bit to clarify,
that the patch only wants to change the call of lm_findn() in the case
of search_library_path():

--- rtld.c.orig 2018-03-20 16:56:48.000000000 +0100
+++ rtld.c      2018-09-11 21:44:03.333739000 +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 *lm_refobj_path = NULL;

 static Objlist list_global =   /* Objects dlopened with RTLD_GLOBAL */
@@ -1496,6 +1497,8 @@
          __DECONST(char *, xname)));

+    if (objgiven)
+       lm_refobj_path = refobj->path;
     if (libmap_disable || !objgiven ||
        (name = lm_find(refobj->path, xname)) == NULL)
        name = (char *)xname;
@@ -1513,8 +1516,10 @@
          (refobj != NULL &&
          (pathname = search_library_path(name, refobj->rpath)) != NULL) ||
           (pathname = search_library_path(name, gethints(false))) !=
-         (pathname = search_library_path(name, STANDARD_LIBRARY_PATH))
!= NULL)
+         (pathname = search_library_path(name, STANDARD_LIBRARY_PATH))
!= NULL) {
+           lm_refobj_path = NULL;
            return (pathname);
+       }
     } else {
        nodeflib = objgiven ? refobj->z_nodeflib : false;
        if ((objgiven &&
@@ -1526,10 +1531,13 @@
          (pathname = search_library_path(name, refobj->runpath)) !=
NULL) ||
          (pathname = search_library_path(name, gethints(nodeflib))) !=
          (objgiven && !nodeflib &&
-         (pathname = search_library_path(name, STANDARD_LIBRARY_PATH))
!= NULL))
+         (pathname = search_library_path(name, STANDARD_LIBRARY_PATH))
!= NULL)) {
+           lm_refobj_path = NULL;
            return (pathname);
+       }

+    lm_refobj_path = NULL;
     if (objgiven && refobj->path != NULL) {
        _rtld_error("Shared object \"%s\" not found, required by \"%s\"",
          name, basename(refobj->path));
@@ -2831,7 +2839,7 @@
        char  *res;

        len = strcspn(path, ":;");
-       trans = lm_findn(NULL, path, len);
+       trans = lm_findn(lm_refobj_path, path, len);
        if (trans)
            res = callback(trans, strlen(trans), arg);

> 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/ using 'ldconfig -32'.

I have tried this without success. With the original and
my constraints in libmap32.conf I got the following:

 -> /usr/local/php52/bin/php -v
Shared object "" not found, required by "php"

The error changed after setting LD_32_LIBRARY_PATH or (with same result)
the file /var/run/ using 'ldconfig -32.

 -> export LD_32_LIBRARY_PATH="/usr/local/lib32:/usr/local/lib32/mysql"
 -> /usr/local/php52/bin/php -v
/usr/local/lib/ unsupported file layout

This error disappears when I move this 64-bit library away,
but thats not a solution.

For your information I append the beginning of the dynamic section from
readelf output of /usr/local/php52/bin/php:

  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: []
 0x00000001 (NEEDED)                     Shared library: []
 0x00000001 (NEEDED)                     Shared library: []
 0x00000001 (NEEDED)                     Shared library: []
 0x00000001 (NEEDED)                     Shared library: []
 0x00000001 (NEEDED)                     Shared library: []
 0x00000001 (NEEDED)                     Shared library: []
 0x0000000f (RPATH)                      Library rpath: [/usr/local/lib]

Andreas Longwitz

More information about the freebsd-stable mailing list