diff --git a/fuzzers/wcet_qemu_sys/src/fuzzer.rs b/fuzzers/wcet_qemu_sys/src/fuzzer.rs index f175e02894..9e89c3535a 100644 --- a/fuzzers/wcet_qemu_sys/src/fuzzer.rs +++ b/fuzzers/wcet_qemu_sys/src/fuzzer.rs @@ -1,5 +1,6 @@ //! A singlethreaded QEMU fuzzer that can auto-restart. +use libafl_qemu::QemuClockObserver; use libafl::feedbacks::Feedback; use crate::worst::HitImprovingFeedback; use crate::worst::HitFeedback; @@ -152,7 +153,7 @@ pub fn main() { } } let mut crashes = out_dir.clone(); - crashes.push("crashes"); + crashes.push("wcets"); out_dir.push("queue"); let in_dir = PathBuf::from(res.value_of("in").unwrap().to_string()); @@ -292,6 +293,7 @@ fn fuzz( // Create an observation channel to keep track of the execution time let time_observer = TimeObserver::new("time"); + let clock_observer = QemuClockObserver::default(); // Create an observation channel using cmplog map let cmplog_observer = CmpLogObserver::new("cmplog", unsafe { &mut cmplog::CMPLOG_MAP }, true); @@ -387,7 +389,7 @@ fn fuzz( //QemuAsanHelper::new(), QemuSysSnapshotHelper::new() ), - tuple_list!(edges_observer, time_observer), + tuple_list!(edges_observer, time_observer, clock_observer), &mut fuzzer, &mut state, &mut mgr, diff --git a/fuzzers/wcet_qemu_sys/src/main.rs b/fuzzers/wcet_qemu_sys/src/main.rs index cca2809009..6b319d5ac9 100644 --- a/fuzzers/wcet_qemu_sys/src/main.rs +++ b/fuzzers/wcet_qemu_sys/src/main.rs @@ -1,3 +1,4 @@ +#![feature(iter_advance_by)] #[cfg(target_os = "linux")] pub mod fuzzer; pub mod showmap; diff --git a/fuzzers/wcet_qemu_sys/src/showmap.rs b/fuzzers/wcet_qemu_sys/src/showmap.rs index 06ed342c7d..22535170c7 100644 --- a/fuzzers/wcet_qemu_sys/src/showmap.rs +++ b/fuzzers/wcet_qemu_sys/src/showmap.rs @@ -1,5 +1,12 @@ //! A singlethreaded QEMU fuzzer that can auto-restart. +use crate::worst::DumpMapFeedback; +use crate::worst::DummyFeedback; +use libafl::corpus::Corpus; +use libafl::state::HasCorpus; +use libafl::Fuzzer; +use libafl::mutators::BitFlipMutator; +use libafl::stages::StdMutationalStage; use libafl_qemu::QemuInstrumentationFilter; use crate::system_trace::QemuSystemStateHelper; use libafl::feedbacks::CrashFeedback; @@ -258,7 +265,7 @@ fn fuzz( let feedback = DumpMapFeedback::with_dump(dump_edges); // A feedback to choose if an input is a solution or not - let objective = QemuClockIncreaseFeedback::new(); + let objective = DummyFeedback::new(false); // create a State from scratch let mut state = StdState::new( @@ -330,67 +337,28 @@ fn fuzz( true => seed_dir.clone().read_dir().expect("Directory not a directory?").next().expect("Directory empty?").expect("File not in directory?").path(), false => seed_dir.clone() }; + // let secondinput = match seed_dir.clone().is_dir() { + // true => { + // let mut a = seed_dir.clone().read_dir().expect("Directory not a directory?"); + // a.advance_by(1); + // a.next().unwrap().expect("File not in directory?").path() + // }, + // false => seed_dir.clone() + // }; fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, Input::from_file(&firstinput).expect("Could not load file")).expect("Evaluation failed"); + // fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, Input::from_file(&secondinput).expect("Could not load file")).expect("Evaluation failed"); + // println!("Nach Eval"); + // if state.corpus().count() < 1 { + // state + // .load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()]) + // .unwrap_or_else(|_| { + // println!("Failed to load initial corpus at {:?}", &seed_dir); + // return; + // }); + // println!("We imported {} inputs from disk.", state.corpus().count()); + // } + // fuzzer + // .fuzz_one(&mut tuple_list!(StdMutationalStage::new(BitFlipMutator::new())), &mut executor, &mut state, &mut mgr) + // .expect("Error in the fuzzing loop"); return Ok(()); } - -//=========================== Debugging Feedback -/// A [`Feedback`] meant to dump the edgemap for debugging. -#[derive(Debug)] -pub struct DumpMapFeedback { - dumpfile: Option -} - -impl Feedback for DumpMapFeedback -where - I: Input, - S: HasClientPerfMonitor, -{ - fn is_interesting( - &mut self, - _state: &mut S, - _manager: &mut EM, - _input: &I, - _observers: &OT, - _exit_kind: &ExitKind, - ) -> Result - where - EM: EventFirer, - OT: ObserversTuple, - { - let observer = _observers.match_name::>>("edges") - .expect("HitcountsMapObserver not found"); - match &self.dumpfile { - Some(s) => { - fs::write(s,ron::to_string(&observer.edgemap).expect("Error serializing hashmap")).expect("Can not dump to file"); - self.dumpfile = None - }, - None => println!("{:#?}",observer.edgemap), - }; - Ok(true) - } -} - -impl Named for DumpMapFeedback { - #[inline] - fn name(&self) -> &str { - "HitFeedback" - } -} - -impl DumpMapFeedback { - /// Creates a new [`HitFeedback`] - #[must_use] - pub fn new() -> Self { - Self {dumpfile: None} - } - pub fn with_dump(dumpfile: Option) -> Self { - Self {dumpfile: dumpfile} - } -} - -impl Default for DumpMapFeedback { - fn default() -> Self { - Self::new() - } -} \ No newline at end of file diff --git a/fuzzers/wcet_qemu_sys/src/worst.rs b/fuzzers/wcet_qemu_sys/src/worst.rs index 1982b7bbab..16ec309e3e 100644 --- a/fuzzers/wcet_qemu_sys/src/worst.rs +++ b/fuzzers/wcet_qemu_sys/src/worst.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; +use std::fs; use libafl::observers::VariableMapObserver; use hashbrown::{HashMap}; use libafl::observers::ObserversTuple; @@ -182,7 +184,8 @@ where } } let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64); - let hit_target = mean_sum_of_squares <= 1.0; + let hit_target = mean_sum_of_squares <= self.target_msd; + eprintln!("hit target: {} {} {:?}",hit_target,mean_sum_of_squares, _input); if hit_target { Ok(true) } else { @@ -312,7 +315,7 @@ where } let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64); let hit_target = mean_sum_of_squares <= self.best_msd; - eprintln!("in worst, {}",hit_target); + eprintln!("improving: {}",hit_target); if hit_target { self.best_msd = mean_sum_of_squares; Ok(true) @@ -341,4 +344,115 @@ impl Default for HitImprovingFeedback { fn default() -> Self { Self::new(HashMap::new()) } +} + +//=========================== Debugging Feedback +/// A [`Feedback`] meant to dump the edgemap for debugging. +#[derive(Debug)] +pub struct DumpMapFeedback { + dumpfile: Option +} + +impl Feedback for DumpMapFeedback +where + I: Input, + S: HasClientPerfMonitor, +{ + fn is_interesting( + &mut self, + _state: &mut S, + _manager: &mut EM, + _input: &I, + _observers: &OT, + _exit_kind: &ExitKind, + ) -> Result + where + EM: EventFirer, + OT: ObserversTuple, + { + let observer = _observers.match_name::>>("edges") + .expect("HitcountsMapObserver not found"); + match &self.dumpfile { + Some(s) => { + fs::write(s,ron::to_string(&observer.edgemap).expect("Error serializing hashmap")).expect("Can not dump to file"); + self.dumpfile = None + }, + None => ()//println!("{:#?}",observer.edgemap), + }; + Ok(true) + } +} + +impl Named for DumpMapFeedback { + #[inline] + fn name(&self) -> &str { + "HitFeedback" + } +} + +impl DumpMapFeedback { + /// Creates a new [`HitFeedback`] + #[must_use] + pub fn new() -> Self { + Self {dumpfile: None} + } + pub fn with_dump(dumpfile: Option) -> Self { + Self {dumpfile: dumpfile} + } +} + +impl Default for DumpMapFeedback { + fn default() -> Self { + Self::new() + } +} + +//=========================== Debugging Feedback +/// A [`Feedback`] meant to dump the edgemap for debugging. +#[derive(Debug)] +pub struct DummyFeedback { + response: bool +} + +impl Feedback for DummyFeedback +where + I: Input, + S: HasClientPerfMonitor, +{ + fn is_interesting( + &mut self, + _state: &mut S, + _manager: &mut EM, + _input: &I, + _observers: &OT, + _exit_kind: &ExitKind, + ) -> Result + where + EM: EventFirer, + OT: ObserversTuple, + { + eprintln!("Input was: {:?}",_input); + Ok(self.response) + } +} + +impl Named for DummyFeedback { + #[inline] + fn name(&self) -> &str { + "DummyFeedback" + } +} + +impl DummyFeedback { + /// Creates a new [`HitFeedback`] + #[must_use] + pub fn new(response: bool) -> Self { + Self {response: response} + } +} + +impl Default for DummyFeedback { + fn default() -> Self { + Self::new(true) + } } \ No newline at end of file diff --git a/libafl_qemu/src/clock.rs b/libafl_qemu/src/clock.rs index 66a316f1e9..04c669afb6 100644 --- a/libafl_qemu/src/clock.rs +++ b/libafl_qemu/src/clock.rs @@ -28,6 +28,16 @@ use libafl::events::EventFirer; use libafl::state::HasClientPerfMonitor; use libafl::inputs::Input; use libafl::feedbacks::Feedback; +use libafl::SerdeAny; +use libafl::state::HasMetadata; +use libafl::corpus::testcase::Testcase; + +//========== Metadata +#[derive(Debug, Serialize, Deserialize, SerdeAny)] +pub struct QemuIcountMetadata { + runtime: i64, +} +// libafl::impl_serdeany!(QemuIcountMetadata); //========== Observer @@ -55,7 +65,11 @@ impl QemuClockObserver { } } -impl Observer for QemuClockObserver { +impl Observer for QemuClockObserver +where + I: Input, + S: HasMetadata, +{ fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { self.last_runtime=0; Ok(()) @@ -63,6 +77,12 @@ impl Observer for QemuClockObserver { fn post_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { unsafe { self.last_runtime = emu::libafl_get_clock() }; + // if !_state.has_metadata::() { + // _state.add_metadata(QemuIcountMetadata{runtime: self.last_runtime()}); + // println!("Added Metadata"); + // } else { + // println!("Found Metadata"); + // } println!("Observer Clock: {}",self.last_runtime()); Ok(()) } @@ -84,12 +104,13 @@ impl Default for QemuClockObserver { } } -//========== Observer +//========== Feedback /// A [`Feedback`] rewarding increasing the execution cycles on Qemu. #[derive(Debug)] pub struct QemuClockIncreaseFeedback { - maximum: i64 + maximum: i64, + last_runtime: i64, } impl Feedback for QemuClockIncreaseFeedback @@ -111,12 +132,26 @@ where { let observer = _observers.match_name::("clock") .expect("QemuClockObserver not found"); - if observer.last_runtime() >= self.maximum { + if observer.last_runtime() > self.maximum { self.maximum = observer.last_runtime(); return Ok(true); } Ok(false) } + + /// Append to the testcase the generated metadata in case of a new corpus item + #[inline] + fn append_metadata(&mut self, _state: &mut S, testcase: &mut Testcase) -> Result<(), Error> { + testcase.metadata_mut().insert(QemuIcountMetadata{runtime: self.last_runtime}); + Ok(()) + } + + /// Discard the stored metadata in case that the testcase is not added to the corpus + #[inline] + fn discard_metadata(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { + Ok(()) + } + } impl Named for QemuClockIncreaseFeedback { @@ -130,7 +165,7 @@ impl QemuClockIncreaseFeedback { /// Creates a new [`HitFeedback`] #[must_use] pub fn new() -> Self { - Self {maximum: 0} + Self {maximum: 0, last_runtime: 0} } }