add a new scheduler for systemtraces
This commit is contained in:
parent
5db99e4e68
commit
6a8e9c80c1
@ -39,7 +39,7 @@ use rand::{SeedableRng, StdRng, Rng};
|
|||||||
use crate::{
|
use crate::{
|
||||||
clock::{QemuClockObserver, ClockTimeFeedback, QemuClockIncreaseFeedback, IcHist},
|
clock::{QemuClockObserver, ClockTimeFeedback, QemuClockIncreaseFeedback, IcHist},
|
||||||
qemustate::QemuStateRestoreHelper,
|
qemustate::QemuStateRestoreHelper,
|
||||||
systemstate::{helpers::QemuSystemStateHelper, observers::QemuSystemStateObserver, feedbacks::{DumpSystraceFeedback, NovelSystemStateFeedback}, graph::{SysMapFeedback, SysGraphFeedbackState, GraphMaximizerCorpusScheduler}}, worst::{TimeMaximizerCorpusScheduler, ExecTimeIncFeedback, TimeStateMaximizerCorpusScheduler},
|
systemstate::{helpers::QemuSystemStateHelper, observers::QemuSystemStateObserver, feedbacks::{DumpSystraceFeedback, NovelSystemStateFeedback}, graph::{SysMapFeedback, SysGraphFeedbackState, GraphMaximizerCorpusScheduler}, schedulers::LongestTraceScheduler}, worst::{TimeMaximizerCorpusScheduler, ExecTimeIncFeedback, TimeStateMaximizerCorpusScheduler},
|
||||||
};
|
};
|
||||||
pub static mut RNG_SEED: u64 = 1;
|
pub static mut RNG_SEED: u64 = 1;
|
||||||
|
|
||||||
@ -302,7 +302,7 @@ pub fn fuzz() {
|
|||||||
#[cfg(all(feature = "feed_afl",not(any(feature = "feed_systemgraph",feature = "feed_systemtrace"))))]
|
#[cfg(all(feature = "feed_afl",not(any(feature = "feed_systemgraph",feature = "feed_systemtrace"))))]
|
||||||
let scheduler = TimeMaximizerCorpusScheduler::new(QueueScheduler::new());
|
let scheduler = TimeMaximizerCorpusScheduler::new(QueueScheduler::new());
|
||||||
#[cfg(feature = "feed_systemtrace")]
|
#[cfg(feature = "feed_systemtrace")]
|
||||||
let scheduler = TimeStateMaximizerCorpusScheduler::new(QueueScheduler::new());
|
let scheduler = LongestTraceScheduler::new(TimeStateMaximizerCorpusScheduler::new(QueueScheduler::new()));
|
||||||
#[cfg(feature = "feed_systemgraph")]
|
#[cfg(feature = "feed_systemgraph")]
|
||||||
let scheduler = GraphMaximizerCorpusScheduler::new(QueueScheduler::new());
|
let scheduler = GraphMaximizerCorpusScheduler::new(QueueScheduler::new());
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ pub mod helpers;
|
|||||||
pub mod observers;
|
pub mod observers;
|
||||||
pub mod feedbacks;
|
pub mod feedbacks;
|
||||||
pub mod graph;
|
pub mod graph;
|
||||||
|
pub mod schedulers;
|
||||||
// pub mod mutators;
|
// pub mod mutators;
|
||||||
|
|
||||||
#[cfg(feature = "fuzz_interrupt")]
|
#[cfg(feature = "fuzz_interrupt")]
|
||||||
@ -125,13 +126,14 @@ impl RefinedFreeRTOSSystemState {
|
|||||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||||
pub struct FreeRTOSSystemStateMetadata {
|
pub struct FreeRTOSSystemStateMetadata {
|
||||||
inner: Vec<RefinedFreeRTOSSystemState>,
|
inner: Vec<RefinedFreeRTOSSystemState>,
|
||||||
|
trace_length: usize,
|
||||||
indices: Vec<usize>, // Hashed enumeration of States
|
indices: Vec<usize>, // Hashed enumeration of States
|
||||||
tcref: isize,
|
tcref: isize,
|
||||||
}
|
}
|
||||||
impl FreeRTOSSystemStateMetadata {
|
impl FreeRTOSSystemStateMetadata {
|
||||||
pub fn new(inner: Vec<RefinedFreeRTOSSystemState>) -> Self{
|
pub fn new(inner: Vec<RefinedFreeRTOSSystemState>) -> Self{
|
||||||
let tmp = inner.iter().enumerate().map(|x| compute_hash(x) as usize).collect();
|
let tmp = inner.iter().enumerate().map(|x| compute_hash(x) as usize).collect();
|
||||||
Self {inner: inner, indices: tmp, tcref: 0}
|
Self {trace_length: inner.len(), inner: inner, indices: tmp, tcref: 0}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn compute_hash<T>(obj: T) -> u64
|
pub fn compute_hash<T>(obj: T) -> u64
|
||||||
|
134
fuzzers/FRET/src/systemstate/schedulers.rs
Normal file
134
fuzzers/FRET/src/systemstate/schedulers.rs
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
//! The Minimizer schedulers are a family of corpus schedulers that feed the fuzzer
|
||||||
|
//! with testcases only from a subset of the total corpus.
|
||||||
|
|
||||||
|
use core::{marker::PhantomData};
|
||||||
|
use std::cmp::max;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use libafl::{
|
||||||
|
bolts::{rands::Rand, serdeany::SerdeAny, AsSlice, HasRefCnt},
|
||||||
|
corpus::{Corpus, Testcase},
|
||||||
|
inputs::UsesInput,
|
||||||
|
schedulers::{Scheduler, TestcaseScore, minimizer::DEFAULT_SKIP_NON_FAVORED_PROB },
|
||||||
|
state::{HasCorpus, HasMetadata, HasRand, UsesState},
|
||||||
|
Error, SerdeAny,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::FreeRTOSSystemStateMetadata;
|
||||||
|
|
||||||
|
/// A state metadata holding a map of favoreds testcases for each map entry
|
||||||
|
#[derive(Debug, Serialize, Deserialize, SerdeAny, Default)]
|
||||||
|
pub struct LongestTracesMetadata {
|
||||||
|
/// map index -> corpus index
|
||||||
|
pub max_trace_length: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LongestTracesMetadata {
|
||||||
|
fn new(l : usize) -> Self {
|
||||||
|
Self {max_trace_length: l}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The [`MinimizerScheduler`] employs a genetic algorithm to compute a subset of the
|
||||||
|
/// corpus that exercise all the requested features (e.g. all the coverage seen so far)
|
||||||
|
/// prioritizing [`Testcase`]`s` using [`TestcaseScore`]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct LongestTraceScheduler<CS> {
|
||||||
|
base: CS,
|
||||||
|
skip_non_favored_prob: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CS> UsesState for LongestTraceScheduler<CS>
|
||||||
|
where
|
||||||
|
CS: UsesState,
|
||||||
|
{
|
||||||
|
type State = CS::State;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CS> Scheduler for LongestTraceScheduler<CS>
|
||||||
|
where
|
||||||
|
CS: Scheduler,
|
||||||
|
CS::State: HasCorpus + HasMetadata + HasRand,
|
||||||
|
{
|
||||||
|
/// Add an entry to the corpus and return its index
|
||||||
|
fn on_add(&self, state: &mut CS::State, idx: usize) -> Result<(), Error> {
|
||||||
|
let l = state.corpus()
|
||||||
|
.get(idx)?
|
||||||
|
.borrow()
|
||||||
|
.metadata()
|
||||||
|
.get::<FreeRTOSSystemStateMetadata>().map_or(0, |x| x.trace_length);
|
||||||
|
self.get_update_trace_length(state,l);
|
||||||
|
self.base.on_add(state, idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replaces the testcase at the given idx
|
||||||
|
fn on_replace(
|
||||||
|
&self,
|
||||||
|
state: &mut CS::State,
|
||||||
|
idx: usize,
|
||||||
|
testcase: &Testcase<<CS::State as UsesInput>::Input>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let l = state.corpus()
|
||||||
|
.get(idx)?
|
||||||
|
.borrow()
|
||||||
|
.metadata()
|
||||||
|
.get::<FreeRTOSSystemStateMetadata>().map_or(0, |x| x.trace_length);
|
||||||
|
self.get_update_trace_length(state, l);
|
||||||
|
self.base.on_replace(state, idx, testcase)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes an entry from the corpus, returning M if M was present.
|
||||||
|
fn on_remove(
|
||||||
|
&self,
|
||||||
|
state: &mut CS::State,
|
||||||
|
idx: usize,
|
||||||
|
testcase: &Option<Testcase<<CS::State as UsesInput>::Input>>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
self.base.on_remove(state, idx, testcase)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the next entry
|
||||||
|
fn next(&self, state: &mut CS::State) -> Result<usize, Error> {
|
||||||
|
let mut idx = self.base.next(state)?;
|
||||||
|
while {
|
||||||
|
let l = state.corpus()
|
||||||
|
.get(idx)?
|
||||||
|
.borrow()
|
||||||
|
.metadata()
|
||||||
|
.get::<FreeRTOSSystemStateMetadata>().map_or(0, |x| x.trace_length);
|
||||||
|
let m = self.get_update_trace_length(state,l);
|
||||||
|
state.rand_mut().below(m) > l as u64
|
||||||
|
} && state.rand_mut().below(100) < self.skip_non_favored_prob
|
||||||
|
{
|
||||||
|
idx = self.base.next(state)?;
|
||||||
|
}
|
||||||
|
Ok(idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CS> LongestTraceScheduler<CS>
|
||||||
|
where
|
||||||
|
CS: Scheduler,
|
||||||
|
CS::State: HasCorpus + HasMetadata + HasRand,
|
||||||
|
{
|
||||||
|
pub fn get_update_trace_length(&self, state: &mut CS::State, par: usize) -> u64 {
|
||||||
|
// Create a new top rated meta if not existing
|
||||||
|
if let Some(td) = state.metadata_mut().get_mut::<LongestTracesMetadata>() {
|
||||||
|
let m = max(td.max_trace_length, par);
|
||||||
|
td.max_trace_length = m;
|
||||||
|
m as u64
|
||||||
|
} else {
|
||||||
|
state.add_metadata(LongestTracesMetadata::new(par));
|
||||||
|
par as u64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn new(base: CS) -> Self {
|
||||||
|
Self {
|
||||||
|
base,
|
||||||
|
skip_non_favored_prob: DEFAULT_SKIP_NON_FAVORED_PROB,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user