From 8d7e32559fdb0db6b81ebf2a4922bc0536077e1a Mon Sep 17 00:00:00 2001 From: Alwin Berger Date: Fri, 6 Dec 2024 16:10:25 +0100 Subject: [PATCH] type fixing --- fuzzers/FRET/src/debug.rs | 4 +- fuzzers/FRET/src/fuzzer.rs | 18 +- fuzzers/FRET/src/lib.rs | 4 +- fuzzers/FRET/src/main.rs | 2 + fuzzers/FRET/src/systemstate/feedbacks.rs | 25 ++- fuzzers/FRET/src/systemstate/helpers.rs | 123 +++++++++----- fuzzers/FRET/src/systemstate/mod.rs | 2 +- fuzzers/FRET/src/systemstate/mutational.rs | 30 ++-- fuzzers/FRET/src/systemstate/observers.rs | 7 +- fuzzers/FRET/src/systemstate/report.rs | 51 +++++- fuzzers/FRET/src/systemstate/schedulers.rs | 19 ++- fuzzers/FRET/src/systemstate/stg.rs | 10 +- fuzzers/FRET/src/templates.rs | 159 ++++++++++++++++++ fuzzers/FRET/src/time/clock.rs | 20 ++- fuzzers/FRET/src/time/qemustate.rs | 63 +++++-- fuzzers/FRET/src/time/worst.rs | 49 ++++-- libafl_qemu/libafl_qemu_sys/src/systemmode.rs | 6 + libafl_qemu/src/emu/hooks.rs | 28 ++- 18 files changed, 462 insertions(+), 158 deletions(-) create mode 100644 fuzzers/FRET/src/templates.rs diff --git a/fuzzers/FRET/src/debug.rs b/fuzzers/FRET/src/debug.rs index e525edf095..18bb01378b 100644 --- a/fuzzers/FRET/src/debug.rs +++ b/fuzzers/FRET/src/debug.rs @@ -44,7 +44,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { if unsafe { counter } > 0 { unsafe { counter -= 1; } @@ -68,7 +68,7 @@ where testcase: &mut Testcase<::Input>, ) -> Result<(), Error> where - OT: ObserversTuple, + OT: ObserversTuple, EM: EventFirer, { testcase.metadata_map_mut().insert(DebugMetadata { val: true }); diff --git a/fuzzers/FRET/src/fuzzer.rs b/fuzzers/FRET/src/fuzzer.rs index 77a5c15db2..587aa48270 100644 --- a/fuzzers/FRET/src/fuzzer.rs +++ b/fuzzers/FRET/src/fuzzer.rs @@ -9,9 +9,8 @@ core_affinity::Cores, ownedref::OwnedMutSlice, rands::StdRand, shmem::{ShMemProv 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, SimplePrintingMonitor, SimpleRestartingEventManager, StdScheduledMutator}, schedulers::QueueScheduler, stages::StdMutationalStage, state::{HasCorpus, StdState}, Error, Evaluator }; -use libafl_qemu::edges::EDGES_MAP_SIZE_IN_USE; use libafl_qemu::{ -edges::{self, edges_map_mut_ptr, QemuEdgeCoverageHelper, MAX_EDGES_FOUND}, elf::EasyElf, emu::Emulator, GuestAddr, GuestPhysAddr, QemuExecutor, QemuExitReason, QemuFilterList, QemuHooks, Regs, StdInstrumentationFilter +elf::EasyElf, emu::Emulator, modules::{edges::{self}, FilterList}, GuestAddr, GuestPhysAddr, QemuExecutor, QemuExitReason, QemuHooks, Regs }; use rand::{SeedableRng, StdRng, Rng}; use crate::{ @@ -30,6 +29,7 @@ use crate::cli::set_env_from_config; use clap::Parser; use log; use rand::RngCore; +use crate::templates; // Constants ================================================================================ @@ -248,7 +248,7 @@ 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 : Vec<_> =isr_ranges.values().map(|x| x.clone()).collect(); -let denylist = QemuFilterList::DenyList(denylist); // do not count isr jumps, which are useless +let denylist = FilterList::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")] @@ -319,7 +319,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| { "if=none,format=qcow2,file=dummy.qcow2", ].into_iter().map(String::from).collect(); let env: Vec<(String, String)> = env::vars().collect(); - let qemu = Qemu::init(&args, &env).expect("Emulator creation failed"); + let qemu = Qemu::init(&args).expect("Emulator creation failed"); if let Some(main_addr) = main_addr { qemu.set_breakpoint(main_addr); @@ -343,7 +343,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| { let initial_snap = None; // The wrapped harness function, calling out to the LLVM-style harness - let mut harness = |input: &MultipartInput| { + let mut harness = |emulator: &mut Emulator<_, _, _, _, _>, state: &mut _, input: &MultipartInput| { unsafe { #[cfg(feature = "fuzz_int")] { @@ -369,7 +369,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| { // Note: I could not find a difference between write_mem and write_phys_mem for my usecase qemu.write_mem(input_addr, bytes); if let Some(s) = input_length_ptr { - qemu.write_mem(s, &len.to_le_bytes()) + qemu.write_mem(s, &len.to_le_bytes()); } qemu.run(); @@ -496,7 +496,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| { let qhelpers = (QemuEdgeCoverageHelper::new(denylist, QemuFilterList::None), qhelpers); let qhelpers = (QemuStateRestoreHelper::with_fast(initial_snap), qhelpers); - let mut hooks = QemuHooks::new(qemu.clone(),qhelpers); + let emulator = Emulator::empty().qemu(qemu).modules(qhelpers).build().unwrap(); let observer_list = tuple_list!(); #[cfg(feature = "observe_systemstate")] @@ -507,7 +507,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| { // Create a QEMU in-process executor let mut executor = QemuExecutor::new( - &mut hooks, + emulator, &mut harness, observer_list, &mut fuzzer, @@ -660,7 +660,7 @@ let 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 = Qemu::init(&args, &env).expect("Emu creation failed"); + let emu = Qemu::init(&args).expect("Emu creation failed"); if let Some(main_addr) = main_addr { emu.set_breakpoint(main_addr); // BREAKPOINT diff --git a/fuzzers/FRET/src/lib.rs b/fuzzers/FRET/src/lib.rs index cd494a25ca..9b1705ef7b 100644 --- a/fuzzers/FRET/src/lib.rs +++ b/fuzzers/FRET/src/lib.rs @@ -5,4 +5,6 @@ pub mod time; #[cfg(target_os = "linux")] pub mod systemstate; #[cfg(target_os = "linux")] -mod cli; \ No newline at end of file +mod cli; +#[cfg(target_os = "linux")] +pub mod templates; \ No newline at end of file diff --git a/fuzzers/FRET/src/main.rs b/fuzzers/FRET/src/main.rs index e23d359bc1..2498e834bb 100644 --- a/fuzzers/FRET/src/main.rs +++ b/fuzzers/FRET/src/main.rs @@ -7,6 +7,8 @@ mod time; mod systemstate; #[cfg(target_os = "linux")] mod cli; +#[cfg(target_os = "linux")] +mod templates; #[cfg(target_os = "linux")] pub fn main() { diff --git a/fuzzers/FRET/src/systemstate/feedbacks.rs b/fuzzers/FRET/src/systemstate/feedbacks.rs index 033cda1eef..229d4ac0a4 100644 --- a/fuzzers/FRET/src/systemstate/feedbacks.rs +++ b/fuzzers/FRET/src/systemstate/feedbacks.rs @@ -23,6 +23,8 @@ use super::FreeRTOSSystemStateMetadata; use super::observers::QemuSystemStateObserver; use std::borrow::Cow; +use libafl::prelude::StateInitializer; + //============================= Feedback /// Shared Metadata for a systemstateFeedback @@ -57,10 +59,14 @@ pub struct NovelSystemStateFeedback // known_traces: HashMap, } +impl StateInitializer for NovelSystemStateFeedback {} + impl Feedback for NovelSystemStateFeedback where S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata, S::Input: Default, + EM: EventFirer, + OT: ObserversTuple, { fn is_interesting( &mut self, @@ -71,9 +77,6 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, - OT: ObserversTuple, - S::Input: Default { let observer : &QemuSystemStateObserver = observers.match_name::>("systemstate") .expect("QemuSystemStateObserver not found"); @@ -126,7 +129,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, _manager: &mut EM, _observers: &OT, testcase: &mut Testcase<::Input>) -> 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)), @@ -170,9 +173,13 @@ pub struct DumpSystraceFeedback last_trace: Option>, } +impl StateInitializer for DumpSystraceFeedback {} + impl Feedback for DumpSystraceFeedback where S: State + UsesInput + MaybeHasClientPerfMonitor, + EM: EventFirer, + OT: ObserversTuple { fn is_interesting( &mut self, @@ -183,8 +190,6 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, - OT: ObserversTuple { if self.dumpfile.is_none() {return Ok(false)}; let observer = observers.match_name::>("systemstate") @@ -225,7 +230,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, _manager: &mut EM, _observers: &OT, _testcase: &mut Testcase<::Input>) -> 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 { @@ -277,10 +282,13 @@ pub struct SystraceErrorFeedback max_reports: Option, } +impl StateInitializer for SystraceErrorFeedback {} + impl Feedback for SystraceErrorFeedback where S: State + UsesInput + MaybeHasClientPerfMonitor, EM: EventFirer, + OT: ObserversTuple { fn is_interesting( &mut self, @@ -291,7 +299,6 @@ where _exit_kind: &ExitKind, ) -> Result where - OT: ObserversTuple { #[cfg(feature = "trace_stg")] { @@ -313,7 +320,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, _manager: &mut EM, _observers: &OT, _testcase: &mut I) -> Result<(), Error> { + fn append_metadata(&mut self, _state: &mut S, _manager: &mut EM, _observers: &OT, _testcase: &mut Testcase) -> Result<(), Error> { Ok(()) } diff --git a/fuzzers/FRET/src/systemstate/helpers.rs b/fuzzers/FRET/src/systemstate/helpers.rs index d5b529e0de..1370ef83b9 100644 --- a/fuzzers/FRET/src/systemstate/helpers.rs +++ b/fuzzers/FRET/src/systemstate/helpers.rs @@ -4,12 +4,14 @@ use hashbrown::HashSet; use libafl::prelude::ExitKind; use libafl::prelude::UsesInput; use libafl_qemu::elf::EasyElf; +use libafl_qemu::modules::NopAddressFilter; +use libafl_qemu::modules::NopPageFilter; use libafl_qemu::read_user_reg_unchecked; use libafl_qemu::GuestAddr; use libafl_qemu::GuestPhysAddr; use libafl_qemu::QemuHooks; use libafl_qemu::Hook; -use libafl_qemu::helpers::{QemuHelper, QemuHelperTuple}; +use libafl_qemu::modules::{EmulatorModule, EmulatorModuleTuple}; use libafl_qemu::sys::TCGTemp; use libafl_qemu::qemu::MemAccessInfo; @@ -22,6 +24,8 @@ use super::freertos::rtos_struct::List_Item_struct; use super::freertos::rtos_struct::*; use super::freertos; use super::CaptureEvent; +use libafl_qemu::EmulatorModules; +use libafl::prelude::ObserversTuple; @@ -156,41 +160,58 @@ impl QemuSystemStateHelper { } } -impl QemuHelper for QemuSystemStateHelper +impl EmulatorModule for QemuSystemStateHelper where - S: UsesInput, + S: UsesInput + Unpin, { - fn first_exec(&self, _hooks: &QemuHooks) + fn first_exec(&mut self, _emulator_modules: &mut EmulatorModules, _state: &mut S) where - QT: QemuHelperTuple, + ET: EmulatorModuleTuple, { // for wp in self.api_fn_addrs.keys() { - // _hooks.instruction(*wp, Hook::Function(exec_syscall_hook::), false); + // _hooks.instruction(*wp, Hook::Function(exec_syscall_hook::), false); // } for wp in self.isr_addrs.keys() { - _hooks.instruction(*wp, Hook::Function(exec_isr_hook::), false); + _emulator_modules.instructions(*wp, Hook::Function(exec_isr_hook::), false); } - _hooks.jmps(Hook::Function(gen_jmp_is_syscall::), Hook::Function(trace_jmp::)); + _emulator_modules.jmps(Hook::Function(gen_jmp_is_syscall::), Hook::Function(trace_jmp::)); #[cfg(feature = "trace_job_response_times")] - _hooks.instruction(self.job_done_addrs, Hook::Function(job_done_hook::), false); + _emulator_modules.instructions(self.job_done_addrs, Hook::Function(job_done_hook::), false); #[cfg(feature = "trace_reads")] - _hooks.reads(Hook::Function(gen_read_is_input::), Hook::Empty,Hook::Empty,Hook::Empty,Hook::Empty,Hook::Function(trace_reads::)); + _emulator_modules.reads(Hook::Function(gen_read_is_input::), Hook::Empty,Hook::Empty,Hook::Empty,Hook::Empty,Hook::Function(trace_reads::)); unsafe { INPUT_MEM = self.input_mem.clone() }; } // TODO: refactor duplicate code - fn pre_exec(&mut self, _emulator: libafl_qemu::Qemu, _input: &I) { + fn pre_exec( + &mut self, + _emulator_modules: &mut EmulatorModules, + _state: &mut S, + _input: &S::Input, + ) where + ET: EmulatorModuleTuple, + { unsafe { CURRENT_SYSTEMSTATE_VEC.clear(); JOBS_DONE.clear(); } } - fn post_exec(&mut self, emulator: libafl_qemu::Qemu, _input: &I, _observers: &mut OT, _exit_kind: &mut ExitKind) { - trigger_collection(&emulator,(0, 0), CaptureEvent::End, self); + fn post_exec( + &mut self, + _emulator_modules: &mut EmulatorModules, + _state: &mut S, + _input: &S::Input, + _observers: &mut OT, + _exit_kind: &mut ExitKind, + ) where + OT: ObserversTuple, + ET: EmulatorModuleTuple, + { + trigger_collection(&_emulator_modules.qemu(),(0, 0), CaptureEvent::End, self); unsafe { - let c = emulator.cpu_from_index(0); - let pc = c.read_reg::(15).unwrap(); + let c = _emulator_modules.qemu().cpu_from_index(0); + let pc = c.read_reg::(15).unwrap(); if CURRENT_SYSTEMSTATE_VEC.len() == 0 {return;} CURRENT_SYSTEMSTATE_VEC[CURRENT_SYSTEMSTATE_VEC.len()-1].edge = (pc,0); CURRENT_SYSTEMSTATE_VEC[CURRENT_SYSTEMSTATE_VEC.len()-1].capture_point = (CaptureEvent::End,"Breakpoint".to_string()); @@ -207,6 +228,26 @@ where CURRENT_SYSTEMSTATE_VEC.drain(..index); } } + + type ModuleAddressFilter = NopAddressFilter; + + type ModulePageFilter = NopPageFilter; + + fn address_filter(&self) -> &Self::ModuleAddressFilter { + todo!() + } + + fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + todo!() + } + + fn page_filter(&self) -> &Self::ModulePageFilter { + todo!() + } + + fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { + todo!() + } } fn read_freertos_list(systemstate : &mut RawFreeRTOSSystemState, emulator: &libafl_qemu::Qemu, target: GuestAddr) -> (freertos::List_t, bool) { @@ -341,57 +382,57 @@ fn trigger_collection(emulator: &libafl_qemu::Qemu, edge: (GuestAddr, GuestAddr) pub static mut JOBS_DONE : Vec<(u64, String)> = vec![]; pub fn job_done_hook( - hooks: &mut QemuHooks, + hooks: &mut EmulatorModules, _state: Option<&mut S>, _pc: GuestAddr, ) where S: UsesInput, - QT: QemuHelperTuple, + QT: EmulatorModuleTuple, { let emulator = hooks.qemu(); - let h = hooks.helpers().match_first_type::().expect("QemuSystemHelper not found in helper tupel"); - let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(emulator, h.tcb_addr); + let h = hooks.modules().match_first_type::().expect("QemuSystemHelper not found in helper tupel"); + let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(&emulator, h.tcb_addr); if curr_tcb_addr == 0 { return; }; - let current_tcb : TCB_t = freertos::emu_lookup::lookup(emulator,curr_tcb_addr); + let current_tcb : TCB_t = freertos::emu_lookup::lookup(&emulator,curr_tcb_addr); let tmp = unsafe {std::mem::transmute::<[i8; 10],[u8; 10]>(current_tcb.pcTaskName)}; let name : String = std::str::from_utf8(&tmp).expect("TCB name was not utf8").chars().filter(|x| *x != '\0').collect::(); - unsafe { JOBS_DONE.push((get_icount(emulator), name)); } + unsafe { JOBS_DONE.push((get_icount(&emulator), name)); } } //============================= Trace interrupt service routines pub fn exec_isr_hook( - hooks: &mut QemuHooks, + hooks: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, ) where S: UsesInput, - QT: QemuHelperTuple, + QT: EmulatorModuleTuple, { 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); + let h = hooks.modules().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); // println!("Exec ISR Call {:#x} {:#x} {}", src, pc, get_icount(emulator)); } //============================= Trace syscalls and returns pub fn gen_jmp_is_syscall( - hooks: &mut QemuHooks, + hooks: &mut EmulatorModules, _state: Option<&mut S>, src: GuestAddr, dest: GuestAddr, ) -> Option where S: UsesInput, - QT: QemuHelperTuple, + QT: EmulatorModuleTuple, { - if let Some(h) = hooks.helpers().match_first_type::() { + if let Some(h) = hooks.modules().match_first_type::() { if h.app_range.contains(&src) && !h.app_range.contains(&dest) && in_any_range(&h.isr_ranges,src).is_none() { if let Some(_) = in_any_range(&h.api_fn_ranges,dest) { // println!("New jmp {:x} {:x}", src, dest); @@ -415,18 +456,18 @@ where } pub fn trace_jmp( - hooks: &mut QemuHooks, + hooks: &mut EmulatorModules, _state: Option<&mut S>, src: GuestAddr, mut dest: GuestAddr, id: u64 ) where S: UsesInput, - QT: QemuHelperTuple, + QT: EmulatorModuleTuple, { - let h = hooks.helpers().match_first_type::().expect("QemuSystemHelper not found in helper tupel"); + let h = hooks.modules().match_first_type::().expect("QemuSystemHelper not found in helper tupel"); let emulator = hooks.qemu(); if id == 1 { // API call - trigger_collection(emulator, (src, dest), CaptureEvent::APIStart, h); + trigger_collection(&emulator, (src, dest), CaptureEvent::APIStart, h); // println!("Exec API Call {:#x} {:#x} {}", src, dest, get_icount(emulator)); } else if id == 2 { // API return // Ignore returns to other APIs or ISRs. We only account for the first call depth of API calls from user space. @@ -436,17 +477,17 @@ where edge.0=in_any_range(&h.api_fn_ranges, src).unwrap().start; edge.1=dest; - trigger_collection(emulator, edge, CaptureEvent::APIEnd, h); + trigger_collection(&emulator, edge, CaptureEvent::APIEnd, h); // println!("Exec API Return Edge {:#x} {:#x} {}", src, dest, get_icount(emulator)); } } else if id == 3 { // ISR return - dest = read_rec_return_stackframe(emulator, dest); + dest = read_rec_return_stackframe(&emulator, dest); let mut edge = (0, 0); edge.0=in_any_range(&h.isr_ranges, src).unwrap().start; edge.1=dest; - trigger_collection(emulator, edge, CaptureEvent::ISREnd, h); + trigger_collection(&emulator, edge, CaptureEvent::ISREnd, h); // println!("Exec ISR Return Edge {:#x} {:#x} {}", src, dest, get_icount(emulator)); } } @@ -454,7 +495,7 @@ where //============================= Read Hooks #[allow(unused)] pub fn gen_read_is_input( - hooks: &mut QemuHooks, + hooks: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, _addr: *mut TCGTemp, @@ -462,9 +503,9 @@ pub fn gen_read_is_input( ) -> Option where S: UsesInput, - QT: QemuHelperTuple, + QT: EmulatorModuleTuple, { - if let Some(h) = hooks.helpers().match_first_type::() { + if let Some(h) = hooks.modules().match_first_type::() { if h.app_range.contains(&pc) { // println!("gen_read {:x}", pc); return Some(1); @@ -478,7 +519,7 @@ static mut MEM_READ : Option> = None; #[allow(unused)] pub fn trace_reads( - hooks: &mut QemuHooks, + hooks: &mut EmulatorModules, _state: Option<&mut S>, _id: u64, addr: GuestAddr, @@ -486,7 +527,7 @@ pub fn trace_reads( ) where S: UsesInput, - QT: QemuHelperTuple, + QT: EmulatorModuleTuple, { if unsafe { INPUT_MEM.contains(&addr) } { let emulator = hooks.qemu(); diff --git a/fuzzers/FRET/src/systemstate/mod.rs b/fuzzers/FRET/src/systemstate/mod.rs index 47bdf8e1a1..6195208020 100644 --- a/fuzzers/FRET/src/systemstate/mod.rs +++ b/fuzzers/FRET/src/systemstate/mod.rs @@ -64,7 +64,7 @@ pub struct RawFreeRTOSSystemState { capture_point: (CaptureEvent,String), mem_reads: Vec<(u32, u8)> } -/// List of system state dumps from QemuHelpers +/// List of system state dumps from EmulatorModules static mut CURRENT_SYSTEMSTATE_VEC: Vec = vec![]; /// A reduced version of freertos::TCB_t diff --git a/fuzzers/FRET/src/systemstate/mutational.rs b/fuzzers/FRET/src/systemstate/mutational.rs index 109acd2da2..f861032899 100644 --- a/fuzzers/FRET/src/systemstate/mutational.rs +++ b/fuzzers/FRET/src/systemstate/mutational.rs @@ -9,7 +9,7 @@ use libafl_bolts::{rands::{ random_seed, Rand, StdRand }, Named}; use libafl::{ - common::{HasMetadata, HasNamedMetadata}, corpus::{self, Corpus}, events::{Event, EventFirer, EventProcessor, LogSeverity}, fuzzer::Evaluator, inputs::{HasMutatorBytes, HasTargetBytes, Input, MultipartInput}, mark_feature_time, {new_hash_feedback, AggregatorOps, CorpusId, MutationResult, Mutator, UserStats, UserStatsValue, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error + common::{HasMetadata, HasNamedMetadata}, corpus::{self, Corpus, HasCurrentCorpusId, Testcase}, events::{Event, EventFirer, EventProcessor, LogSeverity}, fuzzer::Evaluator, inputs::{HasMutatorBytes, HasTargetBytes, Input, MultipartInput}, mark_feature_time, prelude::{new_hash_feedback, AggregatorOps, CorpusId, MutationResult, Mutator, UserStats, UserStatsValue, UsesInput}, stages::Stage, start_timer, state::{HasCorpus, HasRand, MaybeHasClientPerfMonitor, UsesState}, Error }; use libafl::prelude::State; use petgraph::{graph::NodeIndex, graph::{self, DiGraph}}; @@ -163,16 +163,15 @@ where } } -impl Stage for InterruptShiftStage +impl Stage for InterruptShiftStage where - E: UsesState, - EM: UsesState, + E: UsesState, + EM: UsesState, + Z: Evaluator, + S: State> + HasRand + HasCorpus + HasCurrentTestcase + HasMetadata + HasNamedMetadata, + <::State as HasCorpus>::Corpus: Corpus, //delete me EM: EventFirer, - Z: Evaluator, - Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand + HasMetadata + HasNamedMetadata, - ::Input: Input, - Z::State: UsesInput>, - I: HasMutatorBytes + Default + I: Default + Input + HasMutatorBytes, { fn perform( &mut self, @@ -180,7 +179,8 @@ where executor: &mut E, state: &mut Self::State, manager: &mut EM - ) -> Result<(), Error> { + ) -> Result<(), Error> + where ::State: HasCorpus { if self.interrup_config.len() == 0 {return Ok(());} // configuration implies no interrupts let mut myrand = StdRand::new(); myrand.set_seed(state.rand_mut().next()); @@ -203,10 +203,10 @@ where let name = format!("isr_{}_times", interrup_config.0); // manager.log(state, LogSeverity::Info, format!("Mutation {}/{}", loopbound, loopcount))?; - let curr_case = state.current_testcase()?; + let curr_case : std::cell::Ref>> = state.current_testcase()?; let curr_input = curr_case.input().as_ref().unwrap(); - let mut new_input = curr_input.clone(); + let mut new_input : MultipartInput = curr_input.clone(); let new_interrupt_part : &mut I = if new_input.parts_by_name(&name).next().is_some() { new_input.parts_by_name_mut(&name).next().unwrap() } else { @@ -521,7 +521,9 @@ where Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand + HasMetadata + HasNamedMetadata, ::Input: Input, Z::State: UsesInput>, - I: HasMutatorBytes + Default + I: HasMutatorBytes + Default, + Z::State: HasCurrentTestcase+HasCorpus+HasCurrentCorpusId, + ::Corpus: Corpus> { fn perform( &mut self, @@ -537,7 +539,7 @@ where let current_case = state.current_testcase()?; let old_input = current_case.input().as_ref().unwrap(); - let mut new_input = old_input.clone(); + let mut new_input : MultipartInput = old_input.clone(); let new_bytes = new_input.parts_by_name_mut("bytes").next().expect("bytes not found in multipart input").1.bytes_mut(); // dbg!(current_case.metadata_map()); // eprintln!("Run mutator {}", current_case.metadata_map().get::().is_some()); diff --git a/fuzzers/FRET/src/systemstate/observers.rs b/fuzzers/FRET/src/systemstate/observers.rs index 9934b3a99d..f92593ddfb 100644 --- a/fuzzers/FRET/src/systemstate/observers.rs +++ b/fuzzers/FRET/src/systemstate/observers.rs @@ -49,10 +49,11 @@ pub struct QemuSystemStateObserver name: Cow<'static, str>, } -impl Observer<::Input, S> for QemuSystemStateObserver<::Input> +impl Observer for QemuSystemStateObserver where - S: UsesInput + HasMetadata, - S::Input: Default + S: UsesInput + HasMetadata, + S::Input: Default, + I: Clone, { #[inline] fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { diff --git a/fuzzers/FRET/src/systemstate/report.rs b/fuzzers/FRET/src/systemstate/report.rs index 439051906d..db5579bb38 100644 --- a/fuzzers/FRET/src/systemstate/report.rs +++ b/fuzzers/FRET/src/systemstate/report.rs @@ -7,8 +7,9 @@ use libafl_bolts::current_time; use itertools::Itertools; use libafl::{ - corpus::{Corpus, HasCurrentCorpusId}, events::EventFirer, schedulers::minimizer::TopRatedsMetadata, RemovableScheduler, schedulers::minimizer::IsFavoredMetadata, stages::Stage, state::{HasCorpus, HasImported, UsesState}, Error, HasMetadata, HasScheduler + corpus::{Corpus, HasCurrentCorpusId}, events::EventFirer, schedulers::minimizer::TopRatedsMetadata, schedulers::RemovableScheduler, schedulers::minimizer::IsFavoredMetadata, stages::Stage, state::{HasCorpus, HasImported, UsesState}, Error, HasMetadata, HasScheduler }; +use libafl::prelude::UsesInput; use libafl::{ events::Event, monitors::{AggregatorOps, UserStats, UserStatsValue}, @@ -20,6 +21,22 @@ use libafl::prelude::mutational::MUTATION_STAGE_ITER; use libafl::prelude::mutational::MUTATION_STAGE_RETRY; use libafl::prelude::mutational::MUTATION_STAGE_SUCCESS; +use libafl::HasNamedMetadata; +use libafl::prelude::Feedback; +use libafl::prelude::HasMaxSize; +use libafl::prelude::HasSolutions; +use libafl::prelude::HasExecutions; +use std::hash::Hash; +use libafl_bolts::HasLen; +use libafl::prelude::mutational::MutatedTransform; +use libafl::prelude::FeedbackFactory; +use serde::Serialize; +use libafl::prelude::ObserversTuple; +use libafl::prelude::HasObservers; +use libafl::HasFeedback; +use libafl::ExecutesInput; +use libafl::ExecutionProcessor; + /// The [`AflStatsStage`] is a simple stage that computes and reports some stats. #[derive(Debug, Clone)] pub struct SchedulerStatsStage { @@ -37,13 +54,35 @@ where type State = E::State; } -impl Stage for SchedulerStatsStage +// impl Stage for SchedulerStatsStage +// where +// E: UsesState, +// EM: UsesState, +// Z: UsesState, +// Self::State: HasNamedMetadata, +// // E: UsesState, +// // EM: EventFirer, +// // Z: UsesState + HasScheduler, +// // ::Scheduler: UsesState+RemovableScheduler<<::Scheduler as UsesInput>::Input, Self::State>, +// // Self::State: HasImported + HasCorpus + HasMetadata, +// // ::State: HasMetadata+HasImported+UsesState, +// { +impl Stage for SchedulerStatsStage where - E: UsesState, + Z: HasScheduler + ExecutionProcessor + ExecutesInput + HasFeedback, + Z::Scheduler: RemovableScheduler, + E: HasObservers + UsesState, + E::Observers: ObserversTuple + Serialize, EM: EventFirer, - Z: UsesState + HasScheduler, - ::Scheduler: RemovableScheduler, - Self::State: HasImported + HasCorpus + HasMetadata, + // FF: FeedbackFactory, + // F: Feedback, + Self::Input: MutatedTransform + Clone, + Z::State: + HasMetadata + HasExecutions + HasSolutions + HasCorpus + HasMaxSize + HasNamedMetadata, + Z::Feedback: Feedback, + // M: Mutator, + // IP: MutatedTransformPost + Clone, + <::State as HasCorpus>::Corpus: Corpus, // delete me { fn perform( &mut self, diff --git a/fuzzers/FRET/src/systemstate/schedulers.rs b/fuzzers/FRET/src/systemstate/schedulers.rs index 117a17f76c..b7fb9598ab 100644 --- a/fuzzers/FRET/src/systemstate/schedulers.rs +++ b/fuzzers/FRET/src/systemstate/schedulers.rs @@ -45,9 +45,9 @@ where type State = CS::State; } -impl Scheduler for LongestTraceScheduler +impl Scheduler for LongestTraceScheduler where - CS: UsesState + Scheduler, + CS: UsesState + Scheduler, CS::State: HasCorpus + HasMetadata + HasRand, { /// Add an entry to the corpus and return its index @@ -98,7 +98,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 as usize) > l + state.rand_mut().below(std::num::NonZero::new(m as usize+1).unwrap()) > l } && state.rand_mut().coinflip(self.skip_non_favored_prob) { idx = self.base.next(state)?; @@ -108,7 +108,7 @@ where fn set_current_scheduled( &mut self, - state: &mut <::State as UsesInput>::Input, + state: &mut ::State, next_id: Option, ) -> Result<(), Error> { self.base.set_current_scheduled(state, next_id) @@ -117,7 +117,7 @@ where impl LongestTraceScheduler where - CS: UsesState + Scheduler, + CS: UsesState + Scheduler, CS::State: HasCorpus + HasMetadata + HasRand, { pub fn get_update_trace_length(&self, state: &mut CS::State, par: usize) -> u64 { @@ -173,6 +173,7 @@ where impl Scheduler for GenerationScheduler where S: State + HasCorpus + HasMetadata, + <::Corpus as libafl::corpus::Corpus>::Input: Clone, { /// get first element in current gen, /// if current_gen is empty, swap lists, sort by FavFactor, take top k and return first @@ -247,7 +248,7 @@ where state: &mut S, next_id: Option, ) -> Result<(), Error> { - self.base.set_current_scheduled(state, next_id) + Ok(()) } // fn on_replace( // &self, @@ -276,7 +277,7 @@ where // } } -impl RemovableScheduler for GenerationScheduler +impl RemovableScheduler for GenerationScheduler where S: State + HasCorpus + HasMetadata, { @@ -285,7 +286,7 @@ where &mut self, state: &mut ::State, idx: CorpusId, - testcase: &Testcase<<::State as UsesInput>::Input>, + testcase: &Testcase, ) -> Result<(), Error> { Ok(()) } @@ -295,7 +296,7 @@ where &mut self, state: &mut ::State, idx: CorpusId, - testcase: &Option::State as UsesInput>::Input>>, + testcase: &Option>, ) -> Result<(), Error> { Ok(()) } diff --git a/fuzzers/FRET/src/systemstate/stg.rs b/fuzzers/FRET/src/systemstate/stg.rs index 781a35320a..5bf5e575e3 100644 --- a/fuzzers/FRET/src/systemstate/stg.rs +++ b/fuzzers/FRET/src/systemstate/stg.rs @@ -21,7 +21,6 @@ use libafl::state::MaybeHasClientPerfMonitor; use libafl::feedbacks::Feedback; use libafl_bolts::Named; use libafl::Error; -use libafl_qemu::edges::EDGES_MAP_SIZE_IN_USE; use hashbrown::HashMap; use libafl::{executors::ExitKind, observers::ObserversTuple, common::HasMetadata}; use serde::{Deserialize, Serialize}; @@ -300,8 +299,8 @@ impl HasRefCnt for STGNodeMetadata { libafl_bolts::impl_serdeany!(STGNodeMetadata); -pub type GraphMaximizerCorpusScheduler = - MinimizerScheduler::State>,STGNodeMetadata,O>; +pub type GraphMaximizerCorpusScheduler = + MinimizerScheduler,STGNodeMetadata,O>; // AI generated, human verified /// Count the occurrences of each element in a vector, assumes the vector is sorted @@ -336,7 +335,8 @@ where //============================= Graph Feedback -pub static mut STG_MAP: [u16; EDGES_MAP_SIZE_IN_USE] = [0; EDGES_MAP_SIZE_IN_USE]; +pub const STG_MAP_SIZE: usize = 1<<20; +pub static mut STG_MAP: [u16; STG_MAP_SIZE] = [0; STG_MAP_SIZE]; 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()) @@ -531,7 +531,7 @@ where S: State + UsesInput + MaybeHasClientPerfMonitor + HasNamedMetadata, S::Input: Default, EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { #[allow(clippy::wrong_self_convention)] fn is_interesting( diff --git a/fuzzers/FRET/src/templates.rs b/fuzzers/FRET/src/templates.rs new file mode 100644 index 0000000000..ae0c1974ca --- /dev/null +++ b/fuzzers/FRET/src/templates.rs @@ -0,0 +1,159 @@ +use libafl::{events::EventFirer, inputs::UsesInput, prelude::{Feedback, ObserversTuple, StateInitializer}}; +use libafl_bolts::Named; +use libafl_qemu::{modules::EmulatorModule, EmulatorModules}; +use std::borrow::Cow; +use libafl::prelude::*; +use libafl_qemu::modules::*; +use libafl_qemu::*; + +//============================================== Feedback + +/// Example Feedback for type correctness +#[derive(Clone, Debug, Default)] +pub struct MinimalFeedback { + /// The name + name: Cow<'static, str>, +} + +impl StateInitializer for MinimalFeedback {} + +impl Feedback for MinimalFeedback +where + S: State + UsesInput, + EM: EventFirer, + OT: ObserversTuple, +{ + #[allow(clippy::wrong_self_convention)] + fn is_interesting( + &mut self, + state: &mut S, + manager: &mut EM, + input: &I, + observers: &OT, + exit_kind: &ExitKind, + ) -> Result { + Ok(false) + } +} + +impl Named for MinimalFeedback { + #[inline] + fn name(&self) -> &Cow<'static, str> { + &self.name + } +} + +//============================================== TestcaseScore + +pub struct MinimalTestcaseScore {} + +impl TestcaseScore for MinimalTestcaseScore +where + S: HasMetadata + HasCorpus, +{ + fn compute( + _state: &S, + entry: &mut Testcase<::Input>, + ) -> Result { + Ok(0 as f64) + } +} + +//============================================== EmulatorModule + +#[derive(Debug)] +pub struct MinimalEmulatorModule { + af: NopAddressFilter, + pf: NopPageFilter +} + +impl EmulatorModule for MinimalEmulatorModule +where + S: UsesInput, +{ + const HOOKS_DO_SIDE_EFFECTS: bool = true; + type ModuleAddressFilter = NopAddressFilter; + type ModulePageFilter = NopPageFilter; + + + /// Hook run **before** QEMU is initialized. + /// This is always run when Emulator gets initialized, in any case. + /// Install here hooks that should be alive for the whole execution of the VM, even before QEMU gets initialized. + fn pre_qemu_init(&self, _emulator_hooks: &mut EmulatorHooks) + where + ET: EmulatorModuleTuple, + { + } + + /// Hook run **after** QEMU is initialized. + /// This is always run when Emulator gets initialized, in any case. + /// Install here hooks that should be alive for the whole execution of the VM, after QEMU gets initialized. + fn post_qemu_init(&self, _emulator_modules: &mut EmulatorModules) + where + ET: EmulatorModuleTuple, + { + } + + /// Run once just before fuzzing starts. + /// This call can be delayed to the point at which fuzzing is supposed to start. + /// It is mostly used to avoid running hooks during VM initialization, either + /// because it is useless or it would produce wrong results. + fn first_exec(&mut self, _emulator_modules: &mut EmulatorModules, _state: &mut S) + where + ET: EmulatorModuleTuple, + { + } + + /// Run before a new fuzzing run starts. + /// On the first run, it is executed after [`Self::first_exec`]. + fn pre_exec( + &mut self, + _emulator_modules: &mut EmulatorModules, + _state: &mut S, + _input: &S::Input, + ) where + ET: EmulatorModuleTuple, + { + } + + /// Run after a fuzzing run ends. + fn post_exec( + &mut self, + _emulator_modules: &mut EmulatorModules, + _state: &mut S, + _input: &S::Input, + _observers: &mut OT, + _exit_kind: &mut ExitKind, + ) where + OT: ObserversTuple, + ET: EmulatorModuleTuple, + { + } + + /// # Safety + /// + /// This is getting executed in a signal handler. + unsafe fn on_crash(&mut self) {} + + /// # Safety + /// + /// This is getting executed in a signal handler. + unsafe fn on_timeout(&mut self) {} + + fn address_filter(&self) -> &Self::ModuleAddressFilter { + &self.af + } + fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + &mut self.af + } + fn update_address_filter(&mut self, qemu: Qemu, filter: Self::ModuleAddressFilter) { + } + + fn page_filter(&self) -> &Self::ModulePageFilter { + &self.pf + } + + fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { + &mut self.pf + } +} \ No newline at end of file diff --git a/fuzzers/FRET/src/time/clock.rs b/fuzzers/FRET/src/time/clock.rs index 4ba4bacaa4..0347decea1 100644 --- a/fuzzers/FRET/src/time/clock.rs +++ b/fuzzers/FRET/src/time/clock.rs @@ -43,6 +43,8 @@ pub fn tick_to_time(ticks: u64) -> Duration { pub fn tick_to_ms(ticks: u64) -> f32 { (Duration::from_nanos(ticks << QEMU_ICOUNT_SHIFT).as_micros() as f32/10.0).round()/100.0 } +use libafl::prelude::StateInitializer; + //========== Metadata #[derive(Debug, SerdeAny, Serialize, Deserialize)] @@ -216,10 +218,14 @@ pub struct ClockTimeFeedback { name: Cow<'static, str>, } +impl StateInitializer for ClockTimeFeedback {} + impl Feedback for ClockTimeFeedback where S: State + UsesInput + MaybeHasClientPerfMonitor + HasMetadata, - ::Input: Default + ::Input: Default, + EM: EventFirer, + OT: ObserversTuple, { #[allow(clippy::wrong_self_convention)] fn is_interesting( @@ -231,8 +237,6 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, - OT: ObserversTuple, { #[cfg(feature="trace_job_response_times")] { @@ -255,7 +259,7 @@ where _state: &mut S, _manager: &mut EM, _observers: &OT, - testcase: &mut Testcase<::Input>, + testcase: &mut Testcase, ) -> Result<(), Error> { *testcase.exec_time_mut() = self.exec_time; self.exec_time = None; @@ -305,9 +309,13 @@ pub struct QemuClockIncreaseFeedback { name: Cow<'static, str>, } +impl StateInitializer for QemuClockIncreaseFeedback {} + impl Feedback for QemuClockIncreaseFeedback where S: State + UsesInput + HasNamedMetadata + MaybeHasClientPerfMonitor + Debug, + EM: EventFirer, + OT: ObserversTuple, { fn is_interesting( &mut self, @@ -318,8 +326,6 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, - OT: ObserversTuple, { let observer = _observers.match_name::("clock") .expect("QemuClockObserver not found"); @@ -337,7 +343,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, _manager: &mut EM, _observers: &OT, _testcase: &mut Testcase<::Input>) -> 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(()) } diff --git a/fuzzers/FRET/src/time/qemustate.rs b/fuzzers/FRET/src/time/qemustate.rs index b3a4741bce..10a548fec0 100644 --- a/fuzzers/FRET/src/time/qemustate.rs +++ b/fuzzers/FRET/src/time/qemustate.rs @@ -1,10 +1,14 @@ use libafl::prelude::UsesInput; +use libafl_qemu::modules::NopAddressFilter; +use libafl_qemu::modules::NopPageFilter; use libafl_qemu::sys::CPUArchState; use libafl_qemu::FastSnapshotPtr; -use libafl_qemu::QemuHelper; -use libafl_qemu::QemuHelperTuple; +use libafl_qemu::modules::EmulatorModule; +use libafl_qemu::modules::EmulatorModuleTuple; use libafl::executors::ExitKind; use libafl_qemu::QemuHooks; +use libafl_qemu::EmulatorModules; +use libafl::prelude::ObserversTuple; // TODO be thread-safe maybe with https://amanieu.github.io/thread_local-rs/thread_local/index.html #[derive(Debug)] @@ -39,36 +43,43 @@ impl Default for QemuStateRestoreHelper { } } -impl QemuHelper for QemuStateRestoreHelper +impl EmulatorModule for QemuStateRestoreHelper where S: UsesInput, { const HOOKS_DO_SIDE_EFFECTS: bool = true; + type ModuleAddressFilter = NopAddressFilter; + type ModulePageFilter = NopPageFilter; - fn init_hooks(&self, _hooks: &QemuHooks) - where - QT: QemuHelperTuple, + fn post_exec( + &mut self, + _emulator_modules: &mut EmulatorModules, + _state: &mut S, + _input: &S::Input, + _observers: &mut OT, + _exit_kind: &mut ExitKind, + ) where + OT: ObserversTuple, + ET: EmulatorModuleTuple, { - } - - fn first_exec(&self, _hooks: &QemuHooks) - where - QT: QemuHelperTuple, - { - } - - fn post_exec(&mut self, _emulator: libafl_qemu::Qemu, _input: &I, _observers: &mut OT, _exit_kind: &mut ExitKind) { // unsafe { println!("snapshot post {}",emu::icount_get_raw()) }; } - fn pre_exec(&mut self, emulator: libafl_qemu::Qemu, _input: &I) { + fn pre_exec( + &mut self, + _emulator_modules: &mut EmulatorModules, + _state: &mut S, + _input: &S::Input, + ) where + ET: EmulatorModuleTuple, + { // 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) => unsafe { emulator.restore_fast_snapshot(s) }, - None => {self.fastsnap = Some(emulator.create_fast_snapshot(true));}, + Some(s) => unsafe { _emulator_modules.qemu().restore_fast_snapshot(s) }, + None => {self.fastsnap = Some(_emulator_modules.qemu().create_fast_snapshot(true));}, } #[cfg(not(feature = "snapshot_fast"))] if !self.has_snapshot { @@ -94,4 +105,20 @@ where // unsafe { println!("snapshot pre {}",emu::icount_get_raw()) }; } + + fn address_filter(&self) -> &Self::ModuleAddressFilter { + todo!() + } + + fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + todo!() + } + + fn page_filter(&self) -> &Self::ModulePageFilter { + todo!() + } + + fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { + todo!() + } } \ No newline at end of file diff --git a/fuzzers/FRET/src/time/worst.rs b/fuzzers/FRET/src/time/worst.rs index a31d789d6d..fa8d70bb8a 100644 --- a/fuzzers/FRET/src/time/worst.rs +++ b/fuzzers/FRET/src/time/worst.rs @@ -18,7 +18,7 @@ use libafl::prelude::State; use libafl::inputs::Input; use libafl::feedbacks::Feedback; use libafl::common::HasMetadata; -use libafl_qemu::edges::QemuEdgesMapMetadata; +use libafl_qemu::modules::edges::EdgeCoverageModule; use libafl::observers::MapObserver; use serde::{Deserialize, Serialize}; use std::cmp; @@ -39,6 +39,8 @@ use libafl::{ use crate::time::clock::QemuClockObserver; use crate::systemstate::FreeRTOSSystemStateMetadata; +use libafl::prelude::StateInitializer; + use std::borrow::Cow; //=========================== Scheduler @@ -59,7 +61,7 @@ impl TestcaseScore for MaxTimeFavFactor where S: HasCorpus + HasMetadata, { - fn compute(state: &S, entry: &mut Testcase<::Input>) -> Result { + fn compute(state: &S, entry: &mut Testcase<::Input> ) -> Result { // TODO maybe enforce entry.exec_time().is_some() let et = entry.exec_time().expect("testcase.exec_time is needed for scheduler"); let tns : i64 = et.as_nanos().try_into().expect("failed to convert time"); @@ -104,23 +106,25 @@ pub struct SortedFeedback { name: Cow<'static, str> } +impl StateInitializer for SortedFeedback {} + impl Feedback for SortedFeedback where - S: State + UsesInput + MaybeHasClientPerfMonitor, + S: State + UsesInput + MaybeHasClientPerfMonitor, S::Input: HasTargetBytes, + EM: EventFirer, + OT: ObserversTuple, { #[allow(clippy::wrong_self_convention)] fn is_interesting( &mut self, _state: &mut S, _manager: &mut EM, - _input: &I, + _input: &S::Input, _observers: &OT, _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, - OT: ObserversTuple, { let t = _input.target_bytes(); let tmp = t.as_slice(); @@ -178,9 +182,13 @@ pub struct ExecTimeReachedFeedback target_time: u64, } +impl StateInitializer for ExecTimeReachedFeedback {} + impl Feedback for ExecTimeReachedFeedback where S: State + UsesInput + MaybeHasClientPerfMonitor, + EM: EventFirer, + OT: ObserversTuple, { #[allow(clippy::wrong_self_convention)] fn is_interesting( @@ -192,8 +200,6 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, - OT: ObserversTuple, { let observer = observers.match_name::("clock") .expect("QemuClockObserver not found"); @@ -228,9 +234,13 @@ pub struct ExecTimeCollectorFeedback name: Cow<'static, str> } +impl StateInitializer for ExecTimeCollectorFeedback {} + impl Feedback for ExecTimeCollectorFeedback where S: State + UsesInput + MaybeHasClientPerfMonitor, + EM: EventFirer, + OT: ObserversTuple, { #[allow(clippy::wrong_self_convention)] fn is_interesting( @@ -242,8 +252,6 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, - OT: ObserversTuple, { let observer = observers.match_name::("clock") .expect("QemuClockObserver not found"); @@ -300,9 +308,13 @@ pub struct ExecTimeIncFeedback last_is_longest: bool } +impl StateInitializer for ExecTimeIncFeedback {} + impl Feedback for ExecTimeIncFeedback where S: State + UsesInput + MaybeHasClientPerfMonitor, + EM: EventFirer, + OT: ObserversTuple, { #[allow(clippy::wrong_self_convention)] fn is_interesting( @@ -314,8 +326,6 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, - OT: ObserversTuple, { let observer = observers.match_name::("clocktime") .expect("QemuClockObserver not found"); @@ -333,7 +343,7 @@ where _state: &mut S, _manager: &mut EM, observers: &OT, - testcase: &mut Testcase<::Input>, + testcase: &mut Testcase, ) -> Result<(), Error> { #[cfg(feature = "feed_afl")] if self.last_is_longest { @@ -370,9 +380,14 @@ pub struct AlwaysTrueFeedback name: Cow<'static, str> } +impl StateInitializer for AlwaysTrueFeedback {} + impl Feedback for AlwaysTrueFeedback + where S: State + UsesInput + MaybeHasClientPerfMonitor, + EM: EventFirer, + OT: ObserversTuple, { #[allow(clippy::wrong_self_convention)] fn is_interesting( @@ -384,8 +399,6 @@ where _exit_kind: &ExitKind, ) -> Result where - EM: EventFirer, - OT: ObserversTuple, { Ok(true) } @@ -425,11 +438,15 @@ where phantom: PhantomData, } +// impl UsesState for TimeProbMassScheduler { +// type State = S; +// } + impl TestcaseScore for TimeProbFactor where S: HasCorpus + HasMetadata, { - fn compute(_state: &S, entry: &mut Testcase<::Input>) -> Result { + fn compute(_state: &S, entry: &mut Testcase<::Input>) -> Result { // TODO maybe enforce entry.exec_time().is_some() let et = entry.exec_time().expect("testcase.exec_time is needed for scheduler"); let tns : i64 = et.as_nanos().try_into().expect("failed to convert time"); diff --git a/libafl_qemu/libafl_qemu_sys/src/systemmode.rs b/libafl_qemu/libafl_qemu_sys/src/systemmode.rs index e69de29bb2..dbf4ef7916 100644 --- a/libafl_qemu/libafl_qemu_sys/src/systemmode.rs +++ b/libafl_qemu/libafl_qemu_sys/src/systemmode.rs @@ -0,0 +1,6 @@ +use paste::paste; +use crate::extern_c_checked; + +extern_c_checked!( + pub fn icount_get_raw() -> u64; +); \ No newline at end of file diff --git a/libafl_qemu/src/emu/hooks.rs b/libafl_qemu/src/emu/hooks.rs index 93e02d56be..878c960ca0 100644 --- a/libafl_qemu/src/emu/hooks.rs +++ b/libafl_qemu/src/emu/hooks.rs @@ -16,6 +16,7 @@ use crate::qemu::{ CrashHookClosure, CrashHookFn, PostSyscallHookClosure, PostSyscallHookFn, PreSyscallHookClosure, PreSyscallHookFn, }; +use crate::{JmpExecHook, JmpGenHook}; use crate::{ cpu_run_post_exec_hook_wrapper, cpu_run_pre_exec_hook_wrapper, modules::{EmulatorModule, EmulatorModuleTuple}, @@ -765,23 +766,8 @@ where pub fn jmps( &mut self, - generation_hook: Hook< - fn(&mut Self, Option<&mut S>, src: GuestAddr, dest: GuestAddr) -> Option, - Box< - dyn for<'a> FnMut( - &'a mut Self, - Option<&'a mut S>, - GuestAddr, - GuestAddr, - ) -> Option, - >, - extern "C" fn(*const (), src: GuestAddr, dest: GuestAddr) -> u64, - >, - execution_hook: Hook< - fn(&mut Self, Option<&mut S>, src: GuestAddr, dest: GuestAddr, id: u64), - Box FnMut(&'a mut Self, Option<&'a mut S>, GuestAddr, GuestAddr, u64)>, - extern "C" fn(*const (), src: GuestAddr, dest: GuestAddr, id: u64), - >, + generation_hook: JmpGenHook, + execution_hook: JmpExecHook, ) -> JmpHookId { unsafe { let gen = get_raw_hook!( @@ -1162,6 +1148,14 @@ where ) -> NewThreadHookId { self.hooks.thread_creation_closure(hook) } + + pub fn jmps( + &mut self, + generation_hook: JmpGenHook, + execution_hook: JmpExecHook, + ) -> JmpHookId { + self.hooks.jmps(generation_hook, execution_hook) + } } impl EmulatorModules