add sytemstate sceduler, fuzz until time

This commit is contained in:
Alwin Berger 2023-01-25 12:59:17 +01:00
parent ba01f600ee
commit 1f538f9834
3 changed files with 62 additions and 5 deletions

View File

@ -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::<usize>(&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"))]

View File

@ -62,10 +62,10 @@ where
}
pub type LenTimeMaximizerCorpusScheduler<CS> =
MinimizerScheduler<CS, MaxExecsLenFavFactor<<CS as UsesInput>::Input>, MapIndexesMetadata>;
MinimizerScheduler<CS, MaxExecsLenFavFactor<<CS as UsesState>::State>, MapIndexesMetadata>;
pub type TimeStateMaximizerCorpusScheduler<CS> =
MinimizerScheduler<CS, MaxExecsLenFavFactor<<CS as UsesInput>::Input>, FreeRTOSSystemStateMetadata>;
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, FreeRTOSSystemStateMetadata>;
/// Multiply the testcase size with the execution time.
/// This favors small and quick testcases.

View File

@ -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<usize, Error> {
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