From 1f538f98345af4db0b5a3e0e7ba6626d270682a5 Mon Sep 17 00:00:00 2001 From: Alwin Berger Date: Wed, 25 Jan 2023 12:59:17 +0100 Subject: [PATCH] add sytemstate sceduler, fuzz until time --- fuzzers/FRET/src/fuzzer.rs | 29 ++++++++++++++++++++++++++--- fuzzers/FRET/src/worst.rs | 4 ++-- libafl/src/fuzzer/mod.rs | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/fuzzers/FRET/src/fuzzer.rs b/fuzzers/FRET/src/fuzzer.rs index 29c8230bd1..45be58c1f2 100644 --- a/fuzzers/FRET/src/fuzzer.rs +++ b/fuzzers/FRET/src/fuzzer.rs @@ -28,7 +28,7 @@ use libafl::{ stages::StdMutationalStage, state::{HasCorpus, StdState}, Error, - prelude::{SimpleMonitor, SimpleEventManager, AsMutSlice, RandBytesGenerator, Generator}, Evaluator, + prelude::{SimpleMonitor, SimpleEventManager, AsMutSlice, RandBytesGenerator, Generator, SimpleRestartingEventManager}, Evaluator, }; use libafl_qemu::{ edges, edges::QemuEdgeCoverageHelper, elf::EasyElf, emu::Emulator, GuestPhysAddr, QemuExecutor, @@ -37,7 +37,7 @@ use libafl_qemu::{ use crate::{ clock::{QemuClockObserver, ClockTimeFeedback, QemuClockIncreaseFeedback, ICOUNT_HISTORY}, qemustate::QemuStateRestoreHelper, - systemstate::{helpers::QemuSystemStateHelper, observers::QemuSystemStateObserver, feedbacks::{DumpSystraceFeedback, NovelSystemStateFeedback}}, worst::{TimeMaximizerCorpusScheduler, ExecTimeIncFeedback}, + systemstate::{helpers::QemuSystemStateHelper, observers::QemuSystemStateObserver, feedbacks::{DumpSystraceFeedback, NovelSystemStateFeedback}}, worst::{TimeMaximizerCorpusScheduler, ExecTimeIncFeedback, TimeStateMaximizerCorpusScheduler}, }; pub static mut MAX_INPUT_SIZE: usize = 32; @@ -59,6 +59,7 @@ extern "C" { } pub fn fuzz() { + let starttime = std::time::Instant::now(); if let Ok(s) = env::var("FUZZ_SIZE") { str::parse::(&s).expect("FUZZ_SIZE was not a number"); }; @@ -242,7 +243,10 @@ pub fn fuzz() { }); // A minimization+queue policy to get testcasess from the corpus + #[cfg(not(feature = "systemstate"))] let scheduler = TimeMaximizerCorpusScheduler::new(QueueScheduler::new()); + #[cfg(feature = "systemstate")] + let scheduler = TimeStateMaximizerCorpusScheduler::new(QueueScheduler::new()); // A fuzzer with feedbacks and a corpus scheduler let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); @@ -344,8 +348,11 @@ pub fn fuzz() { fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap(); } }} else { + // fuzzer + // .fuzz_loop_for_duration(&mut stages, &mut executor, &mut state, &mut mgr, Duration::from_secs(num)) + // .unwrap(); fuzzer - .fuzz_loop_for_duration(&mut stages, &mut executor, &mut state, &mut mgr, Duration::from_secs(num)) + .fuzz_loop_until(&mut stages, &mut executor, &mut state, &mut mgr, starttime.checked_add(Duration::from_secs(num)).unwrap()) .unwrap(); } if let Ok(td) = env::var("TIME_DUMP") { @@ -395,6 +402,22 @@ pub fn fuzz() { let monitor = SimpleMonitor::new(|s| println!("{}", s)); let mgr = SimpleEventManager::new(monitor); run_client(None, mgr, 0); + + // let mut shmem_provider = StdShMemProvider::new().unwrap(); + // let (state, mut mgr) = match SimpleRestartingEventManager::launch(monitor, &mut shmem_provider) + // { + // // The restarting state will spawn the same process again as child, then restarted it each time it crashes. + // Ok(res) => res, + // Err(err) => match err { + // Error::ShuttingDown => { + // return; + // } + // _ => { + // panic!("Failed to setup the restarter: {}", err); + // } + // }, + // }; + // run_client(state, mgr, 0); } // else -> multicore #[cfg(not(feature = "singlecore"))] diff --git a/fuzzers/FRET/src/worst.rs b/fuzzers/FRET/src/worst.rs index 6bb2a847d8..827be83076 100644 --- a/fuzzers/FRET/src/worst.rs +++ b/fuzzers/FRET/src/worst.rs @@ -62,10 +62,10 @@ where } pub type LenTimeMaximizerCorpusScheduler = - MinimizerScheduler::Input>, MapIndexesMetadata>; + MinimizerScheduler::State>, MapIndexesMetadata>; pub type TimeStateMaximizerCorpusScheduler = - MinimizerScheduler::Input>, FreeRTOSSystemStateMetadata>; + MinimizerScheduler::State>, FreeRTOSSystemStateMetadata>; /// Multiply the testcase size with the execution time. /// This favors small and quick testcases. diff --git a/libafl/src/fuzzer/mod.rs b/libafl/src/fuzzer/mod.rs index b3c6c4f39b..50680619a9 100644 --- a/libafl/src/fuzzer/mod.rs +++ b/libafl/src/fuzzer/mod.rs @@ -271,6 +271,40 @@ where Ok(ret) } + + /// Fuzz for n iterations. + /// Returns the index of the last fuzzed corpus item. + /// (Note: An iteration represents a complete run of every stage. + /// therefore the number n is not always equal to the number of the actual harness executions, + /// because each stage could run the harness for multiple times) + /// + /// If you use this fn in a restarting scenario to only run for `n` iterations, + /// before exiting, make sure you call `event_mgr.on_restart(&mut state)?;`. + /// This way, the state will be available in the next, respawned, iteration. + fn fuzz_loop_until( + &mut self, + stages: &mut ST, + executor: &mut E, + state: &mut EM::State, + manager: &mut EM, + time: std::time::Instant + ) -> Result { + let mut ret = 0; + let mut last = current_time(); + let monitor_timeout = STATS_TIMEOUT_DEFAULT; + + while std::time::Instant::now() < time { + ret = self.fuzz_one(stages, executor, state, manager)?; + last = manager.maybe_report_progress(state, last, monitor_timeout)?; + } + + // If we would assume the fuzzer loop will always exit after this, we could do this here: + // manager.on_restart(state)?; + // But as the state may grow to a few megabytes, + // for now we won' and the user has to do it (unless we find a way to do this on `Drop`). + + Ok(ret) + } } /// The corpus this input should be added to