AngoraFuzzer / Angora

Angora is a mutation-based fuzzer. The main goal of Angora is to increase branch coverage by solving path constraints without symbolic execution.
Apache License 2.0
917 stars 166 forks source link

Sport for fuzzing rust code #10

Open Eh2406 opened 5 years ago

Eh2406 commented 5 years ago

Many people in the rust community are excited to see this project! Both because it is in Rust, and because we want to use it on Rust projects.

Is there any information on how to use it on Rust projects?

spinpx commented 5 years ago

It's an interesting topic. As Shnatsel mentioned, the LLVM pass needs to support Rust's LLVM version. However, since Rust has many built-in libraries, modeling the built-in or external libraries used in rust for taint analysis will be the challenge.

TheBlueMatt commented 5 years ago

At least to get things bootstrapped, ie without instrumenting rust's built-in libraries, it looks like building against system rustc/LLVM is pretty easy.

rustc appears to dynamically load LLVM/its LLVM codegen lib at runtime you can't just LD_PRELOAD angora-llvm-pass cause it wont be able to find LLVM hooks at load. This is just that llvm_mode/Makefile to include $(LLVM_CONFIG) --libs in the flags for angora-llvm-pass so that libLLVM gets loaded at start. I think this should be done upstream, so will open a PR in a sec.

Once you do that, you can just something that looks like LD_PRELOAD="/path/to/angora-llvm-pass.so /path/to/unfold-branch-pass.so" RUSTFLAGS="-C passes=unfold_branch_pass,angora_llvm_pass" cargo build.

For me this results in ICEs that look like this, I presume because I'm using LLVM 7, which is unsupported: Incorrect number of arguments passed to called function! %71 = call i32 @__angora_trace_cmp(i32 %69, i32 1374339812, i64 %70, i64 1), !dbg !232, !nosanitize !56

TheBlueMatt commented 5 years ago

Note that this is, of course, a little bit awkward, because building Angora requires a nightly rust (ie installed via rustup) and then you have to switch to system-installed rust (ie uninstall rustup/remove it from your PATH) to actually build things with the angora pass. It looks like Angora's nightly-requirement is just for nll (so we can switch to edition-2018 and stable there) and C-linked thread-locals (which I'm worried isn't well-defined anyway, would it be too much of a perf hit to take a function-call into a native-built C wrapper to read these?).

TheBlueMatt commented 5 years ago

I'm also very confused (and know nothing about LLVM) because the #[thread_local] variables in shm_conds don't appear to be defined as thread-locals in angora-llvm-pass.so.cc (the second-to-last arg is 0, which in LLVM's GlobalValue.h appears to be:

enum ThreadLocalMode {
  NotThreadLocal = 0,

)

spinpx commented 5 years ago

Hi, @TheBlueMatt . Thanks for your contribution. I merged your pull request on rust-stable branch. I haven't tried Angora in LLVM 7. I will put the support for LLVM 7 in my plan.

For the thread local issues, I defined angora_prev_loc, angora_context in angora-llvm-pass.so.cc as:

  AngoraPrevLoc =
      new GlobalVariable(M, Int32Ty, false, GlobalValue::CommonLinkage,
                         ConstantInt::get(Int32Ty, 0), "__angora_prev_loc", 0,
                         GlobalVariable::GeneralDynamicTLSModel, 0, false);
  AngoraContext =
      new GlobalVariable(M, Int32Ty, false, GlobalValue::CommonLinkage,
                         ConstantInt::get(Int32Ty, 0), "__angora_context", 0,
                         GlobalVariable::GeneralDynamicTLSModel, 0, false);

And the LLVM API is

GlobalVariable (Module &M, Type *Ty, bool isConstant, LinkageTypes Linkage, 
Constant *Initializer, const Twine &Name="", GlobalVariable *InsertBefore=nullptr, 
ThreadLocalMode=NotThreadLocal, unsigned AddressSpace=0, 
bool isExternallyInitialized=false)

"The the second-to-last arg is 0" is for "AddreessSpace". And I implemented the "native-built C wrapper" approach for thread local in the rust-statble branch.

TheBlueMatt commented 5 years ago

Ah, looks like the constructor parameters have changed in newer llvms. That would imply the "stable-rust" branch won't work/link, though I haven't gotten that far in getting rust to build with the LLVM pass to test.

As for the bad function call, it may be some other pass rustc does that removes the function or mangles it. When I try to run the pass and export llvm-ir I get a segfault when it tries to write out the result, I'm guessing because it tries to dereference a lookup of the function which failed to find it but Debian doesn't appear to ship debug symbols for llvm anymore so I can't confirm.

I also need to remove the RegisterStandardPass calls as they cause segfaults on load in rustc.

On Jan 1, 2019, at 21:36, sp1npx notifications@github.com wrote:

Hi, @TheBlueMatt . Thanks for your contribution. I will merge your pull request soon. I haven't tried Angora in LLVM 7. I will put the support for LLVM 7 in my plan. For the thread local issues, I defined angora_prev_loc, angora_context in angora-llvm-pass.so.cc as:

AngoraPrevLoc = new GlobalVariable(M, Int32Ty, false, GlobalValue::CommonLinkage, ConstantInt::get(Int32Ty, 0), "angora_prev_loc", 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); AngoraContext = new GlobalVariable(M, Int32Ty, false, GlobalValue::CommonLinkage, ConstantInt::get(Int32Ty, 0), "angora_context", 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); And the LLVM API is

GlobalVariable (Module &M, Type Ty, bool isConstant, LinkageTypes Linkage, Constant Initializer, const Twine &Name="", GlobalVariable *InsertBefore=nullptr, ThreadLocalMode=NotThreadLocal, unsigned AddressSpace=0, bool isExternallyInitialized=false) "The the second-to-last arg is 0" is for "AddreessSpace".

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

spinpx commented 5 years ago

Thanks @bpfoley, we have an llvm6 branch now. https://github.com/AngoraFuzzer/Angora/tree/llvm6 https://github.com/AngoraFuzzer/Angora/pull/24

I created llvm7 branch here: https://github.com/AngoraFuzzer/Angora/tree/llvm7

https://github.com/AngoraFuzzer/Angora/pull/24#issuecomment-453035998 mentioned the compiling issues that I still have not solved.

dragostis commented 5 years ago

@spinpx, what is the state of this? Is there any way I can help move this forward?

TheBlueMatt commented 5 years ago

@dragostis the next steps are probably to retrace the steps I took, above, using the llvm6/7 branch and see how far you can get. Note that you'll have to use system-LLVM (and a rustc built against that, eg use debian packages, not rustup, as afaict rustup doesn't ship the necessary bits of LLVM to build against).

spinpx commented 5 years ago

We have implemented the new feature for supporting libdft64 here. https://github.com/AngoraFuzzer/Angora/blob/master/docs/pin_mode.md

Since it uses Intel Pin to do track analysis, we needn't compiling whole program now.