From f4e199038770b0e47aa4eb378c66cc08adc01dfc Mon Sep 17 00:00:00 2001 From: Alwin Berger Date: Thu, 5 Jan 2023 17:34:34 +0100 Subject: [PATCH] add systemstate feature and dump times --- fuzzers/FRET/Cargo.toml | 1 + fuzzers/FRET/fuzzer.sh | 6 ++-- fuzzers/FRET/src/clock.rs | 5 ++- fuzzers/FRET/src/fuzzer.rs | 72 ++++++++++++++++++++++++++++++-------- 4 files changed, 67 insertions(+), 17 deletions(-) diff --git a/fuzzers/FRET/Cargo.toml b/fuzzers/FRET/Cargo.toml index 857125a86e..be0d1e4b7a 100644 --- a/fuzzers/FRET/Cargo.toml +++ b/fuzzers/FRET/Cargo.toml @@ -10,6 +10,7 @@ std = [] snapshot_restore = [] snapshot_fast = [ "snapshot_restore" ] singlecore = [] +systemstate = [] [profile.release] lto = true diff --git a/fuzzers/FRET/fuzzer.sh b/fuzzers/FRET/fuzzer.sh index 41084db1b7..557364ed11 100755 --- a/fuzzers/FRET/fuzzer.sh +++ b/fuzzers/FRET/fuzzer.sh @@ -3,6 +3,8 @@ [ -n "$2" -a "$2" != "+" -a -z "$FUZZ_MAIN" ] && export FUZZ_MAIN="$2" [ -n "$3" -a "$3" != "+" -a -z "$FUZZ_INPUT" ] && export FUZZ_INPUT="$3" [ -n "$4" -a "$4" != "+" -a -z "$BREAKPOINT" ] && export BREAKPOINT="$4" -[ -n "$5" -a "$5" != "+" -a -z "$DO_SHOWMAP" ] && export DO_SHOWMAP="$5" -[ -n "$6" -a "$6" != "+" -a -z "$SHOWMAP_TEXTINPUT" ] && export SHOWMAP_TEXTINPUT="$6" +[ -n "$5" -a "$5" != "+" -a -z "$FUZZ_ITERS" ] && export FUZZ_ITERS="$5" +[ -n "$6" -a "$6" != "+" -a -z "$TIME_DUMP" ] && export TIME_DUMP="$6" +[ -n "$7" -a "$7" != "+" -a -z "$DO_SHOWMAP" ] && export DO_SHOWMAP="$7" +[ -n "$8" -a "$8" != "+" -a -z "$SHOWMAP_TEXTINPUT" ] && export SHOWMAP_TEXTINPUT="$8" target/debug/qemu_systemmode -icount shift=3,align=off,sleep=off -machine mps2-an385 -monitor null -kernel $KERNEL -serial null -nographic -S -semihosting --semihosting-config enable=on,target=native # -snapshot -drive if=none,format=qcow2,file=dummy.qcow2 \ No newline at end of file diff --git a/fuzzers/FRET/src/clock.rs b/fuzzers/FRET/src/clock.rs index 5f55133e21..c9987c67e1 100644 --- a/fuzzers/FRET/src/clock.rs +++ b/fuzzers/FRET/src/clock.rs @@ -84,6 +84,8 @@ impl Default for MaxIcountMetadata { //========== Observer +pub static mut ICOUNT_HISTORY : Vec = vec![]; + /// A simple observer, just overlooking the runtime of the target. #[derive(Serialize, Deserialize, Debug, Clone)] pub struct QemuClockObserver { @@ -130,7 +132,8 @@ where fn post_exec(&mut self, _state: &mut S, _input: &S::Input, _exit_kind: &ExitKind) -> Result<(), Error> { unsafe { self.end_tick = emu::icount_get_raw() }; // println!("clock post {}", self.end_tick); - println!("Number of Ticks: {} <- {} {}",self.end_tick - self.start_tick, self.end_tick, self.start_tick); + // println!("Number of Ticks: {} <- {} {}",self.end_tick - self.start_tick, self.end_tick, self.start_tick); + unsafe { ICOUNT_HISTORY.push(self.end_tick - self.start_tick) }; Ok(()) } } diff --git a/fuzzers/FRET/src/fuzzer.rs b/fuzzers/FRET/src/fuzzer.rs index 6a9241eb94..87bc11f73f 100644 --- a/fuzzers/FRET/src/fuzzer.rs +++ b/fuzzers/FRET/src/fuzzer.rs @@ -35,7 +35,7 @@ use libafl_qemu::{ QemuHooks, Regs, QemuInstrumentationFilter, GuestAddr, }; use crate::{ - clock::{QemuClockObserver, ClockTimeFeedback, QemuClockIncreaseFeedback}, + clock::{QemuClockObserver, ClockTimeFeedback, QemuClockIncreaseFeedback, ICOUNT_HISTORY}, qemustate::QemuStateRestoreHelper, systemstate::{helpers::QemuSystemStateHelper, observers::QemuSystemStateObserver, feedbacks::DumpSystraceFeedback}, worst::TimeMaximizerCorpusScheduler, }; @@ -98,16 +98,21 @@ pub fn fuzz() { .expect("Symbol main not found"); println!("main address = {:#x}", main_addr); + #[cfg(feature = "systemstate")] let curr_tcb_pointer = elf // loads to the address specified in elf, without respecting program headers .resolve_symbol("pxCurrentTCB", 0) .expect("Symbol pxCurrentTCBC not found"); // let curr_tcb_pointer = virt2phys(curr_tcb_pointer,&elf); + #[cfg(feature = "systemstate")] println!("TCB pointer at {:#x}", curr_tcb_pointer); + #[cfg(feature = "systemstate")] let task_queue_addr = elf .resolve_symbol("pxReadyTasksLists", 0) .expect("Symbol pxReadyTasksLists not found"); // let task_queue_addr = virt2phys(task_queue_addr,&elf.goblin()); + #[cfg(feature = "systemstate")] println!("Task Queue at {:#x}", task_queue_addr); + #[cfg(feature = "systemstate")] let svh = elf .resolve_symbol("xPortPendSVHandler", 0) .expect("Symbol xPortPendSVHandler not found"); @@ -115,12 +120,15 @@ pub fn fuzz() { // let svh = elf // .resolve_symbol("vPortEnterCritical", 0) // .expect("Symbol vPortEnterCritical not found"); + #[cfg(feature = "systemstate")] let app_start = elf .resolve_symbol("__APP_CODE_START__", 0) .expect("Symbol __APP_CODE_START__ not found"); + #[cfg(feature = "systemstate")] let app_end = elf .resolve_symbol("__APP_CODE_END__", 0) .expect("Symbol __APP_CODE_END__ not found"); + #[cfg(feature = "systemstate")] let app_range = app_start..app_end; let breakpoint = elf @@ -140,11 +148,11 @@ pub fn fuzz() { let env: Vec<(String, String)> = env::vars().collect(); let emu = Emulator::new(&args, &env); - // emu.set_breakpoint(main_addr); - // unsafe { - // emu.run(); - // } - // emu.remove_breakpoint(main_addr); + emu.set_breakpoint(main_addr); + unsafe { + emu.run(); + } + emu.remove_breakpoint(main_addr); emu.set_breakpoint(breakpoint); // BREAKPOINT @@ -192,13 +200,17 @@ pub fn fuzz() { // Feedback to rate the interestingness of an input // This one is composed by two Feedbacks in OR let mut feedback = feedback_or!( - DumpSystraceFeedback::with_dump(None), // New maximization map feedback linked to the edges observer and the feedback state MaxMapFeedback::new_tracking(&edges_observer, true, true), // QemuClockIncreaseFeedback::default(), // Time feedback, this one does not need a feedback state ClockTimeFeedback::new_with_observer(&clock_time_observer) ); + #[cfg(feature = "systemstate")] + let mut feedback = feedback_or!( + DumpSystraceFeedback::with_dump(None), + feedback + ); // A feedback to choose if an input is a solution or not let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new()); @@ -227,15 +239,23 @@ pub fn fuzz() { // A fuzzer with feedbacks and a corpus scheduler let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); - let mut hooks = QemuHooks::new(&emu, - tuple_list!(QemuEdgeCoverageHelper::default(),QemuStateRestoreHelper::new(), - QemuSystemStateHelper::new(svh,curr_tcb_pointer,task_queue_addr,input_counter_ptr,app_range.clone()))); + let qhelpers = tuple_list!( + QemuEdgeCoverageHelper::default(), + QemuStateRestoreHelper::new()); + #[cfg(feature = "systemstate")] + let qhelpers = tuple_list!(qhelpers, + QemuSystemStateHelper::new(svh,curr_tcb_pointer,task_queue_addr,input_counter_ptr,app_range.clone())); + let mut hooks = QemuHooks::new(&emu,qhelpers); + + let observer_list = tuple_list!(edges_observer, clock_time_observer); + #[cfg(feature = "systemstate")] + let observer_list = tuple_list!(observer_list ,systemstate_observer); // Create a QEMU in-process executor let executor = QemuExecutor::new( &mut hooks, &mut harness, - tuple_list!(edges_observer, clock_time_observer, systemstate_observer), + observer_list, &mut fuzzer, &mut state, &mut mgr, @@ -273,9 +293,33 @@ pub fn fuzz() { println!("We imported {} inputs from disk.", state.corpus().count()); } - fuzzer - .fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr) - .unwrap(); + match env::var("FUZZ_ITERS") { + Err(_) => { + fuzzer + .fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr) + .unwrap(); + }, + Ok(t) => { + println!("Iterations {}",t); + let num = str::parse::(&t).expect("FUZZ_ITERS was not a number"); + fuzzer + .fuzz_loop_for(&mut stages, &mut executor, &mut state, &mut mgr, num) + .unwrap(); + let mut strbuf = String::new(); + + unsafe { + for i in ICOUNT_HISTORY.iter() { + strbuf.push_str(&format!("{}\n",i)); + } + } + match env::var("TIME_DUMP") { + Err(_) => (), + Ok(td) => { + fs::write(td, strbuf).expect("could not write time dump"); + } + } + }, + } } #[cfg(not(feature = "singlecore"))] Ok(())