From ee4056a008c14f90511de423f763e73c0a7affa2 Mon Sep 17 00:00:00 2001 From: Alwin Berger Date: Fri, 27 May 2022 01:10:12 +0200 Subject: [PATCH] add objective selection, dump exec times --- fuzzers/wcet_qemu_sys/Cargo.toml | 8 +- fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs | 57 +++++++++-- fuzzers/wcet_qemu_sys/src/worst.rs | 122 +++++++++++++++++++++++- libafl_qemu/src/edges.rs | 1 - 4 files changed, 179 insertions(+), 9 deletions(-) diff --git a/fuzzers/wcet_qemu_sys/Cargo.toml b/fuzzers/wcet_qemu_sys/Cargo.toml index 8a208ac5a7..a200fd110e 100644 --- a/fuzzers/wcet_qemu_sys/Cargo.toml +++ b/fuzzers/wcet_qemu_sys/Cargo.toml @@ -5,7 +5,7 @@ authors = [ "Alwin Berger " ] edition = "2021" [features] -default = ["std"] +default = ["std", "obj_collect"] std = [] multicore = [] @@ -21,6 +21,12 @@ sched_mapmax = [] sched_state = [] sched_graph = [] +# objective selection, additive +obj_collect = [] +obj_trace = [] +obj_edges = [] +obj_ticks = [] + muta_snip = [ "sched_graph" ] [profile.release] diff --git a/fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs b/fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs index 036bf9175c..468892eb31 100644 --- a/fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs +++ b/fuzzers/wcet_qemu_sys/src/bin/fuzzer.rs @@ -1,5 +1,9 @@ //! A singlethreaded QEMU fuzzer that can auto-restart. +use wcet_qemu_sys::worst::DummyFeedback; +use wcet_qemu_sys::worst::ExecTimeCollectorFeedback; +use wcet_qemu_sys::worst::EXEC_TIME_COLLECTION; +use wcet_qemu_sys::worst::ExecTimeReachedFeedback; use libafl::inputs::Input; use libafl::feedbacks::Feedback; use libafl::HasFeedback; @@ -86,7 +90,7 @@ use libafl_qemu::{ clock::ClockFeedback, clock::QemuClockIncreaseFeedback }; -use wcet_qemu_sys::worst::{SortedFeedback,HitFeedback,HitImprovingFeedback,TimeStateMaximizerCorpusScheduler}; +use wcet_qemu_sys::worst::{SortedFeedback,HitFeedback,HitImprovingFeedback,TimeStateMaximizerCorpusScheduler,LenTimeMaximizerCorpusScheduler}; /// The fuzzer main @@ -154,6 +158,16 @@ pub fn main() { .required(true) .takes_value(true), ) + .arg( + Arg::new("exectimes") + .long("libafl-exectimes") + .takes_value(true), + ) + .arg( + Arg::new("targettime") + .long("libafl-targettime") + .takes_value(true), + ) .try_get_matches_from(filter_qemu_args()) { Ok(res) => res, @@ -216,9 +230,19 @@ pub fn main() { None => None }; + let exectimes = match res.value_of("exectimes") { + Some(st) => Some(PathBuf::from(st.to_string())), + None => None + }; + + let targettime = match res.value_of("targettime") { + Some(st) => Some(st.to_string().parse::().expect("targettime not a number")), + None => None + }; + let snapshot = PathBuf::from(res.value_of("snapshot").unwrap().to_string()); - fuzz(out_dir, crashes, in_dir, tokens, logfile, timeout, kernel, edges, traces, snapshot) + fuzz(out_dir, crashes, in_dir, tokens, logfile, timeout, kernel, edges, traces, exectimes, targettime, snapshot) .expect("An error occurred while fuzzing"); } @@ -246,6 +270,8 @@ fn fuzz( kernel: PathBuf, dump_edges: Option, dump_traces: Option, + dump_exectimes: Option, + targettime: Option, snapshot: PathBuf, ) -> Result<(), Error> { env::remove_var("LD_LIBRARY_PATH"); @@ -375,9 +401,15 @@ fn fuzz( let feedback = feedback_or!(feedback, SysMapFeedback::new()); // A feedback to choose if an input is a solution or not - let objective = feedback_or!(HitFeedback::new(target_map,0.0,&edges_observer),HitSysStateFeedback::new(target_trace)); - // let objective = feedback_or!(HitFeedback::new(target_map,0.0,&edges_observer)); - // let objective = SortedFeedback::new(); + let objective = DummyFeedback::new(false); + #[cfg(feature = "obj_collect")] + let objective = ExecTimeCollectorFeedback::new(); + #[cfg(feature = "obj_trace")] + let objective = feedback_or!(HitSysStateFeedback::new(target_trace)); + #[cfg(feature = "obj_edges")] + let objective = feedback_or!(HitFeedback::new(target_map,0.0,&edges_observer), objective); + #[cfg(feature = "obj_ticks")] + let objective = feedback_or!(ExecTimeReachedFeedback::new(targettime)); // create a State from scratch let mut state = state.unwrap_or_else(||{ @@ -412,9 +444,10 @@ fn fuzz( let mutation = StdMutationalStage::new(mutator); // A minimization+queue policy to get testcasess from the corpus - // let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(PowerQueueCorpusScheduler::new()); #[cfg(feature = "sched_queue")] let scheduler = QueueCorpusScheduler::new(); + #[cfg(feature = "sched_mapmax")] + let scheduler = LenTimeMaximizerCorpusScheduler::new(QueueCorpusScheduler::new()); #[cfg(feature = "sched_state")] let scheduler = TimeStateMaximizerCorpusScheduler::new(QueueCorpusScheduler::new()); #[cfg(feature = "sched_graph")] @@ -545,6 +578,18 @@ fn fuzz( fs::write("./graph.dot",tempg).expect("Graph can not be written"); } + // Wite out the collected exec times + #[cfg(feature = "obj_collect")] + match dump_exectimes { + Some(et) => unsafe { + let mut stringforms : Vec = Vec::new(); + for i in EXEC_TIME_COLLECTION.drain(..) { + stringforms.push(format!("{}\n",i)); + } + fs::write(et,stringforms.concat()).expect("Exec times can not be written"); + } + None => (), + } // Never reached Ok(()) diff --git a/fuzzers/wcet_qemu_sys/src/worst.rs b/fuzzers/wcet_qemu_sys/src/worst.rs index 8fef77acf0..3bd837a9e0 100644 --- a/fuzzers/wcet_qemu_sys/src/worst.rs +++ b/fuzzers/wcet_qemu_sys/src/worst.rs @@ -1,3 +1,5 @@ +use libafl::feedbacks::FeedbackState; +use libafl_qemu::QemuClockObserver; use crate::sysstate::FreeRTOSSystemStateMetadata; use num_traits::PrimInt; use core::fmt::Debug; @@ -592,4 +594,122 @@ impl Default for SortedFeedback { } } -//=================================================================== \ No newline at end of file +//=================================================================== +/// A Feedback which expects a certain minimum execution time +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct ExecTimeReachedFeedback +{ + target_time: u64, +} + +impl Feedback for ExecTimeReachedFeedback +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::("clock") + .expect("QemuClockObserver not found"); + Ok(observer.last_runtime() >= self.target_time) + } +} + +impl Named for ExecTimeReachedFeedback +{ + #[inline] + fn name(&self) -> &str { + "ExecTimeReachedFeedback" + } +} + +impl ExecTimeReachedFeedback +where +{ + /// Creates a new [`ExecTimeReachedFeedback`] + #[must_use] + pub fn new(target_time : u64) -> Self { + Self {target_time: target_time} + } +} + +pub static mut EXEC_TIME_COLLECTION : Vec = Vec::new(); + +/// A Noop Feedback which records a list of all execution times +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct ExecTimeCollectorFeedback +{ +} + +impl Feedback for ExecTimeCollectorFeedback +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::("clock") + .expect("QemuClockObserver not found"); + unsafe { EXEC_TIME_COLLECTION.push(observer.last_runtime().try_into().unwrap()); } + Ok(false) + } +} + +impl Named for ExecTimeCollectorFeedback +{ + #[inline] + fn name(&self) -> &str { + "ExecTimeCollectorFeedback" + } +} + +impl ExecTimeCollectorFeedback +where +{ + /// Creates a new [`ExecTimeCollectorFeedback`] + #[must_use] + pub fn new() -> Self { + Self {} + } +} + +/// Shared Metadata for a SysStateFeedback +#[derive(Serialize, Deserialize, Clone, Debug, Default)] +pub struct ExecTimeCollectorFeedbackState +{ + collection: Vec, +} +impl Named for ExecTimeCollectorFeedbackState +{ + #[inline] + fn name(&self) -> &str { + "ExecTimeCollectorFeedbackState" + } +} +impl FeedbackState for ExecTimeCollectorFeedbackState +{ + fn reset(&mut self) -> Result<(), Error> { + self.collection.clear(); + Ok(()) + } +} \ No newline at end of file diff --git a/libafl_qemu/src/edges.rs b/libafl_qemu/src/edges.rs index fba60f5049..cdd9047844 100644 --- a/libafl_qemu/src/edges.rs +++ b/libafl_qemu/src/edges.rs @@ -1,4 +1,3 @@ -use crate::libafl_exec_edge_one_off; use std::ops::Range; use hashbrown::{hash_map::Entry, HashMap}; use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata};