Skip to content
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

Fix ASAN linking #233

Merged
merged 8 commits into from
Apr 24, 2023
Merged

Fix ASAN linking #233

merged 8 commits into from
Apr 24, 2023

Conversation

maxammann
Copy link
Contributor

@maxammann maxammann commented Apr 21, 2023

After upgrading LibAFL from 0.8 to 0.9 the test tls::vulnerabilities::tests::test_seed_heartbleed started to fail. This test checks whether AddressSanitizer is correctly detecting heartbleed in OpenSSL 1.0.
The solution is to use -fsanitize=address instead of linking libasan manually 😵‍💫 and using Ubuntu (which uses a libclang_rt.asan with non-dynamic symbol exports). Linking against libasan is bad because it is from GCC.

Why did ASAN stop working?

LibAFL defines a weak symbol __libafl_asan_region_is_poisoned. The fuzzing target, which is linked to the final Rust binary, is a sanitized (-fsanitize=address -shared-libasan) static library. Because only this static library is sanitized we have to use the shared DSO version of ASAN.

ASAN was linked with the Rust binary and the static library using -lasan.
Now, weak symbols from static libraries are preferred over the dynamic ASAN library.
Therefore, ASAN used the invalid weak symbol from LibAFL. This is valid and not a bug. Linking order does not change this behavior.

Why did this happen with the update from LibAFL 0.8 to 0.9?

The weak __libafl_asan_region_is_poisoned from LibAFL is only included if it is referenced. Else the linker will discard it because it is dead code.
Apparently something in LibAFL changed which made it believe that __libafl_asan_region_is_poisoned is required.

How can we solve this?

Two things are involved here:

  • Pass -fsanitize=address to the linker. This will make sure that the LLVM libclang_rt is used instead of GCC libasan. On Ubuntu libclang_rt uses the correct __libafl_asan_region_is_poisoned symbol.
  • Do never link to libasan through e.g. a build.rs script or RUSTFLAGS.
  • Use clang as a linker. By default, Rust will use cc as linker binary for x86_64 Linux targets.
    • cc will link against the GCC ASAN runtime called libasan.so. This might be invalid with the sanitization applied to the fuzzing target, which uses LLVM.
    • Enable default-linker-libraries, such that it will automatically link against ASAN. This works because the static library (fuzzing target) is compiled with clang and wants to link against ASAN.
  • Set LD_LIBRARY_PATH, such that the LLVM runtime is found. / Use rpath

Minor hints:

  • Always use cargo's --target, else build scripts will also be sanitized.
  • Use RUSTDOCFLAGS, else doc tests will not find ASAN symbols.

Requires: tlspuffin/openssl-src-rs#2

@maxammann maxammann changed the title Fix asan linking Fix ASAN linking Apr 21, 2023
@maxammann maxammann marked this pull request as ready for review April 24, 2023 20:29
@maxammann maxammann merged commit 8cc6574 into main Apr 24, 2023
29 checks passed
@maxammann maxammann deleted the fix-asan branch April 24, 2023 20:33
maxammann added a commit to tlspuffin/openssl-src-rs that referenced this pull request Apr 24, 2023
See tlspuffin/tlspuffin#233

* Do not link against libasan

libasan is from GCC and not from LLVM. Also always use
-fsanitize=address instead of linking manually.
The -f flag makes sure that the correct symbols end up in the final
binary.

* Remove flags which do nothing (rustc link flags do not apply transitively)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant