libfuzzer_libmozjpeg readme

This commit is contained in:
Andrea Fioraldi 2021-03-29 16:07:56 +02:00
parent 144d9dff9d
commit bd9aa89753
2 changed files with 26 additions and 16 deletions

View File

@ -1,16 +1,32 @@
# Libfuzzer for libmozjpeg # Libfuzzer for libmozjpeg
This folder contains an example fuzzer for libmozjpeg, using LLMP for fast multi-process fuzzing and crash detection. This folder contains an example fuzzer for libmozjpeg, using LLMP for fast multi-process fuzzing and crash detection.
Alongside the traditional edge coverage, this example shows how to use a value-profile like feedback to bypass CMPs and an allocations size maximization feedback to spot patological inputs in terms of memory usage.
It has been tested on Linux. It has been tested on Linux.
https://github.com/mozilla/mozjpeg/archive/v4.0.3.tar.gz
## Build ## Build
To build this example, run `cargo build --example libfuzzer_libmozjpeg --release`. To build this example, run `cargo build --release`.
This will call (the build.rs)[./builld.rs], which in turn downloads a libmozjpeg archive from the web. This will build the library with the fuzzer (src/lib.rs) with the libfuzzer compatibility layer. the SanitizerCoverage runtime functions for edges and value-profile feedbacks and the `hook_allocs.c` C file that hooks the allocator to report the size to the fuzzer.
Then, it will link (the fuzzer)[./src/fuzzer.rs] against (the c++ harness)[./harness.cc] and the instrumented `libmozjpeg`. In addition, it will build also two C and C++ compiler wrappers (bin/c(c/xx).rs) that you must use to compile the target.
Afterwards, the fuzzer will be ready to run, from `../../target/examples/libfuzzer_libmozjpeg`.
Then download the mozjpeg source tarball from https://github.com/mozilla/mozjpeg/archive/v4.0.3.tar.gz and unpack the archive.
Now compile it with:
```
cd mozjpeg-4.0.3
cmake --disable-shared . -DCMAKE_C_COMPILER=/path/to/libfuzzer_mozjpeg/target/release/cc -DCMAKE_CXX_COMPILER=/path/to/libfuzzer_mozjpeg/target/release/cxx -G "Unix Makefiles"
make -j `nproc`
```
Now, we have to build the libfuzzer harness and link all togheter to create our fuzzer binary.
```
/path/to/libfuzzer_libpng/target/debug/cxx /path/to/libfuzzer_libpng/harness.cc mozjpeg-4.0.3/*.a -I mozjpeg-4.0.3/ -o fuzzer
```
Afterwards, the fuzzer will be ready to run simply executing `./fuzzer`.
## Run ## Run
@ -21,10 +37,4 @@ As this example uses in-process fuzzing, we added a Restarting Event Manager (`s
This means each client will start itself again to listen for crashes and timeouts. This means each client will start itself again to listen for crashes and timeouts.
By restarting the actual fuzzer, it can recover from these exit conditions. By restarting the actual fuzzer, it can recover from these exit conditions.
For convenience, you may just run `./test.sh` in this folder or: In any real-world scenario, you should use `taskset` to pin each client to an empty CPU core, the lib does not pick an empty core automatically (yet).
broker.sh - starts the broker
start.sh - starts as many clients as there are cores
stop.sh - stop everything

View File

@ -6,8 +6,8 @@ use std::path::Path;
fn main() { fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap(); let out_dir = env::var_os("OUT_DIR").unwrap();
let out_dir = out_dir.to_string_lossy().to_string(); let out_dir = out_dir.to_string_lossy().to_string();
let src_dir = Path::new("src");
//let out_dir_path = Path::new(&out_dir); //let out_dir_path = Path::new(&out_dir);
let _src_dir = Path::new("src");
//std::env::set_var("CC", "clang"); //std::env::set_var("CC", "clang");
//std::env::set_var("CXX", "clang++"); //std::env::set_var("CXX", "clang++");
@ -17,7 +17,7 @@ fn main() {
println!("cargo:rerun-if-changed=src/libfuzzer_compatibility.c"); println!("cargo:rerun-if-changed=src/libfuzzer_compatibility.c");
cc::Build::new() cc::Build::new()
.file(src_dir.join("libfuzzer_compatibility.c")) .file(_src_dir.join("libfuzzer_compatibility.c"))
.compile("libfuzzer_compatibility"); .compile("libfuzzer_compatibility");
} }
@ -26,7 +26,7 @@ fn main() {
println!("cargo:rerun-if-changed=src/value_profile.c"); println!("cargo:rerun-if-changed=src/value_profile.c");
cc::Build::new() cc::Build::new()
.file(src_dir.join("value_profile.c")) .file(_src_dir.join("value_profile.c"))
.compile("value_profile"); .compile("value_profile");
} }