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

Document how to symbolicate fuzzer stack traces #24

Open
MatejKastak opened this issue May 31, 2021 · 5 comments
Open

Document how to symbolicate fuzzer stack traces #24

MatejKastak opened this issue May 31, 2021 · 5 comments

Comments

@MatejKastak
Copy link

Hi, first of all cargo-fuzz is awesome 👍.

I have been playing a little with it. And I found out that resolving memory leaks is not as easy as I thought.

An example:
before

Searching online for the documentation, I wasn't able to find what this trace means and how to correlate it with the original source code. Not even in LLVM sanitizer docs. After some playing with objdump I found a manually intensive way of retrieving the information one by one.

To simplify this, I have created a PoC tool in Python to do this automatically.
after

It is located at https://github.com/MatejKastak/cargo-fuzz-sourcer if anyone is interested.

The question ❓

  • What do you think the right way to correlate leaks with the code is?
  • Is this approach using objdump reasonable?
  • Is this project interested in adopting functionality like this? I can help with it.
  • Should we extend the documentation?

I hope I am not missing something obvious and reinventing the wheel.

@fitzgen
Copy link
Member

fitzgen commented Jun 1, 2021

Those stacks are the stack at the time that the leaked memory was allocated.

There are some build configurations where you can see symbolicated stack traces instead of just addresses. This makes the information much more actionable and easier to process without using objdump by hand. Unfortunately, I don't remember what the build flags for this config is. It is worth trying non-optimized builds and seeing if that has any affect, as well as using RUSTFLAGS=-g and maybe even CFLAGS=-g. Not totally sure here.

Yes, we should definitely document this once we figure it out.

I don't think we want to adopt a post-processing tool into this repo / tool. IME, post-processing tools, especially of ad-hoc/human readable formats rather than something like JSON, are a pain to maintain across upstream upgrades.

@fitzgen
Copy link
Member

fitzgen commented Jun 1, 2021

https://clang.llvm.org/docs/AddressSanitizer.html#symbolizing-the-reports seems relevant.

Unfortunately, it looks like the llvm-tools rustup component doesn't contain llvm-symbolize, so we can't just recommend rustup component add llvm-tools-preview as a one-size-fits-all solution for users.

@fitzgen
Copy link
Member

fitzgen commented Jun 1, 2021

I had llvm-symbolizer-11 on my $PATH, but not llvm-symbolizer. So I did this:

$ sudo ln -s $(which llvm-symbolizer-11) $(dirname $(which llvm-symbolizer-11))/llvm-symbolizer 

and after that, I get properly symbolicated stack traces for your example leak:

==292699==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 40 byte(s) in 1 object(s) allocated from:
    #0 0x55e43d4529ed in malloc /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
    rust-fuzz/cargo-fuzz#1 0x55e43d4dcf68 in leak::leak::hdae5dce9ea1bcf19 (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0x132f68)
    rust-fuzz/cargo-fuzz#2 0x55e43d4dd3f5 in leak::eval::h12e51d43de723d01 (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0x1333f5)
    rust-fuzz/cargo-fuzz#3 0x55e43d489187 in rust_fuzzer_test_input (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xdf187)
    rust-fuzz/cargo-fuzz#4 0x55e43d48d9e0 in __rust_try (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xe39e0)
    rust-fuzz/cargo-fuzz#5 0x55e43d48d16f in LLVMFuzzerTestOneInput (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xe316f)
    rust-fuzz/cargo-fuzz#6 0x55e43d494208 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xea208)
    rust-fuzz/cargo-fuzz#7 0x55e43d4998a3 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xef8a3)
    rust-fuzz/cargo-fuzz#8 0x55e43d49a684 in fuzzer::Fuzzer::MutateAndTestOne() (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xf0684)
    rust-fuzz/cargo-fuzz#9 0x55e43d49c847 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xf2847)
    rust-fuzz/cargo-fuzz#10 0x55e43d4befcf in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0x114fcf)
    rust-fuzz/cargo-fuzz#11 0x55e43d3d6de6 in main (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0x2cde6)
    rust-fuzz/cargo-fuzz#12 0x7ff54fbdacb1 in __libc_start_main csu/../csu/libc-start.c:314:16

Indirect leak of 12 byte(s) in 1 object(s) allocated from:
    #0 0x55e43d4529ed in malloc /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
    rust-fuzz/cargo-fuzz#1 0x55e43d4dd023 in leak::leak::hdae5dce9ea1bcf19 (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0x133023)
    rust-fuzz/cargo-fuzz#2 0x55e43d4dd3f5 in leak::eval::h12e51d43de723d01 (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0x1333f5)
    rust-fuzz/cargo-fuzz#3 0x55e43d489187 in rust_fuzzer_test_input (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xdf187)
    rust-fuzz/cargo-fuzz#4 0x55e43d48d9e0 in __rust_try (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xe39e0)
    rust-fuzz/cargo-fuzz#5 0x55e43d48d16f in LLVMFuzzerTestOneInput (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xe316f)
    rust-fuzz/cargo-fuzz#6 0x55e43d494208 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xea208)
    rust-fuzz/cargo-fuzz#7 0x55e43d4998a3 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xef8a3)
    rust-fuzz/cargo-fuzz#8 0x55e43d49a684 in fuzzer::Fuzzer::MutateAndTestOne() (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xf0684)
    rust-fuzz/cargo-fuzz#9 0x55e43d49c847 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0xf2847)
    rust-fuzz/cargo-fuzz#10 0x55e43d4befcf in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0x114fcf)
    rust-fuzz/cargo-fuzz#11 0x55e43d3d6de6 in main (/home/nick/scratch/cargo-fuzz-sourcer/leak/fuzz/target/x86_64-unknown-linux-gnu/release/eval+0x2cde6)
    rust-fuzz/cargo-fuzz#12 0x7ff54fbdacb1 in __libc_start_main csu/../csu/libc-start.c:314:16

SUMMARY: AddressSanitizer: 52 byte(s) leaked in 2 allocation(s).
INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.

@MatejKastak
Copy link
Author

Thanks for your research!

I was able to replicate this using llvm-symbolizer. I had no idea such tool existed. Also interesting note is that it accepts command line arguments in LLVM_SYMBOLIZER_OPTS env variable. However, an option like --pretty-print, -p is crashing on me.

Feel free to close this question.

@fitzgen
Copy link
Member

fitzgen commented Jun 9, 2021

I think we should keep this open to track documenting this stuff. I'll also move it to the book repo's issue tracker.

@fitzgen fitzgen transferred this issue from rust-fuzz/cargo-fuzz Jun 9, 2021
@fitzgen fitzgen changed the title [Question] How to resolve memory leaks? Document how to symbolicate fuzzer stack traces Jun 9, 2021
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