From a2404a502be43e6c1b12881493fab2bcade145f0 Mon Sep 17 00:00:00 2001 From: Addison Crump Date: Mon, 31 Oct 2022 21:08:50 +0100 Subject: [PATCH] some work for linux --- fuzzers/jif/README.md | 5 +- fuzzers/jif/args.gn | 4 +- fuzzers/jif/chromium_patches.diff | 2 +- fuzzers/jif/libjif/src/bin/libafl_cc.rs | 43 ++++++++++----- fuzzers/jif/libjif/src/js.rs | 19 ++++--- fuzzers/jif/libjif/src/lib.rs | 73 +++++++++---------------- fuzzers/jif/libjif/src/mutators.rs | 37 ++++++------- fuzzers/jif/libjif/src/rvf.rs | 23 +++----- fuzzers/jif/make.sh | 16 +++--- 9 files changed, 107 insertions(+), 115 deletions(-) diff --git a/fuzzers/jif/README.md b/fuzzers/jif/README.md index f1597e81c5..7862f48f0b 100644 --- a/fuzzers/jif/README.md +++ b/fuzzers/jif/README.md @@ -4,7 +4,8 @@ * setup a chromium repo: https://www.chromium.org/developers/how-tos/get-the-code * note that this will take several hours -* `mv jif $root/chromium/src/headless/jif` + * you MUST use revision: fc68e53944be7 +* `mv jif $root/chromium/src/headless/jif` (or symbolic link appropriately) * `cd $root/chromium/src` * `python3 tools/mb/mb.py gen -m chromium.fuzz -b 'Libfuzzer Upload Mac ASan' out/jif` * apply patches in chromium_patches.diff @@ -16,4 +17,4 @@ * `cd $root/chromium/src/out/jif` * `./jif --cores 0-3 --broker-port 1337 --harness harness.js -i corpus -x dict -o out` -* to see arguments, run `./jif --help` \ No newline at end of file +* to see arguments, run `./jif --help` diff --git a/fuzzers/jif/args.gn b/fuzzers/jif/args.gn index e6de5c5c8f..859a3b7319 100644 --- a/fuzzers/jif/args.gn +++ b/fuzzers/jif/args.gn @@ -11,7 +11,7 @@ use_goma = false use_libfuzzer = false use_external_fuzzing_engine = true sanitizer_coverage_flags = "trace-pc-guard,trace-cmp" -clang_base_path = "/Users/jhertz/jif/chromium/src/headless/jif/libjif/llvm/" +clang_base_path = "/home/addisoncrump/Dokumente/xss-fuzzing/chromium/src/headless/jif/libjif/llvm/" clang_use_chrome_plugins = false mac_deployment_target="10.14.0" -mac_sdk_path="/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" # must be 12.3 or higher, use xcrun --show-sdk-path \ No newline at end of file +mac_sdk_path="/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" # must be 12.3 or higher, use xcrun --show-sdk-path diff --git a/fuzzers/jif/chromium_patches.diff b/fuzzers/jif/chromium_patches.diff index f525f688df..21f46ab40e 100644 --- a/fuzzers/jif/chromium_patches.diff +++ b/fuzzers/jif/chromium_patches.diff @@ -75,4 +75,4 @@ index 2a44aec23d..4ea02324d5 100644 + "//ui/gfx/geometry", + ] + libs = ["jif/libjif/target/release/libjif.a"] -+ } \ No newline at end of file ++ } diff --git a/fuzzers/jif/libjif/src/bin/libafl_cc.rs b/fuzzers/jif/libjif/src/bin/libafl_cc.rs index 63cb951315..bee11ef846 100644 --- a/fuzzers/jif/libjif/src/bin/libafl_cc.rs +++ b/fuzzers/jif/libjif/src/bin/libafl_cc.rs @@ -130,8 +130,10 @@ impl CompilerWrapper for ClangWrapper { "-c" | "-S" | "-E" => linking = false, "-shared" => { linking = false; // TODO dynamic list? - new_args.push("-undefined".into()); - new_args.push("dynamic_lookup".into()); + if cfg!(target_vendor = "apple") { + new_args.push("-undefined".into()); + new_args.push("dynamic_lookup".into()); + } } "-Wl,-z,defs" | "-Wl,--no-undefined" | "--no-undefined" => continue, _ => (), @@ -145,17 +147,28 @@ impl CompilerWrapper for ClangWrapper { if linking && suppress_linking > 0 && suppress_linking < 1337 { linking = false; println!("adding no-link-rt"); - new_args.push("-force_load".into()); - new_args.push( - PathBuf::from(OUT_DIR) - .join(format!("{}no-link-rt.{}", LIB_PREFIX, LIB_EXT)) - .into_os_string() - .into_string() - .unwrap(), - ); - - new_args.push("-undefined".into()); - new_args.push("dynamic_lookup".into()); + if cfg!(target_vendor = "apple") { + new_args.push("-force_load".into()); + new_args.push( + PathBuf::from(OUT_DIR) + .join(format!("{}no-link-rt.{}", LIB_PREFIX, LIB_EXT)) + .into_os_string() + .into_string() + .unwrap(), + ); + + new_args.push("-undefined".into()); + new_args.push("dynamic_lookup".into()); + } else { + new_args.push( + PathBuf::from(OUT_DIR) + .join(format!("{}no-link-rt.{}", LIB_PREFIX, LIB_EXT)) + .into_os_string() + .into_string() + .unwrap(), + ); + new_args.push("-lsupc++".into()); + } } self.linking = linking; @@ -250,7 +263,7 @@ impl CompilerWrapper for ClangWrapper { return Ok(args); } - if !self.passes.is_empty() { + if !self.passes.is_empty() && cfg!(target_vendor = "apple") { args.push("-fno-experimental-new-pass-manager".into()); } for pass in &self.passes { @@ -418,7 +431,7 @@ pub fn main() { .expect("Failed to parse the command line") .add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp") // TODO: write the allowlist to a file in /tmp and pass it to the compiler wrapper here - .add_arg("-fsanitize-coverage-allowlist=/Users/jhertz/jif/chromium/src/headless/jif/allowlist.txt") + .add_arg("-fsanitize-coverage-allowlist=/home/addisoncrump/Dokumente/xss-fuzzing/chromium/src/headless/jif/allowlist.txt") .add_pass(LLVMPasses::CmpLogRtn) .run() .expect("Failed to run the wrapped compiler") diff --git a/fuzzers/jif/libjif/src/js.rs b/fuzzers/jif/libjif/src/js.rs index f8c9390c0d..76a5d1bcaa 100644 --- a/fuzzers/jif/libjif/src/js.rs +++ b/fuzzers/jif/libjif/src/js.rs @@ -2,7 +2,7 @@ use libafl::bolts::tuples::Named; use libafl::events::EventFirer; use libafl::executors::ExitKind; use libafl::feedbacks::Feedback; -use libafl::inputs::Input; +use libafl::inputs::UsesInput; use libafl::observers::Observer; use libafl::observers::ObserversTuple; use libafl::state::HasClientPerfMonitor; @@ -29,8 +29,11 @@ extern "C" { fn get_js_coverage() -> *const c_char; } -impl Observer for JSObserver { - fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { +impl Observer for JSObserver +where + S: UsesInput, +{ + fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> { // we don't currently do much here? Ok(()) } @@ -38,7 +41,7 @@ impl Observer for JSObserver { fn post_exec( &mut self, _state: &mut S, - _input: &I, + _input: &S::Input, _exit_kind: &ExitKind, ) -> Result<(), Error> { unsafe { @@ -73,20 +76,20 @@ pub struct JSFeedback { name: String, } -impl Feedback +impl Feedback for JSFeedback { fn is_interesting( &mut self, state: &mut S, _manager: &mut EM, - _input: &I, + _input: &S::Input, observers: &OT, _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, - OT: ObserversTuple, + EM: EventFirer, + OT: ObserversTuple, { let observer = observers.match_name::(&self.name).unwrap(); let novel = state diff --git a/fuzzers/jif/libjif/src/lib.rs b/fuzzers/jif/libjif/src/lib.rs index b0c5354e16..c29e4a1f9f 100644 --- a/fuzzers/jif/libjif/src/lib.rs +++ b/fuzzers/jif/libjif/src/lib.rs @@ -10,10 +10,10 @@ use libafl::events::EventRestarter; use libafl::prelude::Cores; use libafl::prelude::GeneralizationStage; use libafl::prelude::GeneralizedInput; -use libafl::prelude::SkippableStage; use libafl::prelude::LlmpRestartingEventManager; -use libafl::Evaluator; +use libafl::prelude::SkippableStage; use libafl::prelude::TokenInsert; +use libafl::Evaluator; use libafl::{ bolts::{ current_nanos, @@ -135,7 +135,7 @@ struct Opt { parse(from_os_str) )] harness: PathBuf, - + #[structopt( parse(try_from_str = timeout_from_millis_str), short, @@ -181,12 +181,7 @@ struct Opt { )] bytes: bool, - #[structopt( - help = "Use tags mutator", - name = "TAGS", - long = "tags", - short = "t" - )] + #[structopt(help = "Use tags mutator", name = "TAGS", long = "tags", short = "t")] tags: bool, #[structopt( @@ -198,7 +193,6 @@ struct Opt { cmplog: bool, } - /// The main fn, `no_mangle` as it is a C symbol #[allow(clippy::too_many_lines)] #[no_mangle] @@ -233,7 +227,7 @@ pub extern "C" fn main() { let iteration_counter = RelaxedCounter::new(0); let mut run_client = |state: Option>, - mut mgr: LlmpRestartingEventManager<_, _, _, _>, + mut mgr: LlmpRestartingEventManager<_, _>, _core_id| { let repro_file = repro_file.clone(); @@ -269,9 +263,7 @@ pub extern "C" fn main() { corpdir.push("corpus"); let generalization = GeneralizationStage::new(&edges_observer); //TODO: investigate using a multimapobserver - let generalization = SkippableStage::new(generalization, |_s| { - use_grimoire.into() - }); + let generalization = SkippableStage::new(generalization, |_s| use_grimoire.into()); let mut state = match state { Some(state) => state, None => StdState::new( @@ -327,12 +319,9 @@ pub extern "C" fn main() { let calibration = CalibrationStage::new(&max_map_feedback); // Setup a randomic Input2State stage - let i2s = - SkippableStage::new( - StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))), - |_s| { - use_cmplog.into() - }, + let i2s = SkippableStage::new( + StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))), + |_s| use_cmplog.into(), ); // mutations @@ -368,27 +357,20 @@ pub extern "C" fn main() { GrimoireRandomDeleteMutator::new(), )); - let byte_mutational_stage = SkippableStage::new( StdMutationalStage::new(StdScheduledMutator::new(byte_mutations)), - |_s| { - use_bytes.into() - } + |_s| use_bytes.into(), ); let tag_mutational_stage = SkippableStage::new( StdMutationalStage::new(StdScheduledMutator::new(tag_mutations)), - |_s| { - use_tags.into() - } + |_s| use_tags.into(), ); - let grim_mutational_stage = SkippableStage::new( - StdMutationalStage::new(grimoire_mutations), - |_s| { + let grim_mutational_stage = + SkippableStage::new(StdMutationalStage::new(grimoire_mutations), |_s| { use_grimoire.into() - } - ); - + }); + // A minimization+queue policy to get testcases from the corpus let scheduler = QueueScheduler::new(); @@ -407,11 +389,10 @@ pub extern "C" fn main() { ExitKind::Ok }; - // TODO: try without timeout executor // Create the executor for an in-process function with one observer for edge coverage and one for the execution time let mut executor = TimeoutExecutor::new( - InProcessExecutor::new::, _, _>( + InProcessExecutor::new( &mut harness, tuple_list!(edges_observer, time_observer, js_observer), &mut fuzzer, @@ -433,19 +414,17 @@ pub extern "C" fn main() { ExitKind::Ok }; - // Setup a tracing stage in which we log comparisons - let tracing = SkippableStage::new(TracingStage::new(InProcessExecutor::new( - &mut harness, - tuple_list!(cmplog_observer), - &mut fuzzer, - &mut state, - &mut mgr, - )?), |_s| { - use_cmplog.into() - }); - - + let tracing = SkippableStage::new( + TracingStage::new(InProcessExecutor::new( + &mut harness, + tuple_list!(cmplog_observer), + &mut fuzzer, + &mut state, + &mut mgr, + )?), + |_s| use_cmplog.into(), + ); // The order of the stages matter! let mut stages = tuple_list!( diff --git a/fuzzers/jif/libjif/src/mutators.rs b/fuzzers/jif/libjif/src/mutators.rs index f889b57ac3..2afe47a86c 100644 --- a/fuzzers/jif/libjif/src/mutators.rs +++ b/fuzzers/jif/libjif/src/mutators.rs @@ -3,9 +3,8 @@ use libafl::{ bolts::{rands::Rand, tuples::Named}, corpus::Corpus, - inputs::{HasBytesVec, Input}, - mutators::{MutationResult, Mutator}, - prelude::Tokens, + inputs::{HasBytesVec, UsesInput}, + mutators::{MutationResult, Mutator, Tokens}, state::{HasCorpus, HasMetadata, HasRand}, Error, }; @@ -14,15 +13,15 @@ use libafl::{ #[derive(Default, Debug)] pub struct TagDeleteMutator; -impl Mutator for TagDeleteMutator +impl Mutator for TagDeleteMutator where - I: Input + HasBytesVec, - S: HasRand, + S: HasRand + UsesInput, + S::Input: HasBytesVec, { fn mutate( &mut self, state: &mut S, - input: &mut I, + input: &mut S::Input, _stage_idx: i32, ) -> Result { let size = input.bytes().len(); @@ -88,15 +87,15 @@ impl TagDeleteMutator { #[derive(Default, Debug)] pub struct TagCopyMutator; -impl Mutator for TagCopyMutator +impl Mutator for TagCopyMutator where - I: Input + HasBytesVec, - S: HasRand, + S: HasRand + UsesInput, + S::Input: HasBytesVec, { fn mutate( &mut self, state: &mut S, - input: &mut I, + input: &mut S::Input, _stage_idx: i32, ) -> Result { let size = input.bytes().len(); @@ -170,15 +169,15 @@ impl TagCopyMutator { #[derive(Default, Debug)] pub struct TagCrossoverMutator; -impl Mutator for TagCrossoverMutator +impl Mutator for TagCrossoverMutator where - I: Input + HasBytesVec, - S: HasRand + HasCorpus, + S: HasRand + HasCorpus, + S::Input: HasBytesVec, { fn mutate( &mut self, state: &mut S, - input: &mut I, + input: &mut S::Input, _stage_idx: i32, ) -> Result { let size = input.bytes().len(); @@ -281,15 +280,15 @@ impl TagCrossoverMutator { #[derive(Default, Debug)] pub struct TagTokenMutator; -impl Mutator for TagTokenMutator +impl Mutator for TagTokenMutator where - I: Input + HasBytesVec, - S: HasRand + HasCorpus + HasMetadata, + S: HasRand + HasCorpus + HasMetadata, + S::Input: HasBytesVec, { fn mutate( &mut self, state: &mut S, - input: &mut I, + input: &mut S::Input, _stage_idx: i32, ) -> Result { let size = input.bytes().len(); diff --git a/fuzzers/jif/libjif/src/rvf.rs b/fuzzers/jif/libjif/src/rvf.rs index 5f2841b53f..dcc05eaa6c 100644 --- a/fuzzers/jif/libjif/src/rvf.rs +++ b/fuzzers/jif/libjif/src/rvf.rs @@ -1,34 +1,29 @@ -use libafl::prelude::EventFirer; -use libafl::prelude::ExitKind; -use libafl::prelude::Feedback; -use libafl::prelude::HasClientPerfMonitor; -use libafl::prelude::Input; -use libafl::prelude::Named; -use libafl::prelude::ObserversTuple; -use libafl::Error; +use libafl::{ + bolts::tuples::Named, events::EventFirer, executors::ExitKind, feedbacks::Feedback, + inputs::UsesInput, observers::ObserversTuple, state::HasClientPerfMonitor, Error, +}; use serde::{Deserialize, Serialize}; /// A [`ReturnValueFeedback`] reports as interesting if `LLVMTestOneInput == 42` #[derive(Serialize, Deserialize, Clone, Debug)] pub struct ReturnValueFeedback {} -impl Feedback for ReturnValueFeedback +impl Feedback for ReturnValueFeedback where - I: Input, - S: HasClientPerfMonitor, + S: HasClientPerfMonitor + UsesInput, { #[allow(clippy::wrong_self_convention)] fn is_interesting( &mut self, _state: &mut S, _manager: &mut EM, - _input: &I, + _input: &S::Input, _observers: &OT, exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, - OT: ObserversTuple, + EM: EventFirer, + OT: ObserversTuple, { if let ExitKind::Oom = exit_kind { //HACK: we need to add a new ExitKind for XSS diff --git a/fuzzers/jif/make.sh b/fuzzers/jif/make.sh index 52d2048fcd..d7c5c14a27 100755 --- a/fuzzers/jif/make.sh +++ b/fuzzers/jif/make.sh @@ -6,7 +6,7 @@ export LIBAFL_EDGES_MAP_SIZE=3000000 CLANG_FOLDER=`llvm-config --bindir` -pushd libjif +cd libjif cargo build --release echo "[+] Setting up libAFL LLVM environment" @@ -19,11 +19,13 @@ if [ ! -d "llvm" ]; then fi # copy the libafl cc's in place to build chrome -cp target/release/libafl_cc llvm/bin/clang -cp target/release/libafl_cxx llvm/bin/clang++ -popd -# build jif -ninja -v -C ../../out/jif jif - +rm -v llvm/bin/clang{,++} +cp -v target/release/libafl_cc llvm/bin/clang +cp -v target/release/libafl_cxx llvm/bin/clang++ +cd - +# allow for symlinks +outdir="$(dirname "$(dirname "$PWD")")"/out/jif +# build jif +ninja -v -C "$outdir" jif