From 5fad373199c874720e8c7ccc865e34339eb3bb8c Mon Sep 17 00:00:00 2001 From: Alwin Berger Date: Wed, 19 Jun 2024 13:30:36 +0200 Subject: [PATCH] update to 0.13.0 API --- fuzzers/FRET/src/clock.rs | 47 +++++++------- fuzzers/FRET/src/fuzzer.rs | 58 +++++++++-------- fuzzers/FRET/src/mutational.rs | 49 +++++++------- fuzzers/FRET/src/qemustate.rs | 15 +++-- fuzzers/FRET/src/systemstate/feedbacks.rs | 59 +++++++++++------ fuzzers/FRET/src/systemstate/freertos.rs | 6 +- fuzzers/FRET/src/systemstate/graph.rs | 43 ++++++------ fuzzers/FRET/src/systemstate/helpers.rs | 23 +++---- fuzzers/FRET/src/systemstate/mod.rs | 14 ++-- fuzzers/FRET/src/systemstate/observers.rs | 18 +++-- fuzzers/FRET/src/systemstate/schedulers.rs | 9 +-- fuzzers/FRET/src/systemstate/stg.rs | 64 ++++++++++++------ fuzzers/FRET/src/worst.rs | 65 ++++++++++++------- libafl_qemu/libafl_qemu_sys/src/systemmode.rs | 5 -- libafl_qemu/src/hooks.rs | 34 ++++++---- libafl_qemu/src/qemu/mod.rs | 35 +++++----- libafl_qemu/src/qemu/systemmode.rs | 4 +- 17 files changed, 313 insertions(+), 235 deletions(-) diff --git a/fuzzers/FRET/src/clock.rs b/fuzzers/FRET/src/clock.rs index fc965d67dd..a770c4bdb9 100644 --- a/fuzzers/FRET/src/clock.rs +++ b/fuzzers/FRET/src/clock.rs @@ -11,8 +11,9 @@ use libafl::{ fuzzer::{StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, observers::{Observer,VariableMapObserver}, - state::{StdState, HasNamedMetadata}, + state::{StdState}, Error, + common::HasNamedMetadata, observers::ObserversTuple, prelude::UsesInput, }; use serde::{Deserialize, Serialize}; @@ -22,7 +23,7 @@ use libafl_qemu::{ emu, emu::Emulator, executor::QemuExecutor, - helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter}, + helpers::{QemuHelper, QemuHelperTuple, HasInstrumentationFilter}, }; use libafl::events::EventFirer; use libafl::state::MaybeHasClientPerfMonitor; @@ -30,13 +31,14 @@ use libafl::prelude::State; use libafl::inputs::Input; use libafl::feedbacks::Feedback; use libafl::SerdeAny; -use libafl::state::HasMetadata; +use libafl::common::HasMetadata; use libafl::corpus::testcase::Testcase; use core::{fmt::Debug, time::Duration}; // use libafl::feedbacks::FeedbackState; // use libafl::state::HasFeedbackStates; use std::time::{SystemTime, UNIX_EPOCH}; use std::path::PathBuf; +use std::borrow::Cow; pub static mut FUZZ_START_TIMESTAMP : SystemTime = UNIX_EPOCH; @@ -60,7 +62,7 @@ pub struct QemuIcountMetadata { #[derive(Debug, Serialize, Deserialize, SerdeAny)] pub struct MaxIcountMetadata { pub max_icount_seen: u64, - pub name: String, + pub name: Cow<'static, str>, } // impl FeedbackState for MaxIcountMetadata @@ -74,8 +76,8 @@ pub struct MaxIcountMetadata { impl Named for MaxIcountMetadata { #[inline] - fn name(&self) -> &str { - self.name.as_str() + fn name(&self) -> &Cow<'static, str> { + &self.name } } @@ -86,7 +88,7 @@ impl MaxIcountMetadata pub fn new(name: &'static str) -> Self { Self { max_icount_seen: 0, - name: name.to_string(), + name: Cow::from(name), } } } @@ -106,7 +108,7 @@ pub struct IcHist (pub Vec<(u64, u128)>, pub (u64,u128)); /// A simple observer, just overlooking the runtime of the target. #[derive(Serialize, Deserialize, Debug, Clone)] pub struct QemuClockObserver { - name: String, + name: Cow<'static, str>, start_tick: u64, end_tick: u64, dump_path: Option @@ -117,7 +119,7 @@ impl QemuClockObserver { #[must_use] pub fn new(name: &'static str, dump_path: Option) -> Self { Self { - name: name.to_string(), + name: Cow::from(name), start_tick: 0, end_tick: 0, dump_path @@ -149,7 +151,7 @@ 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() }; + unsafe { self.end_tick = libafl_qemu::sys::icount_get_raw() }; if let Some(td) = &self.dump_path { // println!("clock post {}", self.end_tick); // println!("Number of Ticks: {} <- {} {}",self.end_tick - self.start_tick, self.end_tick, self.start_tick); @@ -187,7 +189,7 @@ where impl Named for QemuClockObserver { #[inline] - fn name(&self) -> &str { + fn name(&self) -> &Cow<'static, str> { &self.name } } @@ -195,7 +197,7 @@ impl Named for QemuClockObserver { impl Default for QemuClockObserver { fn default() -> Self { Self { - name: String::from("clock"), + name: Cow::from(String::from("clock")), start_tick: 0, end_tick: 0, dump_path: None @@ -210,7 +212,7 @@ impl Default for QemuClockObserver { #[derive(Serialize, Deserialize, Clone, Debug)] pub struct ClockTimeFeedback { exec_time: Option, - name: String, + name: Cow<'static, str>, } impl Feedback for ClockTimeFeedback @@ -238,9 +240,10 @@ where /// Append to the testcase the generated metadata in case of a new corpus item #[inline] - fn append_metadata( + fn append_metadata( &mut self, _state: &mut S, + _manager: &mut EM, observers: &OT, testcase: &mut Testcase, ) -> Result<(), Error> { @@ -259,8 +262,8 @@ where impl Named for ClockTimeFeedback { #[inline] - fn name(&self) -> &str { - self.name.as_str() + fn name(&self) -> &Cow<'static, str> { + &self.name } } @@ -270,7 +273,7 @@ impl ClockTimeFeedback { pub fn new(name: &'static str) -> Self { Self { exec_time: None, - name: name.to_string(), + name: Cow::from(name.to_string()), } } @@ -279,7 +282,7 @@ impl ClockTimeFeedback { pub fn new_with_observer(observer: &QemuClockObserver) -> Self { Self { exec_time: None, - name: observer.name().to_string(), + name: observer.name().clone(), } } } @@ -287,7 +290,7 @@ impl ClockTimeFeedback { /// A [`Feedback`] rewarding increasing the execution cycles on Qemu. #[derive(Debug)] pub struct QemuClockIncreaseFeedback { - name: String, + name: Cow<'static, str>, } impl Feedback for QemuClockIncreaseFeedback @@ -322,7 +325,7 @@ where /// Append to the testcase the generated metadata in case of a new corpus item #[inline] - fn append_metadata(&mut self, _state: &mut S, observers: &OT, testcase: &mut Testcase) -> Result<(), Error> { + fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, observers: &OT, testcase: &mut Testcase) -> Result<(), Error> { // testcase.metadata_mut().insert(QemuIcountMetadata{runtime: self.last_runtime}); Ok(()) } @@ -337,7 +340,7 @@ where impl Named for QemuClockIncreaseFeedback { #[inline] - fn name(&self) -> &str { + fn name(&self) -> &Cow<'static, str> { &self.name } } @@ -346,7 +349,7 @@ impl QemuClockIncreaseFeedback { /// Creates a new [`HitFeedback`] #[must_use] pub fn new(name: &'static str) -> Self { - Self {name: String::from(name)} + Self {name: Cow::from(String::from(name))} } } diff --git a/fuzzers/FRET/src/fuzzer.rs b/fuzzers/FRET/src/fuzzer.rs index ec199f1fca..3c9f25be49 100644 --- a/fuzzers/FRET/src/fuzzer.rs +++ b/fuzzers/FRET/src/fuzzer.rs @@ -4,13 +4,13 @@ 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, AsMutSlice, AsSlice +core_affinity::Cores, current_nanos, rands::StdRand, shmem::{ShMemProvider, StdShMemProvider}, tuples::tuple_list, AsSlice }; use libafl::{ -corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, executors::{ExitKind, TimeoutExecutor}, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, observers::VariableMapObserver, prelude::{havoc_mutations, minimizer::TopRatedsMetadata, CorpusId, Generator, HasBytesVec, HitcountsMapObserver, RandBytesGenerator, SimpleEventManager, SimpleMonitor, SimpleRestartingEventManager, StdScheduledMutator}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::StdMutationalStage, state::{HasCorpus, HasMetadata, HasNamedMetadata, StdState}, Error, Evaluator +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::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, observers::{CanTrack, VariableMapObserver}, prelude::{havoc_mutations, minimizer::TopRatedsMetadata, CorpusId, Generator, HitcountsMapObserver, RandBytesGenerator, SimpleEventManager, SimpleMonitor, SimpleRestartingEventManager, StdScheduledMutator}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, stages::StdMutationalStage, state::{HasCorpus, StdState}, Error, Evaluator }; use libafl_qemu::{ -edges::{self, edges_map_mut_slice, QemuEdgeCoverageHelper, MAX_EDGES_NUM}, elf::EasyElf, emu::{libafl_qemu_remove_native_breakpoint, libafl_qemu_set_native_breakpoint, Emulator}, GuestAddr, GuestPhysAddr, QemuExecutor, QemuHooks, QemuInstrumentationFilter, Regs +edges::{self, edges_map_mut_ptr, QemuEdgeCoverageHelper, MAX_EDGES_FOUND}, elf::EasyElf, emu::Emulator, GuestAddr, GuestPhysAddr, QemuExecutor, QemuFilterList, QemuHooks, Regs, StdInstrumentationFilter }; use rand::{SeedableRng, StdRng, Rng}; use crate::{ @@ -25,6 +25,8 @@ use petgraph::graph::NodeIndex; use petgraph::prelude::DiGraph; use crate::systemstate::stg::STGFeedbackState; use crate::clock::QEMU_ICOUNT_SHIFT; +use libafl::inputs::HasMutatorBytes; +use libafl_qemu::Qemu; // Constants ================================================================================ @@ -373,8 +375,8 @@ let app_fn_ranges = get_all_fn_symbol_ranges(&elf, app_range.clone()); let mut isr_ranges : HashMap> = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone())))).collect(); systemstate::helpers::ISR_SYMBOLS.iter().for_each(|x| {let _ =(app_fn_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone()))).map(|y| isr_ranges.insert(y.0,y.1));}); // add used defined isr -let denylist=isr_ranges.values().map(|x| x.clone()).collect(); -let denylist = QemuInstrumentationFilter::DenyList(denylist); // do not count isr jumps, which are useless +let denylist : Vec<_> =isr_ranges.values().map(|x| x.clone()).collect(); +let denylist = QemuFilterList::DenyList(denylist); // do not count isr jumps, which are useless #[cfg(feature = "observe_systemstate")] let mut isr_addreses : HashMap = systemstate::helpers::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.remove(&x.to_string()).map(|y| (y.start,x.to_string())))).collect(); #[cfg(feature = "observe_systemstate")] @@ -421,22 +423,22 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| { // "-semihosting", // "--semihosting-config", // "enable=on,target=native", - "-snapshot", - "-drive", - "if=none,format=qcow2,file=dummy.qcow2", + // "-snapshot", + // "-drive", + // "if=none,format=qcow2,file=dummy.qcow2", ].into_iter().map(String::from).collect(); let env: Vec<(String, String)> = env::vars().collect(); - let emu = Emulator::new(&args, &env).expect("Emulator creation failed"); + let emu = Qemu::init(&args, &env).expect("Emulator creation failed"); - if let Some(main_addr) = main_addr { - unsafe { - libafl_qemu_set_native_breakpoint(main_addr); - emu.run(); - libafl_qemu_remove_native_breakpoint(main_addr); - } - } + // if let Some(main_addr) = main_addr { + // unsafe { + // emu.set_breakpoint(main_addr); + // emu.run(); + // emu.remove_breakpoint(main_addr); + // } + // } - unsafe { libafl_qemu_set_native_breakpoint(breakpoint); }// BREAKPOINT + unsafe { emu.set_breakpoint(breakpoint); }// BREAKPOINT // The wrapped harness function, calling out to the LLVM-style harness let mut harness = |input: &BytesInput| { @@ -475,7 +477,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| { // If the execution stops at any point other then the designated breakpoint (e.g. a breakpoint on a panic method) we consider it a crash let mut pcs = (0..emu.num_cpus()) .map(|i| emu.cpu_from_index(i)) - .map(|cpu| -> Result { cpu.read_reg(Regs::Pc) }); + .map(|cpu| -> Result { cpu.read_reg(Regs::Pc) }); match pcs .find(|pc| (breakpoint..breakpoint + 5).contains(pc.as_ref().unwrap_or(&0))) { @@ -496,14 +498,14 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| { addr_of_mut!(MAX_EDGES_NUM) )}; #[cfg(feature = "observer_hitcounts")] - let edges_observer = HitcountsMapObserver::new(edges_observer); + let edges_observer = HitcountsMapObserver::new(edges_observer).track_indices(); #[cfg(feature = "observe_systemstate")] let stg_coverage_observer = unsafe { VariableMapObserver::from_mut_slice( "stg", stg_map_mut_slice(), addr_of_mut!(MAX_STG_NUM) - )}; + )}.track_indices(); #[cfg(feature = "observe_systemstate")] let systemstate_observer = QemuSystemStateObserver::new(); @@ -576,7 +578,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| { #[cfg(feature = "sched_afl",)] let scheduler = TimeMaximizerCorpusScheduler::new(QueueScheduler::new()); #[cfg(feature = "sched_stg")] - let scheduler = LongestTraceScheduler::new(GraphMaximizerCorpusScheduler::new(QueueScheduler::new())); + let scheduler = LongestTraceScheduler::new(GraphMaximizerCorpusScheduler::new(&stg_coverage_observer,QueueScheduler::new())); #[cfg(feature = "sched_genetic")] let scheduler = GenerationScheduler::new(); @@ -587,7 +589,7 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| { #[cfg(feature = "observe_systemstate")] let qhelpers = (QemuSystemStateHelper::new(api_addreses,api_ranges,isr_addreses,isr_ranges,curr_tcb_pointer,task_queue_addr,task_delay_addr,task_delay_overflow_addr,scheduler_lock,scheduler_running, critical_section,input_counter_ptr,app_range.clone()), qhelpers); #[cfg(feature = "observe_edges")] - let qhelpers = (QemuEdgeCoverageHelper::new(denylist), qhelpers); + let qhelpers = (QemuEdgeCoverageHelper::new(denylist, QemuFilterList::None), qhelpers); let qhelpers = (QemuStateRestoreHelper::new(), qhelpers); let mut hooks = QemuHooks::new(emu.clone(),qhelpers); @@ -600,18 +602,18 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| { let observer_list = (clock_time_observer, observer_list); // Create a QEMU in-process executor - let executor = QemuExecutor::new( + let mut executor = QemuExecutor::new( &mut hooks, &mut harness, observer_list, &mut fuzzer, &mut state, &mut mgr, + timeout ) .expect("Failed to create QemuExecutor"); - // Wrap the executor to keep track of the timeout - let mut executor = TimeoutExecutor::new(executor, timeout); + executor.break_on_timeout(); let mutations = havoc_mutations(); // Setup an havoc mutator with a mutational stage @@ -641,7 +643,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..1000 { + for i in 0..10 { let inp = BytesInput::new(vec![rng.gen::(); MAX_INPUT_SIZE]); fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap(); } @@ -740,10 +742,10 @@ let mut run_client = |state: Option<_>, mut mgr, _core_id| { // Initialize QEMU let args: Vec = env::args().collect(); let env: Vec<(String, String)> = env::vars().collect(); - let emu = Emulator::new(&args, &env).expect("Emu creation failed"); + let emu = Qemu::init(&args, &env).expect("Emu creation failed"); if let Some(main_addr) = main_addr { - unsafe { libafl_qemu_set_native_breakpoint(main_addr); }// BREAKPOINT + unsafe { emu.set_breakpoint(main_addr); }// BREAKPOINT } unsafe { emu.run(); diff --git a/fuzzers/FRET/src/mutational.rs b/fuzzers/FRET/src/mutational.rs index 4a3d088368..4fd132c090 100644 --- a/fuzzers/FRET/src/mutational.rs +++ b/fuzzers/FRET/src/mutational.rs @@ -6,14 +6,15 @@ use std::cmp::{max, min}; use hashbrown::HashMap; use libafl_bolts::rands::{ - StdRand, RandomSeed, + StdRand, random_seed, Rand }; use libafl::{ - corpus::{self, Corpus}, fuzzer::Evaluator, mark_feature_time, prelude::{new_hash_feedback, CorpusId, HasBytesVec, MutationResult, Mutator, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasMetadata, HasNamedMetadata, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error + common::{HasMetadata, HasNamedMetadata}, corpus::{self, Corpus}, fuzzer::Evaluator, inputs::HasMutatorBytes, 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 libafl::state::HasCurrentTestcase; pub static mut MINIMUM_INTER_ARRIVAL_TIME : u32 = 1000 /*us*/ * QEMU_ISNS_PER_USEC; // one isn per 2**4 ns @@ -77,32 +78,28 @@ where EM: UsesState, Z: Evaluator, Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand + HasMetadata + HasNamedMetadata, - ::Input: HasBytesVec + ::Input: HasMutatorBytes { fn perform( &mut self, fuzzer: &mut Z, executor: &mut E, state: &mut Self::State, - manager: &mut EM, - corpus_idx: CorpusId, + manager: &mut EM + // corpus_idx: CorpusId, ) -> Result<(), Error> { - let mut _input = state - .corpus() - .get(corpus_idx)? - .borrow_mut().clone(); - let mut newinput = _input.input_mut().as_mut().unwrap().clone(); + let mut myrand = StdRand::new(); + myrand.set_seed(state.rand_mut().next()); + let mut _input = state.current_testcase()?.clone(); + let mut newinput = _input.input().as_ref().unwrap().clone(); let mut do_rerun = false; // if state.rand_mut().between(1, 100) <= 50 // only attempt the mutation half of the time { // need our own random generator, because borrowing rules - let mut myrand = StdRand::new(); let mut target_bytes : Vec = vec![]; { - let input = _input.input_mut().as_ref().unwrap(); + let input = _input.input().as_ref().unwrap(); target_bytes = input.bytes().to_vec(); - let tmp = &mut state.rand_mut(); - myrand.set_seed(tmp.next()); } // produce a slice of absolute interrupt times @@ -129,7 +126,7 @@ where if interrupt_offsets[0] as u64 > maxtick { // place interrupt in reachable range do_rerun = true; for _ in 0..num_interrupts { - prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick, u32::MAX as u64)).try_into().expect("ticks > u32"))); + prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick as usize, u32::MAX as usize)).try_into().expect("ticks > u32"))); } } else { // let choice = myrand.between(1,100); @@ -261,8 +258,8 @@ where ).collect(); if untouched.len() > 0 { let tmp = interrupt_offsets[i]; - let choice = myrand.choose(untouched); - interrupt_offsets[i] = myrand.between(choice.0.start_tick, choice.0.end_tick) + let choice = myrand.choose(untouched).unwrap(); + interrupt_offsets[i] = myrand.between(choice.0.start_tick as usize, choice.0.end_tick as usize) .try_into().expect("tick > u32"); do_rerun = true; } @@ -274,7 +271,7 @@ where continue; } } - let replacement = myrand.choose(alternatives); + let replacement = myrand.choose(alternatives).unwrap(); if (old_hit.map_or(false, |x| x == replacement)) { // use the old value // println!("chose old value, do nothing i: {} {}",i,interrupt_offsets[i]); @@ -285,8 +282,8 @@ where old_handler.map_or(0, |x| x.0.end_tick - x.0.start_tick) } else { 0 }; let tmp = interrupt_offsets[i]; - interrupt_offsets[i] = (myrand.between(replacement.0.start_tick, - replacement.0.end_tick) + extra).try_into().expect("ticks > u32"); + interrupt_offsets[i] = (myrand.between(replacement.0.start_tick as usize, + replacement.0.end_tick as usize) + extra as usize).try_into().expect("ticks > u32"); // println!("chose new alternative, i: {} {} -> {}",i,tmp, interrupt_offsets[i]); do_rerun = true; } @@ -324,8 +321,8 @@ where let mut n : Vec = vec![]; n = [prefix.concat(), suffix].concat(); - newinput.bytes_mut().clear(); - newinput.bytes_mut().append(&mut n); + newinput.drain(..); + newinput.extend(&n); } // InterruptShifterMutator::mutate(&mut mymut, state, &mut input, 0)?; if do_rerun { @@ -333,6 +330,14 @@ where } Ok(()) } + + fn restart_progress_should_run(&mut self, state: &mut Self::State) -> Result { + Ok(true) + } + + fn clear_restart_progress(&mut self, state: &mut Self::State) -> Result<(), Error> { + Ok(()) + } } impl UsesState for InterruptShiftStage diff --git a/fuzzers/FRET/src/qemustate.rs b/fuzzers/FRET/src/qemustate.rs index d815059f8f..390a16992c 100644 --- a/fuzzers/FRET/src/qemustate.rs +++ b/fuzzers/FRET/src/qemustate.rs @@ -1,11 +1,12 @@ use libafl::prelude::UsesInput; -use libafl_qemu::CPUArchState; +use libafl_qemu::sys::CPUArchState; use libafl_qemu::Emulator; -use libafl_qemu::FastSnapshot; +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, state::HasMetadata}; +use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata}; use libafl_qemu::QemuHooks; use libafl_qemu::{ @@ -17,7 +18,7 @@ pub struct QemuStateRestoreHelper { has_snapshot: bool, use_snapshot: bool, saved_cpu_states: Vec, - fastsnap: Option + fastsnap: Option } impl QemuStateRestoreHelper { @@ -56,17 +57,17 @@ where { } - fn post_exec(&mut self, emulator: &Emulator, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) { + fn post_exec(&mut self, emulator: libafl_qemu::Qemu, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) { // unsafe { println!("snapshot post {}",emu::icount_get_raw()) }; } - fn pre_exec(&mut self, emulator: &Emulator, _input: &S::Input) { + fn pre_exec(&mut self, emulator: libafl_qemu::Qemu, _input: &S::Input) { // only restore in pre-exec, to preserve the post-execution state for inspection #[cfg(feature = "snapshot_restore")] { #[cfg(feature = "snapshot_fast")] match self.fastsnap { - Some(s) => emulator.restore_fast_snapshot(s), + Some(s) => unsafe { emulator.restore_fast_snapshot(s) }, None => {self.fastsnap = Some(emulator.create_fast_snapshot(true));}, } #[cfg(not(feature = "snapshot_fast"))] diff --git a/fuzzers/FRET/src/systemstate/feedbacks.rs b/fuzzers/FRET/src/systemstate/feedbacks.rs index b9a481da94..53783033ff 100644 --- a/fuzzers/FRET/src/systemstate/feedbacks.rs +++ b/fuzzers/FRET/src/systemstate/feedbacks.rs @@ -2,7 +2,7 @@ use libafl::SerdeAny; use libafl_bolts::ownedref::OwnedSlice; use libafl::inputs::BytesInput; use libafl::prelude::UsesInput; -use libafl::state::HasNamedMetadata; +use libafl::common::HasNamedMetadata; use std::path::PathBuf; use crate::clock::QemuClockObserver; use libafl::corpus::Testcase; @@ -17,7 +17,7 @@ use libafl::feedbacks::Feedback; use libafl_bolts::Named; use libafl::Error; use hashbrown::HashMap; -use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata}; +use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata}; use serde::{Deserialize, Serialize}; use super::ExecInterval; @@ -28,28 +28,38 @@ use petgraph::prelude::DiGraph; use petgraph::graph::NodeIndex; use petgraph::Direction; use std::cmp::Ordering; +use std::borrow::Cow; //============================= Feedback /// Shared Metadata for a systemstateFeedback -#[derive(Debug, Serialize, Deserialize, SerdeAny, Clone, Default)] +#[derive(Debug, Serialize, Deserialize, SerdeAny, Clone)] pub struct SystemStateFeedbackState { + name: Cow<'static, str>, known_traces: HashMap, // encounters,ticks,length longest: Vec, } impl Named for SystemStateFeedbackState { #[inline] - fn name(&self) -> &str { - "systemstate" + fn name(&self) -> &Cow<'static, str> { + &self.name + } +} + +impl Default for SystemStateFeedbackState +{ + fn default() -> Self { + Self {name: Cow::from("systemstate".to_string()), known_traces: HashMap::new(), longest: Vec::new() } } } /// A Feedback reporting novel System-State Transitions. Depends on [`QemuSystemStateObserver`] -#[derive(Serialize, Deserialize, Clone, Debug, Default)] +#[derive(Serialize, Deserialize, Clone, Debug)] pub struct NovelSystemStateFeedback { + name: Cow<'static, str>, last_trace: Option>, // known_traces: HashMap, } @@ -80,7 +90,7 @@ where Some(s) => s, None => { let n=SystemStateFeedbackState::default(); - state.named_metadata_map_mut().insert(n, "systemstate"); + state.named_metadata_map_mut().insert("systemstate",n); state.named_metadata_map_mut().get_mut::("systemstate").unwrap() } }; @@ -117,7 +127,7 @@ where /// Append to the testcase the generated metadata in case of a new corpus item #[inline] - fn append_metadata(&mut self, _state: &mut S, observers: &OT, testcase: &mut Testcase) -> Result<(), Error> { + fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, observers: &OT, testcase: &mut Testcase) -> Result<(), Error> { let a = self.last_trace.take(); match a { Some(s) => testcase.metadata_map_mut().insert(FreeRTOSSystemStateMetadata::new(s)), @@ -137,8 +147,15 @@ where impl Named for NovelSystemStateFeedback { #[inline] - fn name(&self) -> &str { - "systemstate" + fn name(&self) -> &Cow<'static, str> { + &self.name + } +} + +impl Default for NovelSystemStateFeedback +{ + fn default() -> Self { + Self {name: Cow::from("NovelSystemStateFeedback".to_string()), last_trace: None } } } @@ -147,6 +164,7 @@ impl Named for NovelSystemStateFeedback #[derive(Debug)] pub struct DumpSystraceFeedback { + name: Cow<'static, str>, dumpfile: Option, dump_metadata: bool, last_states: Option>, @@ -185,7 +203,7 @@ where } /// Append to the testcase the generated metadata in case of a new corpus item #[inline] - fn append_metadata(&mut self, _state: &mut S, observers: &OT, testcase: &mut Testcase) -> Result<(), Error> { + fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, observers: &OT, testcase: &mut Testcase) -> Result<(), Error> { if !self.dump_metadata {return Ok(());} // let a = self.last_trace.take(); // match a { @@ -206,8 +224,8 @@ where impl Named for DumpSystraceFeedback { #[inline] - fn name(&self) -> &str { - "Dumpsystemstate" + fn name(&self) -> &Cow<'static, str> { + &self.name } } @@ -216,13 +234,13 @@ impl DumpSystraceFeedback /// Creates a new [`DumpSystraceFeedback`] #[must_use] pub fn new() -> Self { - Self {dumpfile: None, dump_metadata: false, last_trace: None, last_states: None } + Self {name: Cow::from("Dumpsystemstate".to_string()), dumpfile: None, dump_metadata: false, last_trace: None, last_states: None } } pub fn with_dump(dumpfile: Option) -> Self { - Self {dumpfile: dumpfile, dump_metadata: false, last_trace: None, last_states: None} + Self {name: Cow::from("Dumpsystemstate".to_string()), dumpfile: dumpfile, dump_metadata: false, last_trace: None, last_states: None} } pub fn metadata_only() -> Self { - Self {dumpfile: None, dump_metadata: true, last_trace: None, last_states: None} + Self {name: Cow::from("Dumpsystemstate".to_string()), dumpfile: None, dump_metadata: true, last_trace: None, last_states: None} } } @@ -230,6 +248,7 @@ impl DumpSystraceFeedback #[derive(Debug, Default)] pub struct SystraceErrorFeedback { + name: Cow<'static, str>, dump_case: bool } @@ -255,7 +274,7 @@ where } /// Append to the testcase the generated metadata in case of a new corpus item #[inline] - fn append_metadata(&mut self, _state: &mut S, _observers: &OT, _testcase: &mut Testcase) -> Result<(), Error> { + fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, _testcase: &mut Testcase) -> Result<(), Error> { Ok(()) } @@ -269,8 +288,8 @@ where impl Named for SystraceErrorFeedback { #[inline] - fn name(&self) -> &str { - "SystraceErrorFeedback" + fn name(&self) -> &Cow<'static, str> { + &self.name } } @@ -278,6 +297,6 @@ impl SystraceErrorFeedback { #[must_use] pub fn new(dump_case: bool) -> Self { - Self {dump_case} + Self {name: Cow::from(String::from("SystraceErrorFeedback")), dump_case} } } \ No newline at end of file diff --git a/fuzzers/FRET/src/systemstate/freertos.rs b/fuzzers/FRET/src/systemstate/freertos.rs index 04e4338b5c..98d324923a 100644 --- a/fuzzers/FRET/src/systemstate/freertos.rs +++ b/fuzzers/FRET/src/systemstate/freertos.rs @@ -1,7 +1,7 @@ #![allow(non_camel_case_types,non_snake_case,non_upper_case_globals,deref_nullptr)] use serde::{Deserialize, Serialize}; // Manual Types -use libafl_qemu::Emulator; +use libafl_qemu::{Emulator, Qemu}; /*========== Start of generated Code =============*/ pub type char_ptr = ::std::os::raw::c_uint; @@ -88,7 +88,7 @@ pub type TCB_t = tskTCB; /*========== End of generated Code =============*/ pub trait emu_lookup { - fn lookup(emu: &Emulator, addr: ::std::os::raw::c_uint) -> Self; + fn lookup(emu: &Qemu, addr: ::std::os::raw::c_uint) -> Self; } @@ -104,7 +104,7 @@ pub enum rtos_struct { macro_rules! impl_emu_lookup { ($struct_name:ident) => { impl $crate::systemstate::freertos::emu_lookup for $struct_name { - fn lookup(emu: &Emulator, addr: ::std::os::raw::c_uint) -> $struct_name { + fn lookup(emu: &Qemu, addr: ::std::os::raw::c_uint) -> $struct_name { let mut tmp : [u8; std::mem::size_of::<$struct_name>()] = [0u8; std::mem::size_of::<$struct_name>()]; unsafe { emu.read_mem(addr.into(), &mut tmp); diff --git a/fuzzers/FRET/src/systemstate/graph.rs b/fuzzers/FRET/src/systemstate/graph.rs index 2d59be87c4..84426fa269 100644 --- a/fuzzers/FRET/src/systemstate/graph.rs +++ b/fuzzers/FRET/src/systemstate/graph.rs @@ -1,14 +1,14 @@ use libafl::SerdeAny; /// Feedbacks organizing SystemStates as a graph -use libafl::inputs::HasBytesVec; -use libafl_bolts::rands::RandomSeed; +// use libafl::inputs::HasBytesVec; +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::state::HasNamedMetadata; +use libafl::common::HasNamedMetadata; use libafl::state::UsesState; use libafl::prelude::State; use core::marker::PhantomData; @@ -35,7 +35,7 @@ use libafl::feedbacks::Feedback; use libafl_bolts::Named; use libafl::Error; use hashbrown::HashMap; -use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata}; +use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata}; use serde::{Deserialize, Serialize}; use super::ExecInterval; @@ -46,6 +46,7 @@ use petgraph::prelude::DiGraph; use petgraph::graph::NodeIndex; use petgraph::Direction; use std::cmp::Ordering; +use std::borrow::Cow; use libafl_bolts::rands::Rand; @@ -148,14 +149,14 @@ impl SysGraphMetadata { Self {indices: inner.iter().map(|x| x.index()).collect(), inner: inner, tcref: 0} } } -impl AsSlice for SysGraphMetadata { - /// Convert the slice of system-states to a slice of hashes over enumerated states - fn as_slice(&self) -> &[usize] { - self.indices.as_slice() - } +// impl AsSlice for SysGraphMetadata { +// /// Convert the slice of system-states to a slice of hashes over enumerated states +// fn as_slice(&self) -> &[usize] { +// self.indices.as_slice() +// } - type Entry = usize; -} +// type Entry = usize; +// } impl HasRefCnt for SysGraphMetadata { fn refcnt(&self) -> isize { @@ -169,8 +170,8 @@ impl HasRefCnt for SysGraphMetadata { libafl_bolts::impl_serdeany!(SysGraphMetadata); -pub type GraphMaximizerCorpusScheduler = - MinimizerScheduler::State>,SysGraphMetadata>; +pub type GraphMaximizerCorpusScheduler = + MinimizerScheduler::State>,SysGraphMetadata,O>; //============================= Graph Feedback @@ -181,7 +182,7 @@ pub struct SysGraphFeedbackState pub graph: DiGraph, entrypoint: NodeIndex, exit: NodeIndex, - name: String, + name: Cow<'static, str> } impl SysGraphFeedbackState { @@ -193,7 +194,7 @@ impl SysGraphFeedbackState exit.base.current_task.task_name="End".to_string(); let entry = graph.add_node(entry); let exit = graph.add_node(exit); - Self {graph: graph, entrypoint: entry, exit: exit, name: String::from("SysMap")} + Self {graph: graph, entrypoint: entry, exit: exit, name: Cow::from(String::from("SysMap"))} } fn insert(&mut self, list: Vec, input: &Vec) { let mut current_index = self.entrypoint; @@ -251,7 +252,7 @@ impl SysGraphFeedbackState impl Named for SysGraphFeedbackState { #[inline] - fn name(&self) -> &str { + fn name(&self) -> &Cow<'static, str> { &self.name } } @@ -278,12 +279,12 @@ impl SysGraphFeedbackState #[derive(Serialize, Deserialize, Clone, Debug, Default)] pub struct SysMapFeedback { - name: String, + name: Cow<'static, str>, last_trace: Option>, } impl SysMapFeedback { pub fn new() -> Self { - Self {name: String::from("SysMapFeedback"), last_trace: None } + Self {name: Cow::from(String::from("SysMapFeedback")), last_trace: None } } } @@ -313,7 +314,7 @@ where Some(s) => s, None => { let n=SysGraphFeedbackState::default(); - state.named_metadata_map_mut().insert(n, "SysMap"); + state.named_metadata_map_mut().insert("SysMap",n); state.named_metadata_map_mut().get_mut::("SysMap").unwrap() } }; @@ -324,7 +325,7 @@ where /// Append to the testcase the generated metadata in case of a new corpus item #[inline] - fn append_metadata(&mut self, _state: &mut S, _observers: &OT, testcase: &mut Testcase) -> Result<(), Error> { + fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, testcase: &mut Testcase) -> Result<(), Error> { let a = self.last_trace.take(); match a { Some(s) => testcase.metadata_map_mut().insert(SysGraphMetadata::new(s)), @@ -343,7 +344,7 @@ where impl Named for SysMapFeedback { #[inline] - fn name(&self) -> &str { + fn name(&self) -> &Cow<'static, str> { &self.name } } diff --git a/fuzzers/FRET/src/systemstate/helpers.rs b/fuzzers/FRET/src/systemstate/helpers.rs index 759e19e98b..db6f4aab48 100644 --- a/fuzzers/FRET/src/systemstate/helpers.rs +++ b/fuzzers/FRET/src/systemstate/helpers.rs @@ -9,6 +9,7 @@ use libafl_qemu::Emulator; use libafl_qemu::GuestAddr; use libafl_qemu::GuestPhysAddr; use libafl_qemu::GuestReg; +use libafl_qemu::Qemu; use libafl_qemu::QemuHooks; use libafl_qemu::edges::QemuEdgesMapMetadata; use libafl_qemu::emu; @@ -26,7 +27,7 @@ use super::freertos; use super::CaptureEvent; use libafl_qemu::{ - helper::{QemuHelper, QemuHelperTuple}, + helpers::{QemuHelper, QemuHelperTuple}, // edges::SAVED_JUMP, }; @@ -120,14 +121,14 @@ where } // TODO: refactor duplicate code - fn pre_exec(&mut self, _emulator: &Emulator, _input: &S::Input) { + fn pre_exec(&mut self, _emulator: libafl_qemu::Qemu, _input: &S::Input) { unsafe { CURRENT_SYSTEMSTATE_VEC.clear(); } } - fn post_exec(&mut self, emulator: &Emulator, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) { - trigger_collection(emulator,(0, 0), CaptureEvent::End, self); + fn post_exec(&mut self, emulator: libafl_qemu::Qemu, _input: &S::Input, _observers: &mut OT, _exit_kind: &mut ExitKind) { + trigger_collection(&emulator,(0, 0), CaptureEvent::End, self); unsafe { let c = emulator.cpu_from_index(0); let pc = c.read_reg::(15).unwrap(); @@ -148,7 +149,7 @@ where } } -fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &Emulator, target: GuestAddr) -> freertos::List_t { +fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &libafl_qemu::Qemu, target: GuestAddr) -> freertos::List_t { let read : freertos::List_t = freertos::emu_lookup::lookup(emulator, target); let listbytes : GuestAddr = GuestAddr::try_from(std::mem::size_of::()).unwrap(); @@ -187,7 +188,7 @@ fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &Emul } #[inline] -fn trigger_collection(emulator: &Emulator, edge: (GuestAddr, GuestAddr), event: CaptureEvent, h: &QemuSystemStateHelper) { +fn trigger_collection(emulator: &libafl_qemu::Qemu, edge: (GuestAddr, GuestAddr), event: CaptureEvent, h: &QemuSystemStateHelper) { let listbytes : GuestAddr = GuestAddr::try_from(std::mem::size_of::()).unwrap(); let mut systemstate = RawFreeRTOSSystemState::default(); @@ -272,7 +273,7 @@ where S: UsesInput, QT: QemuHelperTuple, { - let emulator = hooks.emulator(); + let emulator = hooks.qemu(); let h = hooks.helpers().match_first_type::().expect("QemuSystemHelper not found in helper tupel"); let src = read_rec_return_stackframe(emulator, 0xfffffffc); trigger_collection(emulator, (src, pc), CaptureEvent::ISRStart, h); @@ -324,7 +325,7 @@ where QT: QemuHelperTuple, { let h = hooks.helpers().match_first_type::().expect("QemuSystemHelper not found in helper tupel"); - let emulator = hooks.emulator(); + let emulator = hooks.qemu(); if id == 1 { // API call trigger_collection(emulator, (src, dest), CaptureEvent::APIStart, h); // println!("Exec API Call {:#x} {:#x} {}", src, dest, get_icount(emulator)); @@ -353,19 +354,19 @@ where //============================= Utility functions -fn get_icount(emulator : &Emulator) -> u64 { +fn get_icount(emulator : &libafl_qemu::Qemu) -> u64 { unsafe { // TODO: investigate why can_do_io is not set sometimes, as this is just a workaround let c = emulator.cpu_from_index(0); let can_do_io = (*c.raw_ptr()).neg.can_do_io; (*c.raw_ptr()).neg.can_do_io = true; - let r = emu::icount_get_raw(); + let r = libafl_qemu::sys::icount_get_raw(); (*c.raw_ptr()).neg.can_do_io = can_do_io; r } } -fn read_rec_return_stackframe(emu : &Emulator, lr : GuestAddr) -> GuestAddr { +fn read_rec_return_stackframe(emu : &libafl_qemu::Qemu, lr : GuestAddr) -> GuestAddr { let lr_ = lr & u32::MAX-1; if lr_ == 0xfffffffc || lr_ == 0xFFFFFFF8 || lr_ == 0xFFFFFFF0 { unsafe { diff --git a/fuzzers/FRET/src/systemstate/mod.rs b/fuzzers/FRET/src/systemstate/mod.rs index a18c14be22..289164afb5 100644 --- a/fuzzers/FRET/src/systemstate/mod.rs +++ b/fuzzers/FRET/src/systemstate/mod.rs @@ -242,14 +242,14 @@ where s.finish() } -impl AsSlice for FreeRTOSSystemStateMetadata { - /// Convert the slice of system-states to a slice of hashes over enumerated states - fn as_slice(&self) -> &[usize] { - self.indices.as_slice() - } +// impl AsSlice for FreeRTOSSystemStateMetadata { +// /// Convert the slice of system-states to a slice of hashes over enumerated states +// fn as_slice(&self) -> &[usize] { +// self.indices.as_slice() +// } - type Entry = usize; -} +// type Entry = usize; +// } impl HasRefCnt for FreeRTOSSystemStateMetadata { fn refcnt(&self) -> isize { diff --git a/fuzzers/FRET/src/systemstate/observers.rs b/fuzzers/FRET/src/systemstate/observers.rs index ab4c3cc933..f01cdeee0b 100644 --- a/fuzzers/FRET/src/systemstate/observers.rs +++ b/fuzzers/FRET/src/systemstate/observers.rs @@ -12,6 +12,7 @@ use crate::systemstate::CaptureEvent; use std::rc::Rc; use std::cell::RefCell; use std::collections::VecDeque; +use std::borrow::Cow; use super::{ AtomicBasicBlock, ExecInterval}; use super::{ @@ -26,7 +27,7 @@ use super::{ /// The Qemusystemstate Observer retrieves the systemstate /// that will get updated by the target. -#[derive(Serialize, Deserialize, Debug, Default)] +#[derive(Serialize, Deserialize, Debug)] #[allow(clippy::unsafe_derive_deserialize)] pub struct QemuSystemStateObserver { @@ -35,7 +36,7 @@ pub struct QemuSystemStateObserver pub last_trace: Vec, pub last_input: Vec, pub success: bool, - name: String, + name: Cow<'static, str>, } impl Observer for QemuSystemStateObserver @@ -74,9 +75,8 @@ where impl Named for QemuSystemStateObserver { - #[inline] - fn name(&self) -> &str { - self.name.as_str() + fn name(&self) -> &Cow<'static, str> { + &self.name } } @@ -90,9 +90,13 @@ impl HasLen for QemuSystemStateObserver impl QemuSystemStateObserver { pub fn new() -> Self { - Self{last_run: vec![], last_trace: vec![], last_input: vec![], name: "systemstate".to_string(), last_states: HashMap::new(), success: false } + Self{last_run: vec![], last_trace: vec![], last_input: vec![], name: Cow::from("systemstate".to_string()), last_states: HashMap::new(), success: false } + } +} +impl Default for QemuSystemStateObserver { + fn default() -> Self { + Self::new() } - } //============================= Parsing helpers diff --git a/fuzzers/FRET/src/systemstate/schedulers.rs b/fuzzers/FRET/src/systemstate/schedulers.rs index d7b56e5aa6..6ef96054ad 100644 --- a/fuzzers/FRET/src/systemstate/schedulers.rs +++ b/fuzzers/FRET/src/systemstate/schedulers.rs @@ -11,7 +11,8 @@ use libafl::{ corpus::{Corpus, Testcase}, inputs::UsesInput, schedulers::{Scheduler, TestcaseScore, minimizer::DEFAULT_SKIP_NON_FAVORED_PROB }, - state::{HasCorpus, HasMetadata, HasRand, UsesState, State}, + state::{HasCorpus, HasRand, UsesState, State}, + common::HasMetadata, Error, SerdeAny, prelude::CorpusId, }; @@ -39,7 +40,7 @@ impl LongestTracesMetadata { #[derive(Debug, Clone)] pub struct LongestTraceScheduler { base: CS, - skip_non_favored_prob: u64, + skip_non_favored_prob: usize, } impl UsesState for LongestTraceScheduler @@ -102,7 +103,7 @@ where .metadata_map() .get::().map_or(0, |x| x.nodes.len()); let m = self.get_update_trace_length(state,l); - state.rand_mut().below(m) > l as u64 + state.rand_mut().below(m as usize) > l } && state.rand_mut().below(100) < self.skip_non_favored_prob { idx = self.base.next(state)?; @@ -130,7 +131,7 @@ where pub fn new(base: CS) -> Self { Self { base, - skip_non_favored_prob: DEFAULT_SKIP_NON_FAVORED_PROB, + skip_non_favored_prob: (DEFAULT_SKIP_NON_FAVORED_PROB * 100.0) as usize, } } } diff --git a/fuzzers/FRET/src/systemstate/stg.rs b/fuzzers/FRET/src/systemstate/stg.rs index dd4c2d5fcf..f25d11cbe0 100644 --- a/fuzzers/FRET/src/systemstate/stg.rs +++ b/fuzzers/FRET/src/systemstate/stg.rs @@ -2,17 +2,18 @@ use hashbrown::HashSet; use libafl::SerdeAny; /// Feedbacks organizing SystemStates as a graph -use libafl::inputs::HasBytesVec; +// use libafl::inputs::HasBytesVec; use libafl_bolts::ownedref::OwnedMutSlice; +use libafl_bolts::AsIter; use petgraph::graph::EdgeIndex; use std::fs; -use libafl_bolts::rands::RandomSeed; +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::state::HasNamedMetadata; +use libafl::common::HasNamedMetadata; use libafl::state::UsesState; use libafl::prelude::State; use petgraph::dot::Config; @@ -40,9 +41,9 @@ use libafl::state::MaybeHasClientPerfMonitor; use libafl::feedbacks::Feedback; use libafl_bolts::Named; use libafl::Error; -use libafl_qemu::edges::EDGES_MAP_SIZE; +use libafl_qemu::edges::EDGES_MAP_SIZE_IN_USE; use hashbrown::HashMap; -use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata}; +use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, common::HasMetadata}; use serde::{Deserialize, Serialize}; use super::feedbacks::SystemStateFeedbackState; @@ -63,6 +64,9 @@ use libafl_bolts::rands::Rand; use crate::clock::FUZZ_START_TIMESTAMP; use std::time::SystemTime; use std::{fs::OpenOptions, io::Write}; +use std::borrow::Cow; +use std::ops::Deref; +use std::ops::DerefMut; //============================= Data Structures #[derive(Serialize, Deserialize, Clone, Debug, Default, Hash)] @@ -144,6 +148,7 @@ impl STGEdge { #[derive(Debug, Serialize, Deserialize, SerdeAny, Clone)] pub struct STGFeedbackState { + name: Cow<'static, str>, // aggregated traces as a graph pub graph: DiGraph, systemstate_index: HashMap, @@ -179,6 +184,7 @@ impl Default for STGFeedbackState { let index = HashMap::from([(h_entry, entrypoint), (h_exit, exitpoint)]); STGFeedbackState { + name: Cow::from("stgfeedbackstate".to_string()), graph, stgnode_index: index, entrypoint, @@ -196,8 +202,8 @@ impl Default for STGFeedbackState { impl Named for STGFeedbackState { #[inline] - fn name(&self) -> &str { - "stgfeedbackstate" + fn name(&self) -> &Cow<'static, str> { + &self.name } } @@ -238,13 +244,31 @@ impl STGNodeMetadata { Self {indices, intervals, nodes, abbs, aggregate, top_abb_counts, edges, tcref: 0} } } -impl AsSlice for STGNodeMetadata { - /// Convert the slice of system-states to a slice of hashes over enumerated states - fn as_slice(&self) -> &[usize] { - self.indices.as_slice() - } - type Entry = usize; +// impl AsSlice for STGNodeMetadata { +// /// Convert the slice of system-states to a slice of hashes over enumerated states +// fn as_slice(&self) -> &[usize] { +// self.indices.as_slice() +// } + +// type Entry = usize; + +// type SliceRef = &[usize]; +// } + +impl Deref for STGNodeMetadata { + type Target = [usize]; + /// Convert to a slice + fn deref(&self) -> &[usize] { + &self.indices + } +} + +impl DerefMut for STGNodeMetadata { + /// Convert to a slice + fn deref_mut(&mut self) -> &mut [usize] { + &mut self.indices + } } impl HasRefCnt for STGNodeMetadata { @@ -259,8 +283,8 @@ impl HasRefCnt for STGNodeMetadata { libafl_bolts::impl_serdeany!(STGNodeMetadata); -pub type GraphMaximizerCorpusScheduler = - MinimizerScheduler::State>,STGNodeMetadata>; +pub type GraphMaximizerCorpusScheduler = + MinimizerScheduler::State>,STGNodeMetadata,O>; // AI generated, human verified fn count_occurrences(vec: &Vec) -> HashMap<&T, usize> @@ -294,7 +318,7 @@ where //============================= Graph Feedback -pub static mut STG_MAP: [u16; EDGES_MAP_SIZE] = [0; EDGES_MAP_SIZE]; +pub static mut STG_MAP: [u16; EDGES_MAP_SIZE_IN_USE] = [0; EDGES_MAP_SIZE_IN_USE]; pub static mut MAX_STG_NUM: usize = 0; pub unsafe fn stg_map_mut_slice<'a>() -> OwnedMutSlice<'a, u16> { OwnedMutSlice::from_raw_parts_mut(STG_MAP.as_mut_ptr(), STG_MAP.len()) @@ -304,7 +328,7 @@ pub unsafe fn stg_map_mut_slice<'a>() -> OwnedMutSlice<'a, u16> { #[derive(Serialize, Deserialize, Clone, Debug, Default)] pub struct StgFeedback { - name: String, + name: Cow<'static, str>, last_node_trace: Option>, last_edge_trace: Option>, last_intervals: Option>, @@ -468,7 +492,7 @@ where Some(s) => s, None => { let n=STGFeedbackState::default(); - state.named_metadata_map_mut().insert(n, "stgfeedbackstate"); + state.named_metadata_map_mut().insert("stgfeedbackstate",n); state.named_metadata_map_mut().get_mut::("stgfeedbackstate").unwrap() } }; @@ -565,7 +589,7 @@ where /// Append to the testcase the generated metadata in case of a new corpus item #[inline] - fn append_metadata(&mut self, _state: &mut S, _observers: &OT, testcase: &mut Testcase) -> Result<(), Error> { + fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, testcase: &mut Testcase) -> Result<(), Error> { let nodes = self.last_node_trace.take(); let edges = self.last_edge_trace.take(); match nodes { @@ -584,7 +608,7 @@ where impl Named for StgFeedback { #[inline] - fn name(&self) -> &str { + fn name(&self) -> &Cow<'static, str> { &self.name } } \ No newline at end of file diff --git a/fuzzers/FRET/src/worst.rs b/fuzzers/FRET/src/worst.rs index b40062d232..4db3ac1cde 100644 --- a/fuzzers/FRET/src/worst.rs +++ b/fuzzers/FRET/src/worst.rs @@ -17,7 +17,7 @@ use libafl::state::{MaybeHasClientPerfMonitor, HasCorpus, UsesState}; use libafl::prelude::State; use libafl::inputs::Input; use libafl::feedbacks::Feedback; -use libafl::state::HasMetadata; +use libafl::common::HasMetadata; use libafl_qemu::edges::QemuEdgesMapMetadata; use libafl::observers::MapObserver; use serde::{Deserialize, Serialize}; @@ -35,10 +35,12 @@ use libafl::{ use crate::clock::QemuClockObserver; use crate::systemstate::FreeRTOSSystemStateMetadata; + +use std::borrow::Cow; //=========================== Scheduler -pub type TimeMaximizerCorpusScheduler = - MinimizerScheduler::State>, MapIndexesMetadata>; +pub type TimeMaximizerCorpusScheduler = + MinimizerScheduler::State>, MapIndexesMetadata, O>; /// Multiply the testcase size with the execution time. /// This favors small and quick testcases. @@ -64,11 +66,11 @@ where } } -pub type LenTimeMaximizerCorpusScheduler = - MinimizerScheduler::State>, MapIndexesMetadata>; +pub type LenTimeMaximizerCorpusScheduler = + MinimizerScheduler::State>, MapIndexesMetadata, O>; -pub type TimeStateMaximizerCorpusScheduler = - MinimizerScheduler::State>, FreeRTOSSystemStateMetadata>; +pub type TimeStateMaximizerCorpusScheduler = + MinimizerScheduler::State>, FreeRTOSSystemStateMetadata, O>; /// Multiply the testcase size with the execution time. /// This favors small and quick testcases. @@ -98,6 +100,7 @@ where /// A Feedback reporting if the Input consists of strictly decreasing bytes. #[derive(Serialize, Deserialize, Clone, Debug)] pub struct SortedFeedback { + name: Cow<'static, str> } impl Feedback for SortedFeedback @@ -146,8 +149,8 @@ where impl Named for SortedFeedback { #[inline] - fn name(&self) -> &str { - "Sorted" + fn name(&self) -> &Cow<'static, str> { + &self.name } } @@ -155,7 +158,7 @@ impl SortedFeedback { /// Creates a new [`HitFeedback`] #[must_use] pub fn new() -> Self { - Self {} + Self {name: Cow::from("Sorted".to_string()),} } } @@ -170,6 +173,7 @@ impl Default for SortedFeedback { #[derive(Serialize, Deserialize, Clone, Debug)] pub struct ExecTimeReachedFeedback { + name: Cow<'static, str>, target_time: u64, } @@ -199,8 +203,8 @@ where impl Named for ExecTimeReachedFeedback { #[inline] - fn name(&self) -> &str { - "ExecTimeReachedFeedback" + fn name(&self) -> &Cow<'static, str> { + &self.name } } @@ -210,7 +214,7 @@ where /// Creates a new [`ExecTimeReachedFeedback`] #[must_use] pub fn new(target_time : u64) -> Self { - Self {target_time: target_time} + Self {name: Cow::from("ExecTimeReachedFeedback".to_string()), target_time: target_time} } } @@ -220,6 +224,7 @@ pub static mut EXEC_TIME_COLLECTION : Vec = Vec::new(); #[derive(Serialize, Deserialize, Clone, Debug)] pub struct ExecTimeCollectorFeedback { + name: Cow<'static, str> } impl Feedback for ExecTimeCollectorFeedback @@ -249,8 +254,8 @@ where impl Named for ExecTimeCollectorFeedback { #[inline] - fn name(&self) -> &str { - "ExecTimeCollectorFeedback" + fn name(&self) -> &Cow<'static, str> { + &self.name } } @@ -260,21 +265,27 @@ where /// Creates a new [`ExecTimeCollectorFeedback`] #[must_use] pub fn new() -> Self { - Self {} + Self {name: Cow::from("ExecTimeCollectorFeedback".to_string())} } } /// Shared Metadata for a SysStateFeedback -#[derive(Serialize, Deserialize, Clone, Debug, Default)] +#[derive(Serialize, Deserialize, Clone, Debug)] pub struct ExecTimeCollectorFeedbackState { + name: Cow<'static, str>, collection: Vec, } impl Named for ExecTimeCollectorFeedbackState { #[inline] - fn name(&self) -> &str { - "ExecTimeCollectorFeedbackState" + fn name(&self) -> &Cow<'static, str> { + &self.name + } +} +impl Default for ExecTimeCollectorFeedbackState { + fn default() -> Self { + Self {name: Cow::from("ExecTimeCollectorFeedbackState".to_string()), collection: Vec::new()} } } @@ -283,6 +294,7 @@ impl Named for ExecTimeCollectorFeedbackState #[derive(Serialize, Deserialize, Clone, Debug)] pub struct ExecTimeIncFeedback { + name: Cow<'static, str>, longest_time: u64, last_is_longest: bool } @@ -315,9 +327,10 @@ where Ok(false) } } - fn append_metadata( + fn append_metadata( &mut self, _state: &mut S, + _manager: &mut EM, observers: &OT, testcase: &mut Testcase<::Input>, ) -> Result<(), Error> { @@ -334,8 +347,8 @@ where impl Named for ExecTimeIncFeedback { #[inline] - fn name(&self) -> &str { - "ExecTimeReachedFeedback" + fn name(&self) -> &Cow<'static, str> { + &self.name } } @@ -345,7 +358,7 @@ where /// Creates a new [`ExecTimeReachedFeedback`] #[must_use] pub fn new() -> Self { - Self {longest_time: 0, last_is_longest: false} + Self {name: Cow::from("ExecTimeReachedFeedback".to_string()), longest_time: 0, last_is_longest: false} } } @@ -353,6 +366,7 @@ where #[derive(Serialize, Deserialize, Clone, Debug)] pub struct AlwaysTrueFeedback { + name: Cow<'static, str> } impl Feedback for AlwaysTrueFeedback @@ -379,8 +393,8 @@ where impl Named for AlwaysTrueFeedback { #[inline] - fn name(&self) -> &str { - "AlwaysTrueFeedback" + fn name(&self) -> &Cow<'static, str> { + &self.name } } @@ -391,6 +405,7 @@ where #[must_use] pub fn new() -> Self { Self { + name: Cow::from("AlwaysTrueFeedback".to_string()) } } } \ No newline at end of file diff --git a/libafl_qemu/libafl_qemu_sys/src/systemmode.rs b/libafl_qemu/libafl_qemu_sys/src/systemmode.rs index bb0a8a56fb..7e15d7776d 100644 --- a/libafl_qemu/libafl_qemu_sys/src/systemmode.rs +++ b/libafl_qemu/libafl_qemu_sys/src/systemmode.rs @@ -16,9 +16,4 @@ extern_c_checked! { pub fn icount_get_raw() -> u64; pub fn libafl_start_int_timer(); - pub fn libafl_add_jmp_hook( - gen: Option u64>, // data,src,dest - exec: Option, // data,src,dest,id - data: u64 - ) -> usize; } diff --git a/libafl_qemu/src/hooks.rs b/libafl_qemu/src/hooks.rs index 503d0e484a..45dc32dda0 100644 --- a/libafl_qemu/src/hooks.rs +++ b/libafl_qemu/src/hooks.rs @@ -24,7 +24,7 @@ use crate::{ helpers::QemuHelperTuple, qemu::{MemAccessInfo, Qemu, SKIP_EXEC_HOOK}, sys::TCGTemp, - BackdoorHookId, BlockHookId, CmpHookId, EdgeHookId, HookId, InstructionHookId, ReadHookId, + BackdoorHookId, BlockHookId, CmpHookId, EdgeHookId, HookId, InstructionHookId, ReadHookId, JmpHookId, WriteHookId, }; #[cfg(emulation_mode = "usermode")] @@ -370,9 +370,9 @@ where } } -static mut JMP_HOOKS: Vec> = vec![]; -create_gen_wrapper!(jmp, (src: GuestAddr, dest: GuestAddr), u64, 1); -create_exec_wrapper!(jmp, (src: GuestAddr, dst: GuestAddr, id: u64), 0, 1); +static mut JMP_HOOKS: Vec>>> = vec![]; +create_gen_wrapper!(jmp, (src: GuestAddr, dest: GuestAddr), u64, 1, JmpHookId); +create_exec_wrapper!(jmp, (src: GuestAddr, dst: GuestAddr, id: u64), 0, 1, JmpHookId); @@ -1410,28 +1410,36 @@ where Box FnMut(&'a mut Self, Option<&'a mut S>, GuestAddr, GuestAddr, u64)>, extern "C" fn(*const (), src: GuestAddr, dest: GuestAddr, id: u64), >, - ) -> HookId { + ) -> JmpHookId { unsafe { let gen = get_raw_hook!( generation_hook, jmp_gen_hook_wrapper::, - extern "C" fn(&mut HookState<1>, src: GuestAddr, dest: GuestAddr) -> u64 + unsafe extern "C" fn(&mut HookState<1, JmpHookId>, src: GuestAddr, dest: GuestAddr) -> u64 ); let exec = get_raw_hook!( execution_hook, jmp_0_exec_hook_wrapper::, - extern "C" fn(&mut HookState<1>, src: GuestAddr, dest: GuestAddr, id: u64) + unsafe extern "C" fn(&mut HookState<1, JmpHookId>, src: GuestAddr, dest: GuestAddr, id: u64) ); - JMP_HOOKS.push(HookState { - id: HookId(0), + JMP_HOOKS.push(Box::pin(HookState { + id: JmpHookId(0), gen: hook_to_repr!(generation_hook), post_gen: HookRepr::Empty, execs: [hook_to_repr!(execution_hook)], - }); + })); let id = self - .emulator - .add_jmp_hooks(JMP_HOOKS.last_mut().unwrap(), gen, exec); - JMP_HOOKS.last_mut().unwrap().id = id; + .qemu + .add_jmp_hooks(JMP_HOOKS.last_mut().unwrap().as_mut().get_unchecked_mut(), + gen, + exec + ); + JMP_HOOKS + .last_mut() + .unwrap() + .as_mut() + .get_unchecked_mut() + .id = id; id } } diff --git a/libafl_qemu/src/qemu/mod.rs b/libafl_qemu/src/qemu/mod.rs index b102e721a8..645e9e6129 100644 --- a/libafl_qemu/src/qemu/mod.rs +++ b/libafl_qemu/src/qemu/mod.rs @@ -85,22 +85,7 @@ create_hook_id!(Cmp, libafl_qemu_remove_cmp_hook, true); create_hook_id!(PreSyscall, libafl_qemu_remove_pre_syscall_hook, false); create_hook_id!(PostSyscall, libafl_qemu_remove_post_syscall_hook, false); create_hook_id!(NewThread, libafl_qemu_remove_new_thread_hook, false); - -pub fn add_jmp_hooks>( - &self, - data: T, - gen: Option u64>, - exec: Option, -) -> HookId { - unsafe { - let data: u64 = data.into().0; - let gen: Option u64> = - core::mem::transmute(gen); - let exec: Option = core::mem::transmute(exec); - let num = libafl_add_jmp_hook(gen, exec, data); - HookId(num) - } -} +create_hook_id!(Jmp, libafl_qemu_remove_jmp_hook, true); #[derive(Debug)] pub enum QemuInitError { @@ -251,7 +236,7 @@ pub struct MemAccessInfo { #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct CPU { - ptr: CPUStatePtr, + pub ptr: CPUStatePtr, } #[derive(Debug, Clone, PartialEq)] @@ -1028,6 +1013,22 @@ impl Qemu { pub fn host_page_size(&self) -> usize { unsafe { libafl_qemu_sys::libafl_qemu_host_page_size() } } + + pub fn add_jmp_hooks>( + &self, + data: T, + gen: Option u64>, + exec: Option, + ) -> JmpHookId { + unsafe { + let data: u64 = data.into().0; + let gen: Option u64> = + core::mem::transmute(gen); + let exec: Option = core::mem::transmute(exec); + let num = libafl_qemu_sys::libafl_add_jmp_hook(gen, exec, data); + JmpHookId(num) + } + } } impl ArchExtras for Qemu { diff --git a/libafl_qemu/src/qemu/systemmode.rs b/libafl_qemu/src/qemu/systemmode.rs index e21fe03c86..6dfae7d4cd 100644 --- a/libafl_qemu/src/qemu/systemmode.rs +++ b/libafl_qemu/src/qemu/systemmode.rs @@ -8,9 +8,7 @@ use std::{ use bytes_utils::SegmentedBuf; use libafl_qemu_sys::{ - libafl_load_qemu_snapshot, libafl_page_from_addr, libafl_qemu_current_paging_id, - libafl_save_qemu_snapshot, qemu_cleanup, qemu_main_loop, vm_start, GuestAddr, GuestPhysAddr, - GuestUsize, GuestVirtAddr, + libafl_load_qemu_snapshot, libafl_page_from_addr, libafl_qemu_current_paging_id, libafl_save_qemu_snapshot, libafl_start_int_timer, qemu_cleanup, qemu_main_loop, vm_start, GuestAddr, GuestPhysAddr, GuestUsize, GuestVirtAddr }; use num_traits::Zero;