musl locates the config file with search paths relative to the interpreter/loader by taking the path up to the second to last /, that is, it tries to drop the filename and dir. This logic is flawed when the interpreter contains multiple /'s between dir and filename. This commit fixes that. Example: ``` $ ./configure "--prefix=$PWD/build" "--syslibdir=$PWD/build/loader/lib" $ make install -j $ mkdir -p build/loader/etc example $ echo "$PWD/example" > "./build/loader/etc/ld-musl-$(arch).path" $ echo 'int f() {return 0;}' | ./build/bin/musl-gcc -shared -x c - -Wl,-soname,libf.so -o example/libf.so $ echo 'int f(); int main(){return f();}' | ./build/bin/musl-gcc -x c - -Lexample -lf -o example/a.out $ ./example/a.out && echo "works" works $ patchelf --set-interpreter "$PWD/build/loader/lib//ld-musl-$(arch).so.1" example/a.out $ ./example/a.out || echo "does not work" Error loading shared library libf.so: No such file or directory (needed by ./example/a.out) Error relocating ./example/a.out: f: symbol not found does not work ``` --- ldso/dynlink.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 5b9c8be4..3e7766ac 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -1065,8 +1065,12 @@ static struct dso *load_library(const char *name, struct dso *needed_by) size_t prefix_len; if (ldso.name[0]=='/') { char *s, *t, *z; - for (s=t=z=ldso.name; *s; s++) - if (*s=='/') z=t, t=s; + s=t=z=ldso.name; + do { + if (*s++ != '/') continue; + z=t, t=s-1; + while (*s == '/') ++s; + } while (*s); prefix_len = z-ldso.name; if (prefix_len < PATH_MAX) prefix = ldso.name; -- 2.25.1