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

fuzz_mutator seems to not work with stripping dead code by default #396

Open
0xalpharush opened this issue Feb 7, 2025 · 3 comments
Open

Comments

@0xalpharush
Copy link
Contributor

0xalpharush commented Feb 7, 2025

Using the package from crates prior to #394:

$ cargo fuzz --version
cargo-fuzz 0.12.0
$ git clone [email protected]:rust-fuzz/libfuzzer.git && cd libfuzzer/example_mutator
$ cargo fuzz run boom  
...
thread '<unnamed>' panicked at
...

If I install from git cargo install --git https://github.com/rust-fuzz/cargo-fuzz, it not longer panics nearly instantly (finds an input that is prefixed with "boom"). I suspect this is because fuzz_mutator is stripped due to #394. That said, I did notice stripping dead code fixed errors llvm-cov produced when I was trying to generating coverage reports.

More info:
If I compile the example in a standalone project without cargo-fuzz, I can reproduce the behavior more clearly.

$ cargo new example_mutator && cargo add flate2 libfuzzer-sys && mv ~/libfuzzer/example_mutator/fuzz_targets/boom.rs ~/example_mutator/main.rs
$ cargo +nightly rustc -- \                                      
    -C passes='sancov-module' \
    -C llvm-args='-sanitizer-coverage-level=4' \
    -C llvm-args='-sanitizer-coverage-inline-8bit-counters' \
    -C link-dead-code

Next, add a panic!(); to fuzz_mutator! and run ./target/debug/example_mutator. I get a crash at the inserted panic.

If I remove -C link-dead-code, the panic isn't reached.

@saethlin
Copy link
Contributor

I can't reproduce this. What target are you compiling for? What linker are you using?

@0xalpharush
Copy link
Contributor Author

rustc: 1.84.0-aarch64-apple-darwin

I'm not sure how to check what rustc is invoking for linking

@saethlin
Copy link
Contributor

saethlin commented Feb 18, 2025

I was trying to repro on Linux. Easy repro on a Mac laptop.

I think the problem is that the custom mutator system relies on exporting symbols from executables, which is the (stalled) flag -Zexport-executable-symbols: https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/export-executable-symbols.html
rust-lang/rust#84161

-Clink-dead-code is one way to paper over this.

This problem only happens on Apple targets because libfuzzer uses a different mechanism to load these functions on Apple targets. On linux/bsd, libfuzzer uses weak symbols and says this is the reason it doesn't use them on Apple:
https://github.com/rust-fuzz/libfuzzer/blob/4b077c206e8c256eca681678acd1e21f03e19fb6/libfuzzer/FuzzerExtFunctionsWeak.cpp#L8-L12

// Implementation for Linux. This relies on the linker's support for weak
// symbols. We don't use this approach on Apple platforms because it requires
// clients of LibFuzzer to pass ``-U _<symbol_name>`` to the linker to allow
// weak symbols to be undefined. That is a complication we don't want to expose
// to clients right now.

I'm not sure I agree that some -U flags are less complicated. Perhaps there's a compatibility issue as they add/remove weak symbols?

If you enable the weak symbol strategy on Apple, here's how you'd build a simple mutator fuzzer:

cargo +nightly rustc -- \
  -Cpasses=sancov-module \
  -Cllvm-args=-sanitizer-coverage-level=4 \
  -Cllvm-args=-sanitizer-coverage-inline-8bit-counters \
  -Clink-arg="-Wl,-U,_LLVMFuzzerCustomCrossOver" \
  -Clink-arg="-Wl,-U,___lsan_disable" \
  -Clink-arg="-Wl,-U,___lsan_do_recoverable_leak_check" \
  -Clink-arg="-Wl,-U,___lsan_enable" \
  -Clink-arg="-Wl,-U,___msan_scoped_disable_interceptor_checks" \
  -Clink-arg="-Wl,-U,___msan_scoped_enable_interceptor_checks" \
  -Clink-arg="-Wl,-U,___msan_unpoison" \
  -Clink-arg="-Wl,-U,___msan_unpoison_param" \
  -Clink-arg="-Wl,-U,___sanitizer_acquire_crash_state" \
  -Clink-arg="-Wl,-U,___sanitizer_get_module_and_offset_for_pc" \
  -Clink-arg="-Wl,-U,___sanitizer_install_malloc_and_free_hooks" \
  -Clink-arg="-Wl,-U,___sanitizer_log_write" \
  -Clink-arg="-Wl,-U,___sanitizer_print_memory_profile" \
  -Clink-arg="-Wl,-U,___sanitizer_print_stack_trace" \
  -Clink-arg="-Wl,-U,___sanitizer_set_death_callback" \
  -Clink-arg="-Wl,-U,___sanitizer_set_report_fd" \
  -Clink-arg="-Wl,-U,___sanitizer_symbolize_pc" \
  -Clink-arg="-Wl,-U,___sanitizer_purge_allocator"

Inglorious, but I can confirm it works.

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

No branches or pull requests

2 participants