Open fjricci opened 8 years ago
So WONTFIX?
Sorry, only noticed this now (my Samsung address is inactive). I'm afraid I don't see how we could fix this easily and not intercepting dlopen is undesirable too. Perhaps just treat this as known issue?
Yes. If asan is linked statically, the dlopen
call will happen from within the original binary (or DSO), which will have the correct RUNPATH
set. It's only a problem if dlopen
is called from within the asan dso.
So, the problem only appears with -shared-libasan
?
Adding the Yuri and Max who have more experience with shared-libasan
this hurts when developing on NixOS. one workaround is setting a shellHook = "export LD_LIBRARY_PATH=/run/opengl-driver/lib"
, if for example you need libGL. but I sure hope this workaround is not needed.
can't sanitizer dlopen look at the source shared object and find its rpath?
I think the original statement about this only applying when using -shared-libasan
is incorrect. When using statically linked asan the same thing can happen when you have 1 shared library that loads another. The setup looks like this:
// main.cc
#include <dlfcn.h>
#include <iostream>
int main() {
std::cout << "start main\n";
::dlopen("foo.so", RTLD_NOW);
std::cout << dlerror() << "\n";
std::cout << "end main\n";
}
// foo.cc
#include <cstdint>
#include <dlfcn.h>
#include <iostream>
__attribute__((constructor))
void loadbar() {
std::cout << "start foo\n";
::dlopen("bar.so", RTLD_NOW);
std::cout << "end foo\n";
}
// bar.cc
#include <iostream>
__attribute__((constructor))
void runbar() {
std::cout << "loaded bar\n";
}
# Makefile
foo/foo.so: lib.h foo.cc
clang++ -shared foo.cc '-Wl,-rpath,$$ORIGIN/../bar' -o foo/foo.so -fsanitize=address
bar/bar.so: lib.h bar.cc
clang++ -shared bar.cc -o bar/bar.so -fsanitize=address
main: main.cc lib.h foo/foo.so bar/bar.so
clang++ main.cc '-Wl,-rpath,$$ORIGIN/foo' -o main -fsanitize=address
clean:
rm -f main bar/bar.so foo/foo.so
In this case even with asan linked statically:
% ldd main
linux-vdso.so.1 (0x0000f3e552cf3000)
libstdc++.so.6 => /lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000f3e551f00000)
libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000f3e551e60000)
libresolv.so.2 => /lib/aarch64-linux-gnu/libresolv.so.2 (0x0000f3e551e30000)
libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000f3e551e00000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000f3e551c50000)
/lib/ld-linux-aarch64.so.1 (0x0000f3e552cba000)
It will fail to load bar
at runtime, and when you run with LD_DEBUG=libs
you can see it's using the RUNPATH from main:
237995: find library=bar.so [0]; searching
237995: search path=/home/ubuntu/repro-dlopen-issue/foo (RUNPATH from file ./main)
237995: trying file=/home/ubuntu/repro-dlopen-issue/foo/bar.so
237995: search cache=/etc/ld.so.cache
237995: search path=(SNIP) (system search path)
SNIP
end foo
bar.so: cannot open shared object file: No such file or directory
end main
Here's this project for testing: repro-dlopen-issue.zip
Extended Description
dlopen()
uses theRUNPATH
of the dso which calls it. This means that when a shared sanitizer dso interceptsdlopen
, theRUNPATH
of the sanitizer dso will be used instead of theRUNPATH
of the dso being intercepted.Repro steps:
Note that executing
clean
andsanitized_static
will succeed, while executingsanitized_dynamic
will fail.foo.c:
test.c: