-
Notifications
You must be signed in to change notification settings - Fork 11.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Binaries linked with shared ASAN behave different on various distributions #62431
Comments
@hahnjo pinging you here because you issues the original report on the mailing list :) https://www.mail-archive.com/ubuntu-bugs@lists.ubuntu.com/msg6005262.html |
Most sanitizer functions are not intended to be interposed. Do you know why AFLplusplus does https://github.com/AFLplusplus/AFLplusplus/blob/7ca1b85c5e8229fa49620d0fb542c86965ef5abb/instrumentation/afl-compiler-rt.o.c#L1999-L2003 ? This is a weak definition and will lose to For
You get a non-interposable If you want to interpose it (weak definition in |
Sadly I don't understand yet why AFL++ requires that. Interesting! I think one thing which would be great to define is whether certain functions should be interposable or not and somehow enforce that downstream. |
We have an object file that is compiled into targets. I am open to other ideas how to solve that in our code. |
Yes, I think the first thing this should be adressed is to enforce from upstream that the " Then shared ASAN will be broken fro the AFL++ usecase, but I guess that is fine. The |
Since ASAN should be enabled by providing the |
sadly that is not possible because the runtime is built once and never again, and afterwards has to be linked with any target, asan or not. |
But is it a problem if That said, it doesn't solve the problem I reported here: https://bugs.launchpad.net/ubuntu/+source/llvm-defaults/+bug/1964487 |
This is not a problem, it is just like an unused symbol in the binary. I agree that your problem is not solved and indeed we should make sure that compiler-rt is not compiled with any -B option. This will break shared ASAN for AFL++ ok Ubuntu (just like on any other distribution. Later we should figure out how to support the linker-based ASAN detection which AFL++ uses. |
for those interested, can you please test https://github.com/AFLplusplus/AFLplusplus/tree/gccasan ? |
Have you considered using |
BTW is splitting AFL runtime an option (so that Asan part is linked only under |
I reported this to Ubuntu because I believe that is the best place to fix it: https://bugs.launchpad.net/ubuntu/+source/clang/+bug/2052954 |
It is possible to link ASan statically or dynamically. The default in Clang is static, and dynamic is to a certain degree experimental. On GCC (which uses compiler-rt) the default is dynamic and it is a stable feature.
While fuzzing with AFLplusplus I discovered a discrepancy on how it behaves on Ubuntu vs. Debian/Fedora/Nix. I raised an issue in AFL++, but we are unsure what and where the proper fix should be implemented.
A very similar issue exists with
__asan_default_options
, though no fix was proposed.Reproduction
The following experiments are performed on Debian and NOT on Ubuntu. See below for more information.
Suppose the following harness, which copies from outside an allocated region to some other buffer (y).
(
__asan_region_is_poisoned
is for instance defined in AFL++ and other tools. See issue on how.)Compiling and executing this with ASan should crash. And it is true in the default configuration.
clang harness.c -o harness -O0 -fsanitize=address && ./harness
clang harness.c -o harness -O0 -fsanitize=address -shared-libasan && LD_PRELOAD=$(clang -print-file-name=libclang_rt.asan-x86_64.so) ./harness
The reason for this is that
libclang_rt.asan-x86_64.so
exports__asan_region_is_poisoned
and makes it relocatable on Debian. On Ubuntu the symbol is exported but not relocatable, and therefore the correct implementation fromlibclang_rt.asan-x86_64.so
will be chosen.With GCC shared ASan is the default. And it works with static and shared ASan.
gcc harness.c -o harness -O0 -fsanitize=address && ./harness
gcc harness.c -o harness -O0 -fsanitize=address -static-libasan && ./harness
Why is shared ASan + Clang not working on Debian?
On Debian the
libclang_rt.asan-x86_64.so
exports__asan_region_is_poisoned
as dynamic relocatable. On Ubuntu it is not relocatable.The impact is that on Debian, ASan will use the stub
__asan_region_is_poisoned
defined by the main binary.On Ubuntu, ASan will use the
__asan_region_is_poisoned
from ASan, because it is statically referenced.This can be checked using the following command:
Why does this behavior only show on Debian and not Ubuntu?
Like already described, the output of
objdump --dynamic-reloc $(clang -print-file-name=libclang_rt.asan-x86_64.so)
is different on Ubuntu and Debian.The reason is that
dpkg-buildflags --get LDFLAGS
includes-Wl,-Bsymbolic-functions
, which avoids that exported symbols are made relocatable during linking. That way on Ubuntulibclang_rt.asan-x86_64.so
contains no relocatable functions.Proposed fix
Enable
-Bsymbolic-functions
for compiler-rt directly in LLVM, so the behavior is identical across distributions. This has already been done for clang-shlib here.Even though Ubuntu enabled this flag globally for performance reasons, it is actually the better behavior for shared ASAN, because it will avoid that binaries can "overwrite" functions which are internal to ASan.
Another options would be to drastically limit which functions ASan exports (this will also remove it from the relocation table). Though, this might not be the intended thing to do because certain internal functions are already called by tools.
References:
__asan_default_options
: https://www.mail-archive.com/ubuntu-bugs@lists.ubuntu.com/msg6005262.html (Not fixed)The text was updated successfully, but these errors were encountered: