This commit is contained in:
Alwin Berger 2024-07-01 13:28:38 +02:00
parent 77799f77a9
commit 810ec36115
13 changed files with 43 additions and 78 deletions

View File

@ -4,7 +4,7 @@ use core::time::Duration;
use std::{env, path::PathBuf, process::{self, abort}, io::{Read, Write}, fs::{self, OpenOptions}, cmp::{min, max}, mem::transmute_copy, collections::btree_map::Range, ptr::addr_of_mut, ffi::OsStr};
use hashbrown::HashMap;
use libafl_bolts::{
core_affinity::Cores, current_nanos, rands::StdRand, shmem::{ShMemProvider, StdShMemProvider}, tuples::tuple_list, AsSlice
core_affinity::Cores, rands::StdRand, shmem::{ShMemProvider, StdShMemProvider}, tuples::tuple_list, AsSlice
};
use libafl::{
common::{HasMetadata, HasNamedMetadata}, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, executors::ExitKind, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{multi::MultipartInput, BytesInput, HasTargetBytes, Input}, monitors::MultiMonitor, observers::{CanTrack, VariableMapObserver}, prelude::{havoc_mutations, minimizer::TopRatedsMetadata, CorpusId, Generator, HitcountsMapObserver, RandBytesGenerator, SimpleEventManager, SimpleMonitor, SimpleRestartingEventManager, StdScheduledMutator}, schedulers::QueueScheduler, stages::StdMutationalStage, state::{HasCorpus, StdState}, Error, Evaluator
@ -14,16 +14,17 @@ edges::{self, edges_map_mut_ptr, QemuEdgeCoverageHelper, MAX_EDGES_FOUND}, elf::
};
use rand::{SeedableRng, StdRng, Rng};
use crate::{
clock::{ClockTimeFeedback, IcHist, QemuClockIncreaseFeedback, QemuClockObserver, FUZZ_START_TIMESTAMP}, mutational::{input_bytes_to_interrupt_times, InterruptShiftStage, MINIMUM_INTER_ARRIVAL_TIME}, qemustate::QemuStateRestoreHelper, systemstate::{self, feedbacks::{DumpSystraceFeedback, NovelSystemStateFeedback, SystraceErrorFeedback}, helpers::{get_function_range, load_symbol, try_load_symbol, QemuSystemStateHelper, ISR_SYMBOLS}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, GraphMaximizerCorpusScheduler, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}}, worst::{AlwaysTrueFeedback, ExecTimeIncFeedback, TimeMaximizerCorpusScheduler, TimeProbMassScheduler, TimeStateMaximizerCorpusScheduler}
time::{
clock::{ClockTimeFeedback, IcHist, QemuClockIncreaseFeedback, QemuClockObserver, FUZZ_START_TIMESTAMP, QEMU_ICOUNT_SHIFT},
worst::{AlwaysTrueFeedback, ExecTimeIncFeedback, TimeMaximizerCorpusScheduler, TimeProbMassScheduler, TimeStateMaximizerCorpusScheduler},
qemustate::QemuStateRestoreHelper
},
systemstate::{self, feedbacks::{DumpSystraceFeedback, NovelSystemStateFeedback, SystraceErrorFeedback}, helpers::{get_function_range, load_symbol, try_load_symbol, QemuSystemStateHelper, ISR_SYMBOLS}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, GraphMaximizerCorpusScheduler, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}},
systemstate::mutational::{input_bytes_to_interrupt_times, InterruptShiftStage, MINIMUM_INTER_ARRIVAL_TIME},
};
use std::time::{SystemTime, UNIX_EPOCH};
use csv::Reader;
use petgraph::{dot::{Config, Dot}, Graph};
use petgraph::graph::EdgeIndex;
use petgraph::graph::NodeIndex;
use petgraph::prelude::DiGraph;
use std::time::SystemTime;
use petgraph::dot::Dot;
use crate::systemstate::stg::STGFeedbackState;
use crate::clock::QEMU_ICOUNT_SHIFT;
use libafl::inputs::HasMutatorBytes;
use libafl_qemu::Qemu;
use crate::cli::Cli;
@ -35,7 +36,6 @@ use clap::Parser;
pub static mut RNG_SEED: u64 = 1;
pub static mut LIMIT : u32 = u32::MAX;
pub const FIRST_INT : u32 = 500000;
pub const MAX_NUM_INTERRUPT: usize = 128;
@ -66,6 +66,7 @@ for i in api_addreses.iter() {
return api_addreses;
}
#[allow(unused)]
extern "C" {
static mut libafl_interrupt_offsets : [u32; MAX_NUM_INTERRUPT];
static mut libafl_num_interrupts : usize;
@ -154,6 +155,7 @@ macro_rules! do_dump_toprated {
// Fuzzer setup ================================================================================
#[allow(unused)]
pub fn fuzz() {
let cli = Cli::parse();
set_env_from_config(&cli.kernel, &cli.config);
@ -266,7 +268,7 @@ let isr_ranges : Vec<_> = isr_ranges.into_iter().collect();
// Client setup ================================================================================
let mut run_client = |state: Option<_>, mut mgr, _core_id| {
let run_client = |state: Option<_>, mut mgr, _core_id| {
// Initialize QEMU
let args: Vec<String> = vec![
"target/debug/fret",
@ -323,7 +325,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
unsafe {
#[cfg(feature = "fuzz_int")]
{
let time_bytes = input.parts_by_name("interrupts").next().unwrap().1.bytes();
let time_bytes = input.parts_by_name("interrupts").next().map(|x| x.1.bytes()).unwrap_or(&[0u8; MAX_NUM_INTERRUPT*4]);
let t = input_bytes_to_interrupt_times(time_bytes);
for i in 0..t.len() {libafl_interrupt_offsets[i]=t[i];}
libafl_num_interrupts=t.len();
@ -516,7 +518,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| {
if let Some(se) = seed {
unsafe {
let mut rng = StdRng::seed_from_u64(se);
for i in 0..10 {
for _ in 0..100 {
let inp1 = BytesInput::new(vec![rng.gen::<u8>(); MAX_NUM_INTERRUPT*4]);
let inp2 = BytesInput::new(vec![rng.gen::<u8>(); MAX_INPUT_SIZE]);
let inp = MultipartInput::from([("interrupts",inp1),("bytes",inp2)]);

View File

@ -1,14 +1,8 @@
#[cfg(target_os = "linux")]
mod fuzzer;
#[cfg(target_os = "linux")]
mod clock;
mod time;
#[cfg(target_os = "linux")]
mod qemustate;
#[cfg(target_os = "linux")]
pub mod systemstate;
#[cfg(target_os = "linux")]
mod mutational;
#[cfg(target_os = "linux")]
mod worst;
mod systemstate;
#[cfg(target_os = "linux")]
mod cli;

View File

@ -2,16 +2,10 @@
#[cfg(target_os = "linux")]
mod fuzzer;
#[cfg(target_os = "linux")]
mod clock;
#[cfg(target_os = "linux")]
mod qemustate;
mod time;
#[cfg(target_os = "linux")]
mod systemstate;
#[cfg(target_os = "linux")]
mod worst;
#[cfg(target_os = "linux")]
mod mutational;
#[cfg(target_os = "linux")]
mod cli;
#[cfg(target_os = "linux")]

View File

@ -2,7 +2,7 @@ use libafl::SerdeAny;
use libafl::prelude::UsesInput;
use libafl::common::HasNamedMetadata;
use std::path::PathBuf;
use crate::clock::QemuClockObserver;
use crate::time::clock::QemuClockObserver;
use libafl::corpus::Testcase;
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;

View File

@ -17,6 +17,7 @@ pub mod observers;
pub mod feedbacks;
pub mod schedulers;
pub mod stg;
pub mod mutational;
// Constants
const NUM_PRIOS: usize = 5;

View File

@ -13,7 +13,7 @@ use libafl::{
common::{HasMetadata, HasNamedMetadata}, corpus::{self, Corpus}, fuzzer::Evaluator, inputs::{HasMutatorBytes, HasTargetBytes, Input, MultipartInput}, mark_feature_time, prelude::{new_hash_feedback, CorpusId, MutationResult, Mutator, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error
};
use libafl::prelude::State;
use crate::{clock::{IcHist, QEMU_ISNS_PER_USEC}, fuzzer::{DO_NUM_INTERRUPT, FIRST_INT, MAX_NUM_INTERRUPT}, systemstate::{stg::{STGFeedbackState, STGNodeMetadata}, CaptureEvent, ExecInterval, FreeRTOSSystemStateMetadata, ReducedFreeRTOSSystemState}};
use crate::{time::clock::{IcHist, QEMU_ISNS_PER_USEC}, fuzzer::{DO_NUM_INTERRUPT, FIRST_INT, MAX_NUM_INTERRUPT}, systemstate::{stg::{STGFeedbackState, STGNodeMetadata}, CaptureEvent, ExecInterval, FreeRTOSSystemStateMetadata, ReducedFreeRTOSSystemState}};
use libafl::state::HasCurrentTestcase;
pub static mut MINIMUM_INTER_ARRIVAL_TIME : u32 = 1000 /*us*/ * QEMU_ISNS_PER_USEC;

View File

@ -1,8 +1,7 @@
use libafl::prelude::ExitKind;
use libafl::{inputs::HasTargetBytes, prelude::UsesInput};
use libafl::prelude::UsesInput;
use libafl_bolts::HasLen;
use libafl_bolts::Named;
use libafl_bolts::AsSlice;
use libafl::Error;
use libafl::observers::Observer;
use serde::{Deserialize, Serialize};

View File

@ -17,7 +17,7 @@ use libafl::{
};
use crate::worst::MaxTimeFavFactor;
use crate::time::worst::MaxTimeFavFactor;
use super::{stg::STGNodeMetadata, FreeRTOSSystemStateMetadata};

View File

@ -1,38 +1,16 @@
use hashbrown::HashSet;
use libafl::SerdeAny;
/// Feedbacks organizing SystemStates as a graph
// use libafl::inputs::HasBytesVec;
use libafl::SerdeAny;
use libafl_bolts::ownedref::OwnedMutSlice;
use libafl_bolts::AsIter;
use petgraph::graph::EdgeIndex;
use std::fs;
use libafl_bolts::rands::random_seed;
use libafl_bolts::rands::StdRand;
use libafl::mutators::Mutator;
use libafl::mutators::MutationResult;
use libafl::prelude::HasTargetBytes;
use libafl::prelude::UsesInput;
use libafl::common::HasNamedMetadata;
use libafl::state::UsesState;
use libafl::prelude::State;
use petgraph::dot::Config;
use petgraph::dot::Dot;
use core::marker::PhantomData;
use libafl::state::HasCorpus;
use libafl::state::HasSolutions;
use libafl::state::HasRand;
use crate::worst::MaxExecsLenFavFactor;
use crate::worst::MaxTimeFavFactor;
use libafl::schedulers::MinimizerScheduler;
use libafl_bolts::HasRefCnt;
use libafl_bolts::AsSlice;
use libafl_bolts::ownedref::OwnedSlice;
use libafl::inputs::BytesInput;
use std::path::PathBuf;
use crate::clock::QemuClockObserver;
use libafl::corpus::Testcase;
use libafl_bolts::tuples::MatchName;
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
use std::hash::Hash;
@ -43,25 +21,21 @@ use libafl_bolts::Named;
use libafl::Error;
use libafl_qemu::edges::EDGES_MAP_SIZE_IN_USE;
use hashbrown::HashMap;
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata};
use libafl::{executors::ExitKind, observers::ObserversTuple, common::HasMetadata};
use serde::{Deserialize, Serialize};
use super::feedbacks::SystemStateFeedbackState;
use super::AtomicBasicBlock;
use super::CaptureEvent;
use super::ExecInterval;
use super::ReducedFreeRTOSSystemState;
use super::FreeRTOSSystemStateMetadata;
use super::observers::QemuSystemStateObserver;
use petgraph::prelude::DiGraph;
use petgraph::graph::NodeIndex;
use petgraph::Direction;
use std::cmp::Ordering;
use std::rc::Rc;
use libafl_bolts::rands::Rand;
use crate::clock::FUZZ_START_TIMESTAMP;
use crate::time::clock::QemuClockObserver;
use crate::time::clock::FUZZ_START_TIMESTAMP;
use crate::time::worst::MaxTimeFavFactor;
use std::time::SystemTime;
use std::{fs::OpenOptions, io::Write};
use std::borrow::Cow;
@ -76,7 +50,7 @@ pub struct STGNode
abb: AtomicBasicBlock,
}
impl STGNode {
pub fn pretty_print(&self) -> String {
pub fn _pretty_print(&self) -> String {
format!("{}\nl{} {:x}-{:x}\n{}", self.base.current_task.task_name, self.abb.level, self.abb.start, self.abb.ends.iter().next().unwrap_or_else(||&0xFFFF), self.base.print_lists())
}
pub fn color_print(&self) -> String {
@ -118,7 +92,7 @@ pub struct STGEdge
}
impl STGEdge {
pub fn pretty_print(&self) -> String {
pub fn _pretty_print(&self) -> String {
let mut short = match self.event {
CaptureEvent::APIStart => "Call: ",
CaptureEvent::APIEnd => "Ret: ",
@ -221,6 +195,7 @@ pub struct STGNodeMetadata {
}
impl STGNodeMetadata {
pub fn new(nodes: Vec<NodeIndex>, edges: Vec<EdgeIndex>, abbs: u64, aggregate: u64, top_abb_counts: Vec<u64>, intervals: Vec<ExecInterval>) -> Self{
#[allow(unused)]
let mut indices : Vec<_> = vec![];
#[cfg(all(feature = "sched_stg",not(any(feature = "sched_stg_pathhash",feature = "sched_stg_abbhash",feature = "sched_stg_aggregatehash"))))]
{
@ -393,7 +368,7 @@ impl StgFeedback {
let mut interesting = false;
let mut updated = false;
// add all missing state+abb combinations to the graph
for (i,interval) in trace.iter().enumerate() { // Iterate intervals
for (_i,interval) in trace.iter().enumerate() { // Iterate intervals
let node = STGNode {base: table[&interval.start_state].clone(), abb: interval.abb.as_ref().unwrap().clone()};
let h_node = node.get_hash();
let next_idx = if let Some(idx) = fbs.stgnode_index.get(&h_node) {
@ -502,7 +477,7 @@ where
}
}
let mut tmp = StgFeedback::abbs_in_exec_order(&observer.last_trace);
let tmp = StgFeedback::abbs_in_exec_order(&observer.last_trace);
if INTEREST_AGGREGATE || INTEREST_ABBPATH {
if INTEREST_ABBPATH {
let h = get_generic_hash(&tmp);

View File

@ -0,0 +1,3 @@
pub mod clock;
pub mod qemustate;
pub mod worst;

View File

@ -1,21 +1,17 @@
use libafl::prelude::UsesInput;
use libafl_qemu::sys::CPUArchState;
use libafl_qemu::Emulator;
use libafl_qemu::FastSnapshotPtr;
use libafl_qemu::Qemu;
use libafl_qemu::QemuExecutor;
use libafl_qemu::QemuHelper;
use libafl_qemu::QemuHelperTuple;
use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata};
use libafl::executors::ExitKind;
use libafl_qemu::QemuHooks;
use libafl_qemu::{
emu,
};
// TODO be thread-safe maybe with https://amanieu.github.io/thread_local-rs/thread_local/index.html
#[derive(Debug)]
pub struct QemuStateRestoreHelper {
#[allow(unused)]
has_snapshot: bool,
#[allow(unused)]
saved_cpu_states: Vec<CPUArchState>,
fastsnap: Option<FastSnapshotPtr>
}
@ -29,6 +25,7 @@ impl QemuStateRestoreHelper {
fastsnap: None
}
}
#[allow(unused)]
pub fn with_fast(fastsnap: Option<FastSnapshotPtr>) -> Self {
let mut r = Self::new();
r.fastsnap = fastsnap;
@ -60,7 +57,7 @@ where
{
}
fn post_exec<OT>(&mut self, emulator: libafl_qemu::Qemu, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) {
fn post_exec<OT>(&mut self, _emulator: libafl_qemu::Qemu, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) {
// unsafe { println!("snapshot post {}",emu::icount_get_raw()) };
}

View File

@ -33,7 +33,7 @@ use libafl::{
Error,
};
use crate::clock::QemuClockObserver;
use crate::time::clock::QemuClockObserver;
use crate::systemstate::FreeRTOSSystemStateMetadata;
use std::borrow::Cow;
@ -112,7 +112,7 @@ where
_state: &mut S,
_manager: &mut EM,
_input: &S::Input,
observers: &OT,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where