diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index d3013dff2b..2d37cd3d17 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -360,8 +360,8 @@ jobs: # Full-system - ./fuzzers/full_system/qemu_baremetal - # - ./fuzzers/full_system/qemu_linux_kernel - #- ./fuzzers/full_system/qemu_linux_process + - ./fuzzers/full_system/qemu_linux_kernel + - ./fuzzers/full_system/qemu_linux_process runs-on: [ self-hosted, qemu ] container: registry.gitlab.com/qemu-project/qemu/qemu/ubuntu2204:latest diff --git a/fuzzers/binary_only/fuzzbench_fork_qemu/src/fuzzer.rs b/fuzzers/binary_only/fuzzbench_fork_qemu/src/fuzzer.rs index fa10f654f3..3f367dfcab 100644 --- a/fuzzers/binary_only/fuzzbench_fork_qemu/src/fuzzer.rs +++ b/fuzzers/binary_only/fuzzbench_fork_qemu/src/fuzzer.rs @@ -327,7 +327,7 @@ fn fuzz( let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); // The wrapped harness function, calling out to the LLVM-style harness - let mut harness = |_emulator: &mut Emulator<_, _, _, _, _>, input: &BytesInput| { + let mut harness = |_emulator: &mut Emulator<_, _, _, _, _, _, _>, input: &BytesInput| { let target = input.target_bytes(); let mut buf = target.as_slice(); let mut len = buf.len(); diff --git a/fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs b/fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs index a1490c5a68..5b1df52099 100644 --- a/fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs +++ b/fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs @@ -345,7 +345,7 @@ fn fuzz( // The wrapped harness function, calling out to the LLVM-style harness let mut harness = - |_emulator: &mut Emulator<_, _, _, _, _>, _state: &mut _, input: &BytesInput| { + |_emulator: &mut Emulator<_, _, _, _, _, _, _>, _state: &mut _, input: &BytesInput| { let target = input.target_bytes(); let mut buf = target.as_slice(); let mut len = buf.len(); diff --git a/fuzzers/binary_only/intel_pt_baby_fuzzer/src/main.rs b/fuzzers/binary_only/intel_pt_baby_fuzzer/src/main.rs index eaae1771c5..0614a5e9bd 100644 --- a/fuzzers/binary_only/intel_pt_baby_fuzzer/src/main.rs +++ b/fuzzers/binary_only/intel_pt_baby_fuzzer/src/main.rs @@ -122,8 +122,8 @@ pub fn main() { } .build(); - type PTInProcessExecutor<'a, H, OT, S, T> = - GenericInProcessExecutor, ()), OT, S>; + type PTInProcessExecutor<'a, H, I, OT, S, T> = + GenericInProcessExecutor, ()), I, OT, S>; // Create the executor for an in-process function with just one observer let mut executor = PTInProcessExecutor::with_timeout_generic( tuple_list!(pt_hook), diff --git a/fuzzers/binary_only/qemu_cmin/src/fuzzer.rs b/fuzzers/binary_only/qemu_cmin/src/fuzzer.rs index 483e20c3f8..b38b86ff2d 100644 --- a/fuzzers/binary_only/qemu_cmin/src/fuzzer.rs +++ b/fuzzers/binary_only/qemu_cmin/src/fuzzer.rs @@ -197,7 +197,7 @@ pub fn fuzz() -> Result<(), Error> { let scheduler = QueueScheduler::new(); let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); - let mut harness = |_emulator: &mut Emulator<_, _, _, _, _>, input: &BytesInput| { + let mut harness = |_emulator: &mut Emulator<_, _, _, _, _, _, _>, input: &BytesInput| { let target = input.target_bytes(); let mut buf = target.as_slice(); let mut len = buf.len(); diff --git a/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs b/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs index e3fed6483a..e1f4e5307b 100644 --- a/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs +++ b/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs @@ -197,7 +197,7 @@ pub fn fuzz() { }; let mut harness = - |_emulator: &mut Emulator<_, _, _, _, _>, _state: &mut _, input: &BytesInput| { + |_emulator: &mut Emulator<_, _, _, _, _, _, _>, _state: &mut _, input: &BytesInput| { let target = input.target_bytes(); let mut buf = target.as_slice(); let mut len = buf.len(); diff --git a/fuzzers/binary_only/qemu_launcher/src/instance.rs b/fuzzers/binary_only/qemu_launcher/src/instance.rs index 24d2c056fe..3401e04e36 100644 --- a/fuzzers/binary_only/qemu_launcher/src/instance.rs +++ b/fuzzers/binary_only/qemu_launcher/src/instance.rs @@ -26,7 +26,7 @@ use libafl::{ calibrate::CalibrationStage, power::StdPowerMutationalStage, AflStatsStage, IfStage, ShadowTracingStage, StagesTuple, StdMutationalStage, }, - state::{HasCorpus, StdState, UsesState}, + state::{HasCorpus, StdState}, Error, HasMetadata, NopFuzzer, }; #[cfg(not(feature = "simplemgr"))] @@ -113,7 +113,7 @@ impl Instance<'_, M> { state: Option, ) -> Result<(), Error> where - ET: EmulatorModuleTuple + Debug, + ET: EmulatorModuleTuple + Debug, { // Create an observation channel using the coverage map let mut edges_observer = unsafe { @@ -138,7 +138,7 @@ impl Instance<'_, M> { let qemu = emulator.qemu(); // update address filter after qemu has been initialized - as EmulatorModule>::update_address_filter(emulator.modules_mut() + as EmulatorModule>::update_address_filter(emulator.modules_mut() .modules_mut() .match_first_type_mut::>() .expect("Could not find back the edge module"), qemu, self.coverage_filter(qemu)?); @@ -216,7 +216,7 @@ impl Instance<'_, M> { harness.post_fork(); - let mut harness = |_emulator: &mut Emulator<_, _, _, _, _>, + let mut harness = |_emulator: &mut Emulator<_, _, _, _, _, _, _>, _state: &mut _, input: &BytesInput| harness.run(input); diff --git a/fuzzers/full_system/qemu_baremetal/src/fuzzer_breakpoint.rs b/fuzzers/full_system/qemu_baremetal/src/fuzzer_breakpoint.rs index 6248078597..5aff233c64 100644 --- a/fuzzers/full_system/qemu_baremetal/src/fuzzer_breakpoint.rs +++ b/fuzzers/full_system/qemu_baremetal/src/fuzzer_breakpoint.rs @@ -87,10 +87,11 @@ pub fn fuzz() { let args: Vec = env::args().collect(); // The wrapped harness function, calling out to the LLVM-style harness - let mut harness = - |emulator: &mut Emulator<_, _, _, _, _>, state: &mut _, input: &BytesInput| unsafe { - emulator.run(state, input).unwrap().try_into().unwrap() - }; + let mut harness = |emulator: &mut Emulator<_, _, _, _, _, _, _>, + state: &mut _, + input: &BytesInput| unsafe { + emulator.run(state, input).unwrap().try_into().unwrap() + }; // Create an observation channel using the coverage map let mut edges_observer = unsafe { diff --git a/fuzzers/full_system/qemu_baremetal/src/fuzzer_low_level.rs b/fuzzers/full_system/qemu_baremetal/src/fuzzer_low_level.rs index 72fac07d83..837d0644c6 100644 --- a/fuzzers/full_system/qemu_baremetal/src/fuzzer_low_level.rs +++ b/fuzzers/full_system/qemu_baremetal/src/fuzzer_low_level.rs @@ -146,7 +146,7 @@ pub fn fuzz() { // The wrapped harness function, calling out to the LLVM-style harness let mut harness = - |emulator: &mut Emulator<_, _, _, _, _>, _state: &mut _, input: &BytesInput| { + |emulator: &mut Emulator<_, _, _, _, _, _, _>, _state: &mut _, input: &BytesInput| { let target = input.target_bytes(); let mut buf = target.as_slice(); let len = buf.len(); diff --git a/fuzzers/full_system/qemu_baremetal/src/fuzzer_sync_exit.rs b/fuzzers/full_system/qemu_baremetal/src/fuzzer_sync_exit.rs index dd691305ec..79e033fabb 100644 --- a/fuzzers/full_system/qemu_baremetal/src/fuzzer_sync_exit.rs +++ b/fuzzers/full_system/qemu_baremetal/src/fuzzer_sync_exit.rs @@ -71,10 +71,11 @@ pub fn fuzz() { println!("Devices = {:?}", devices); // The wrapped harness function, calling out to the LLVM-style harness - let mut harness = - |emulator: &mut Emulator<_, _, _, _, _>, state: &mut _, input: &BytesInput| unsafe { - emulator.run(state, input).unwrap().try_into().unwrap() - }; + let mut harness = |emulator: &mut Emulator<_, _, _, _, _, _, _>, + state: &mut _, + input: &BytesInput| unsafe { + emulator.run(state, input).unwrap().try_into().unwrap() + }; // Create an observation channel to keep track of the execution time let time_observer = TimeObserver::new("time"); diff --git a/fuzzers/full_system/qemu_linux_kernel/Makefile.toml b/fuzzers/full_system/qemu_linux_kernel/Makefile.toml index 9eb271f2a0..b451537467 100644 --- a/fuzzers/full_system/qemu_linux_kernel/Makefile.toml +++ b/fuzzers/full_system/qemu_linux_kernel/Makefile.toml @@ -138,6 +138,24 @@ ${TARGET_DIR}/${PROFILE_DIR}/qemu_linux_kernel \ -serial null ''' +[tasks.test_unix] +script_runner = "@shell" +script = ''' +# TODO: Run real test, not only building. + +# LibAFL QEMU API +HARNESS_API=lqemu cargo make build + +# Nyx API +HARNESS_API=nyx cargo make build +''' + +[tasks.test] +description = "Run a test" +linux_alias = "test_unix" +mac_alias = "test_unix" +windows_alias = "unsupported" + [tasks.debug] dependencies = ["build"] command = "time" diff --git a/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs b/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs index 8470f12be8..461f273fd1 100644 --- a/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs +++ b/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs @@ -12,7 +12,7 @@ use libafl::{ feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, - inputs::{BytesInput, HasTargetBytes, UsesInput}, + inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{havoc_mutations, scheduled::StdScheduledMutator, I2SRandReplaceBinonly}, observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, @@ -32,7 +32,10 @@ use libafl_bolts::{ #[cfg(feature = "nyx")] use libafl_qemu::{command::nyx::NyxCommandManager, NyxEmulatorDriver}; #[cfg(not(feature = "nyx"))] -use libafl_qemu::{command::StdCommandManager, StdEmulatorDriver}; +use libafl_qemu::{ + command::StdCommandManager, modules::utils::filters::LINUX_PROCESS_ADDRESS_RANGE, + StdEmulatorDriver, +}; use libafl_qemu::{ emu::Emulator, executor::QemuExecutor, @@ -45,17 +48,17 @@ use libafl_qemu::{ use libafl_targets::{edges_map_mut_ptr, EDGES_MAP_DEFAULT_SIZE, MAX_EDGES_FOUND}; #[cfg(feature = "nyx")] -fn get_emulator( +fn get_emulator( args: Vec, modules: ET, ) -> Result< - Emulator, NyxEmulatorDriver, ET, S, NopSnapshotManager>, + Emulator, NyxEmulatorDriver, ET, I, S, NopSnapshotManager>, QemuInitError, > where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - ::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, { Emulator::empty() .qemu_parameters(args) @@ -67,17 +70,17 @@ where } #[cfg(not(feature = "nyx"))] -fn get_emulator( +fn get_emulator( args: Vec, mut modules: ET, ) -> Result< - Emulator, StdEmulatorDriver, ET, S, FastSnapshotManager>, + Emulator, StdEmulatorDriver, ET, I, S, FastSnapshotManager>, QemuInitError, > where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, S: State + HasExecutions + Unpin, - ::Input: HasTargetBytes, { // Allow linux process address space addresses as feedback modules.allow_address_range_all(LINUX_PROCESS_ADDRESS_RANGE); @@ -146,10 +149,11 @@ pub fn fuzz() { println!("Devices = {:?}", devices); // The wrapped harness function, calling out to the LLVM-style harness - let mut harness = - |emulator: &mut Emulator<_, _, _, _, _>, state: &mut _, input: &BytesInput| unsafe { - emulator.run(state, input).unwrap().try_into().unwrap() - }; + let mut harness = |emulator: &mut Emulator<_, _, _, _, _, _, _>, + state: &mut _, + input: &BytesInput| unsafe { + emulator.run(state, input).unwrap().try_into().unwrap() + }; // Create an observation channel to keep track of the execution time let time_observer = TimeObserver::new("time"); diff --git a/fuzzers/full_system/qemu_linux_kernel/src/main.rs b/fuzzers/full_system/qemu_linux_kernel/src/main.rs index b2cf41cb60..fd6ca0acac 100644 --- a/fuzzers/full_system/qemu_linux_kernel/src/main.rs +++ b/fuzzers/full_system/qemu_linux_kernel/src/main.rs @@ -1,6 +1,6 @@ //! A systemmode linux kernel example //! -#[cfg(all(target_os = "linux"))] +#[cfg(target_os = "linux")] mod fuzzer; #[cfg(target_os = "linux")] diff --git a/fuzzers/full_system/qemu_linux_process/Makefile.toml b/fuzzers/full_system/qemu_linux_process/Makefile.toml index 5d3c2c0323..9761452463 100644 --- a/fuzzers/full_system/qemu_linux_process/Makefile.toml +++ b/fuzzers/full_system/qemu_linux_process/Makefile.toml @@ -135,6 +135,24 @@ args = [ "${FEATURE}", ] +[tasks.test_unix] +script_runner = "@shell" +script = ''' +# TODO: Run real test, not only building. + +# LibAFL QEMU API +HARNESS_API=lqemu cargo make build + +# Nyx API +HARNESS_API=nyx cargo make build +''' + +[tasks.test] +description = "Run a test" +linux_alias = "test_unix" +mac_alias = "test_unix" +windows_alias = "unsupported" + [tasks.run] dependencies = ["build"] script_runner = "@shell" diff --git a/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs b/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs index d141163113..a8ef071c64 100644 --- a/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs +++ b/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs @@ -8,11 +8,11 @@ use libafl::state::{HasExecutions, State}; use libafl::{ corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, - executors::{ExitKind, ShadowExecutor}, + executors::ShadowExecutor, feedback_and_fast, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, - inputs::{BytesInput, HasTargetBytes, UsesInput}, + inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{havoc_mutations, I2SRandReplaceBinonly, StdScheduledMutator}, observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver}, @@ -32,31 +32,33 @@ use libafl_bolts::{ #[cfg(feature = "nyx")] use libafl_qemu::{command::nyx::NyxCommandManager, NyxEmulatorDriver}; #[cfg(not(feature = "nyx"))] -use libafl_qemu::{command::StdCommandManager, StdEmulatorDriver}; +use libafl_qemu::{ + command::StdCommandManager, modules::utils::filters::LINUX_PROCESS_ADDRESS_RANGE, + StdEmulatorDriver, +}; use libafl_qemu::{ emu::Emulator, executor::QemuExecutor, modules::{ - cmplog::CmpLogObserver, edges::StdEdgeCoverageClassicModule, - utils::filters::LINUX_PROCESS_ADDRESS_RANGE, CmpLogModule, EmulatorModuleTuple, + cmplog::CmpLogObserver, edges::StdEdgeCoverageClassicModule, CmpLogModule, + EmulatorModuleTuple, }, - EmulatorDriverError, FastSnapshotManager, NopSnapshotManager, QemuInitError, - QemuSnapshotManager, + FastSnapshotManager, NopSnapshotManager, QemuInitError, QemuSnapshotManager, }; use libafl_targets::{edges_map_mut_ptr, EDGES_MAP_DEFAULT_SIZE, MAX_EDGES_FOUND}; #[cfg(feature = "nyx")] -fn get_emulator( +fn get_emulator( args: Vec, modules: ET, ) -> Result< - Emulator, NyxEmulatorDriver, ET, S, NopSnapshotManager>, + Emulator, NyxEmulatorDriver, ET, I, S, NopSnapshotManager>, QemuInitError, > where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - ::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + S: Unpin, + I: HasTargetBytes + Unpin, { Emulator::empty() .qemu_parameters(args) @@ -68,17 +70,17 @@ where } #[cfg(not(feature = "nyx"))] -fn get_emulator( +fn get_emulator( args: Vec, mut modules: ET, ) -> Result< - Emulator, StdEmulatorDriver, ET, S, FastSnapshotManager>, + Emulator, StdEmulatorDriver, ET, I, S, FastSnapshotManager>, QemuInitError, > where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, S: State + HasExecutions + Unpin, - ::Input: HasTargetBytes, { // Allow linux process address space addresses as feedback modules.allow_address_range_all(LINUX_PROCESS_ADDRESS_RANGE); @@ -145,15 +147,16 @@ pub fn fuzz() { let emu = get_emulator(args, modules)?; // The wrapped harness function, calling out to the LLVM-style harness - let mut harness = - |emulator: &mut Emulator<_, _, _, _, _>, state: &mut _, input: &BytesInput| unsafe { - match emulator.run(state, input) { - Ok(res) => res.try_into().unwrap(), - Err(e) => match e { - _ => panic!("{e:?}"), - }, - } - }; + let mut harness = |emulator: &mut Emulator<_, _, _, _, _, _, _>, + state: &mut _, + input: &BytesInput| unsafe { + match emulator.run(state, input) { + Ok(res) => res.try_into().unwrap(), + Err(e) => match e { + _ => panic!("{e:?}"), + }, + } + }; // Create an observation channel to keep track of the execution time let time_observer = TimeObserver::new("time"); diff --git a/fuzzers/full_system/qemu_linux_process/src/main.rs b/fuzzers/full_system/qemu_linux_process/src/main.rs index b2cf41cb60..fd6ca0acac 100644 --- a/fuzzers/full_system/qemu_linux_process/src/main.rs +++ b/fuzzers/full_system/qemu_linux_process/src/main.rs @@ -1,6 +1,6 @@ //! A systemmode linux kernel example //! -#[cfg(all(target_os = "linux"))] +#[cfg(target_os = "linux")] mod fuzzer; #[cfg(target_os = "linux")] diff --git a/libafl/src/executors/hooks/inprocess.rs b/libafl/src/executors/hooks/inprocess.rs index e6cc114b73..18d9da8735 100644 --- a/libafl/src/executors/hooks/inprocess.rs +++ b/libafl/src/executors/hooks/inprocess.rs @@ -24,20 +24,19 @@ use crate::executors::hooks::timer::TimerStruct; #[cfg(all(unix, feature = "std"))] use crate::executors::hooks::unix::unix_signal_handler; #[cfg(any(unix, windows))] -use crate::observers::ObserversTuple; +use crate::{corpus::Corpus, inputs::Input, observers::ObserversTuple, state::HasCurrentTestcase}; use crate::{ - corpus::Corpus, events::{EventFirer, EventRestarter}, executors::{hooks::ExecutorHook, inprocess::HasInProcessHooks, Executor, HasObservers}, feedbacks::Feedback, - inputs::{Input, UsesInput}, - state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, + inputs::UsesInput, + state::{HasCorpus, HasExecutions, HasSolutions}, Error, HasObjective, }; /// The inmem executor's handlers. #[expect(missing_debug_implementations)] -pub struct InProcessHooks { +pub struct InProcessHooks { /// On crash C function pointer #[cfg(feature = "std")] pub crash_handler: *const c_void, @@ -47,7 +46,7 @@ pub struct InProcessHooks { /// `TImer` struct #[cfg(feature = "std")] pub timer: TimerStruct, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, } /// Any hooks that is about timeout @@ -83,7 +82,7 @@ pub trait HasTimeout { fn handle_timeout(&mut self, data: &mut InProcessExecutorHandlerData) -> bool; } -impl HasTimeout for InProcessHooks { +impl HasTimeout for InProcessHooks { #[cfg(feature = "std")] fn timer(&self) -> &TimerStruct { &self.timer @@ -187,14 +186,13 @@ impl HasTimeout for InProcessHooks { } } -impl ExecutorHook<::Input, S> for InProcessHooks +impl ExecutorHook for InProcessHooks where S: HasCorpus, { fn init(&mut self, _state: &mut S) {} /// Call before running a target. - #[expect(unused_variables)] - fn pre_exec(&mut self, state: &mut S, input: &::Input) { + fn pre_exec(&mut self, _state: &mut S, _input: &I) { #[cfg(feature = "std")] unsafe { let data = &raw mut GLOBAL_STATE; @@ -207,7 +205,7 @@ where } /// Call after running a target. - fn post_exec(&mut self, _state: &mut S, _input: &::Input) { + fn post_exec(&mut self, _state: &mut S, _input: &I) { // timeout stuff // # Safety // We're calling this only once per execution, in a single thread. @@ -216,24 +214,20 @@ where } } -impl InProcessHooks { +impl InProcessHooks { /// Create new [`InProcessHooks`]. #[cfg(unix)] #[allow(unused_variables)] // for `exec_tmout` without `std` pub fn new(exec_tmout: Duration) -> Result where - E: Executor::Input, S, Z> + HasObservers + HasInProcessHooks, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasObservers + HasInProcessHooks, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasExecutions - + HasSolutions - + HasCorpus - + HasCurrentTestcase - + UsesInput::Input>, + OF: Feedback, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, Z: HasObjective, - ::Input: Input + Clone, - S::Solutions: Corpus::Input>, + I: Input + Clone, + S::Solutions: Corpus, { // # Safety // We get a pointer to `GLOBAL_STATE` that will be initialized at this point in time. @@ -242,7 +236,7 @@ impl InProcessHooks { #[cfg(all(not(miri), unix, feature = "std"))] let data = unsafe { &raw mut GLOBAL_STATE }; #[cfg(feature = "std")] - unix_signal_handler::setup_panic_hook::(); + unix_signal_handler::setup_panic_hook::(); // # Safety // Setting up the signal handlers with a pointer to the `GLOBAL_STATE` which should not be NULL at this point. // We are the sole users of `GLOBAL_STATE` right now, and only dereference it in case of Segfault/Panic. @@ -254,10 +248,10 @@ impl InProcessHooks { compiler_fence(Ordering::SeqCst); Ok(Self { #[cfg(feature = "std")] - crash_handler: unix_signal_handler::inproc_crash_handler:: + crash_handler: unix_signal_handler::inproc_crash_handler:: as *const c_void, #[cfg(feature = "std")] - timeout_handler: unix_signal_handler::inproc_timeout_handler:: + timeout_handler: unix_signal_handler::inproc_timeout_handler:: as *const _, #[cfg(feature = "std")] timer: TimerStruct::new(exec_tmout), @@ -270,18 +264,14 @@ impl InProcessHooks { #[allow(unused_variables)] // for `exec_tmout` without `std` pub fn new(exec_tmout: Duration) -> Result where - E: Executor::Input, S, Z> + HasObservers + HasInProcessHooks, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasObservers + HasInProcessHooks, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasExecutions - + HasSolutions - + HasCorpus - + HasCurrentTestcase - + UsesInput::Input>, + I: Input + Clone, + OF: Feedback, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, + S::Solutions: Corpus, Z: HasObjective, - ::Input: Input + Clone, - S::Solutions: Corpus::Input>, { let ret; #[cfg(feature = "std")] @@ -290,6 +280,7 @@ impl InProcessHooks { crate::executors::hooks::windows::windows_exception_handler::setup_panic_hook::< E, EM, + I, OF, S, Z, @@ -300,6 +291,7 @@ impl InProcessHooks { crate::executors::hooks::windows::windows_exception_handler::inproc_crash_handler::< E, EM, + I, OF, S, Z, @@ -308,6 +300,7 @@ impl InProcessHooks { crate::executors::hooks::windows::windows_exception_handler::inproc_timeout_handler::< E, EM, + I, OF, S, Z, @@ -335,13 +328,10 @@ impl InProcessHooks { #[expect(unused_variables)] pub fn new(exec_tmout: Duration) -> Result where - E: Executor::Input, S, Z> + HasObservers + HasInProcessHooks, + E: Executor + HasObservers + HasInProcessHooks, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasExecutions - + HasSolutions - + HasCorpus - + UsesInput::Input>, + OF: Feedback, + S: HasExecutions + HasSolutions + HasCorpus + UsesInput, Z: HasObjective, { #[cfg_attr(miri, allow(unused_variables))] diff --git a/libafl/src/executors/hooks/inprocess_fork.rs b/libafl/src/executors/hooks/inprocess_fork.rs index 6684189450..b386a57296 100644 --- a/libafl/src/executors/hooks/inprocess_fork.rs +++ b/libafl/src/executors/hooks/inprocess_fork.rs @@ -14,7 +14,6 @@ use libafl_bolts::os::unix_signals::{ucontext_t, Signal, SignalHandler}; use libc::siginfo_t; use crate::{ - corpus::Corpus, executors::{ common_signals, hooks::ExecutorHook, @@ -28,15 +27,15 @@ use crate::{ /// The inmem fork executor's hooks. #[derive(Debug)] -pub struct InChildProcessHooks { +pub struct InChildProcessHooks { /// On crash C function pointer pub crash_handler: *const c_void, /// On timeout C function pointer pub timeout_handler: *const c_void, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, } -impl ExecutorHook<::Input, S> for InChildProcessHooks +impl ExecutorHook for InChildProcessHooks where S: HasCorpus, { @@ -44,7 +43,7 @@ where fn init(&mut self, _state: &mut S) {} /// Call before running a target. - fn pre_exec(&mut self, _state: &mut S, _input: &::Input) { + fn pre_exec(&mut self, _state: &mut S, _input: &I) { unsafe { let data = &raw mut FORK_EXECUTOR_GLOBAL_DATA; (*data).crash_handler = self.crash_handler; @@ -53,15 +52,15 @@ where } } - fn post_exec(&mut self, _state: &mut S, _input: &::Input) {} + fn post_exec(&mut self, _state: &mut S, _input: &I) {} } -impl InChildProcessHooks { +impl InChildProcessHooks { /// Create new [`InChildProcessHooks`]. pub fn new() -> Result where E: HasObservers, - E::Observers: ObserversTuple<::Input, S>, + E::Observers: ObserversTuple, S: HasCorpus, { #[cfg_attr(miri, allow(unused_variables, unused_unsafe))] @@ -72,16 +71,10 @@ impl InChildProcessHooks { setup_signal_handler(data)?; compiler_fence(Ordering::SeqCst); Ok(Self { - crash_handler: child_signal_handlers::child_crash_handler::< - E, - ::Input, - S, - > as *const c_void, - timeout_handler: child_signal_handlers::child_timeout_handler::< - E, - ::Input, - S, - > as *const c_void, + crash_handler: child_signal_handlers::child_crash_handler:: + as *const c_void, + timeout_handler: child_signal_handlers::child_timeout_handler:: + as *const c_void, phantom: PhantomData, }) } diff --git a/libafl/src/executors/hooks/unix.rs b/libafl/src/executors/hooks/unix.rs index 20cb7d559f..feb15caa0d 100644 --- a/libafl/src/executors/hooks/unix.rs +++ b/libafl/src/executors/hooks/unix.rs @@ -77,20 +77,16 @@ pub mod unix_signal_handler { } /// invokes the `post_exec` hook on all observer in case of panic - pub fn setup_panic_hook() + pub fn setup_panic_hook() where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasObservers, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasExecutions - + HasSolutions - + HasCurrentTestcase - + HasCorpus - + UsesInput::Input>, - S::Solutions: Corpus::Input>, + OF: Feedback, + S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput, + S::Solutions: Corpus, Z: HasObjective, - ::Input: Input + Clone, + I: Input + Clone, { let old_hook = panic::take_hook(); panic::set_hook(Box::new(move |panic_info| unsafe { @@ -101,11 +97,11 @@ pub mod unix_signal_handler { // We are fuzzing! let executor = (*data).executor_mut::(); let state = (*data).state_mut::(); - let input = (*data).take_current_input::<::Input>(); + let input = (*data).take_current_input::(); let fuzzer = (*data).fuzzer_mut::(); let event_mgr = (*data).event_mgr_mut::(); - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, @@ -127,24 +123,20 @@ pub mod unix_signal_handler { /// Well, signal handling is not safe #[cfg(unix)] #[allow(clippy::needless_pass_by_value)] // nightly no longer requires this - pub unsafe fn inproc_timeout_handler( + pub unsafe fn inproc_timeout_handler( _signal: Signal, _info: &mut siginfo_t, _context: Option<&mut ucontext_t>, data: &mut InProcessExecutorHandlerData, ) where - E: Executor::Input, S, Z> + HasInProcessHooks + HasObservers, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasInProcessHooks + HasObservers, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasExecutions - + HasSolutions - + HasCurrentTestcase - + HasCorpus - + UsesInput::Input>, + OF: Feedback, + S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput, Z: HasObjective, - ::Input: Input + Clone, - S::Solutions: Corpus::Input>, + I: Input + Clone, + S::Solutions: Corpus, { // this stuff is for batch timeout if !data.executor_ptr.is_null() @@ -165,11 +157,11 @@ pub mod unix_signal_handler { let state = data.state_mut::(); let event_mgr = data.event_mgr_mut::(); let fuzzer = data.fuzzer_mut::(); - let input = data.take_current_input::<::Input>(); + let input = data.take_current_input::(); log::error!("Timeout in fuzz run."); - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, @@ -188,24 +180,20 @@ pub mod unix_signal_handler { /// # Safety /// Well, signal handling is not safe #[allow(clippy::needless_pass_by_value)] // nightly no longer requires this - pub unsafe fn inproc_crash_handler( + pub unsafe fn inproc_crash_handler( signal: Signal, _info: &mut siginfo_t, _context: Option<&mut ucontext_t>, data: &mut InProcessExecutorHandlerData, ) where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasObservers, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasExecutions - + HasSolutions - + HasCorpus - + HasCurrentTestcase - + UsesInput::Input>, + OF: Feedback, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, Z: HasObjective, - ::Input: Input + Clone, - S::Solutions: Corpus::Input>, + I: Input + Clone, + S::Solutions: Corpus, { #[cfg(all(target_os = "android", target_arch = "aarch64"))] let _context = _context.map(|p| { @@ -220,7 +208,7 @@ pub mod unix_signal_handler { let state = data.state_mut::(); let event_mgr = data.event_mgr_mut::(); let fuzzer = data.fuzzer_mut::(); - let input = data.take_current_input::<::Input>(); + let input = data.take_current_input::(); log::error!("Child crashed!"); @@ -245,7 +233,7 @@ pub mod unix_signal_handler { } } - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, diff --git a/libafl/src/executors/hooks/windows.rs b/libafl/src/executors/hooks/windows.rs index fdcf0b88f5..1e6bbc4fe1 100644 --- a/libafl/src/executors/hooks/windows.rs +++ b/libafl/src/executors/hooks/windows.rs @@ -24,20 +24,16 @@ pub mod windows_asan_handler { /// # Safety /// ASAN deatch handler - pub unsafe extern "C" fn asan_death_handler() + pub unsafe extern "C" fn asan_death_handler() where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasObservers, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasExecutions - + HasSolutions - + HasCurrentTestcase - + HasCorpus - + UsesInput::Input>, - S::Solutions: Corpus::Input>, + I: Input + Clone, + OF: Feedback, + S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput, + S::Solutions: Corpus, Z: HasObjective, - ::Input: Input + Clone, { let data = &raw mut GLOBAL_STATE; (*data).set_in_handler(true); @@ -89,9 +85,9 @@ pub mod windows_asan_handler { log::error!("Child crashed!"); // Make sure we don't crash in the crash handler forever. - let input = (*data).take_current_input::<::Input>(); + let input = (*data).take_current_input::(); - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, @@ -186,20 +182,16 @@ pub mod windows_exception_handler { /// # Safety /// Well, exception handling is not safe #[cfg(feature = "std")] - pub fn setup_panic_hook() + pub fn setup_panic_hook() where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasObservers, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasExecutions - + HasSolutions - + HasCurrentTestcase - + HasCorpus - + UsesInput::Input>, - S::Solutions: Corpus::Input>, + I: Input + Clone, + OF: Feedback, + S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput, + S::Solutions: Corpus, Z: HasObjective, - ::Input: Input + Clone, { let old_hook = panic::take_hook(); panic::set_hook(Box::new(move |panic_info| unsafe { @@ -228,9 +220,9 @@ pub mod windows_exception_handler { let fuzzer = (*data).fuzzer_mut::(); let event_mgr = (*data).event_mgr_mut::(); - let input = (*data).take_current_input::<::Input>(); + let input = (*data).take_current_input::(); - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, @@ -250,23 +242,19 @@ pub mod windows_exception_handler { /// /// # Safety /// Well, exception handling is not safe - pub unsafe extern "system" fn inproc_timeout_handler( + pub unsafe extern "system" fn inproc_timeout_handler( _p0: *mut u8, global_state: *mut c_void, _p1: *mut u8, ) where - E: Executor::Input, S, Z> + HasInProcessHooks + HasObservers, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasInProcessHooks + HasObservers, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasExecutions - + HasSolutions - + HasCurrentTestcase - + HasCorpus - + UsesInput::Input>, + I: Input + Clone, + OF: Feedback, + S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus + UsesInput, Z: HasObjective, - ::Input: Input + Clone, - S::Solutions: Corpus::Input>, + S::Solutions: Corpus, { let data: &mut InProcessExecutorHandlerData = &mut *(global_state as *mut InProcessExecutorHandlerData); @@ -298,12 +286,10 @@ pub mod windows_exception_handler { } else { log::error!("Timeout in fuzz run."); - let input = (data.current_input_ptr as *const ::Input) - .as_ref() - .unwrap(); + let input = (data.current_input_ptr as *const I).as_ref().unwrap(); data.current_input_ptr = ptr::null_mut(); - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, @@ -327,22 +313,18 @@ pub mod windows_exception_handler { /// /// # Safety /// Well, exception handling is not safe - pub unsafe fn inproc_crash_handler( + pub unsafe fn inproc_crash_handler( exception_pointers: *mut EXCEPTION_POINTERS, data: &mut InProcessExecutorHandlerData, ) where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasObservers, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasExecutions - + HasSolutions - + HasCorpus - + HasCurrentTestcase - + UsesInput::Input>, + I: Input + Clone, + OF: Feedback, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, Z: HasObjective, - ::Input: Input + Clone, - S::Solutions: Corpus::Input>, + S::Solutions: Corpus, { // Have we set a timer_before? if data.ptp_timer.is_some() { @@ -428,7 +410,7 @@ pub mod windows_exception_handler { // Make sure we don't crash in the crash handler forever. if is_crash { - let input = data.take_current_input::<::Input>(); + let input = data.take_current_input::(); { let mut bsod = Vec::new(); { @@ -440,7 +422,7 @@ pub mod windows_exception_handler { } log::error!("{}", std::str::from_utf8(&bsod).unwrap()); } - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, diff --git a/libafl/src/executors/inprocess/inner.rs b/libafl/src/executors/inprocess/inner.rs index 24a868ec39..6656f5d44f 100644 --- a/libafl/src/executors/inprocess/inner.rs +++ b/libafl/src/executors/inprocess/inner.rs @@ -1,7 +1,6 @@ use core::{ ffi::c_void, fmt::{self, Debug, Formatter}, - marker::PhantomData, ptr::{self, null, write_volatile}, sync::atomic::{compiler_fence, Ordering}, time::Duration, @@ -35,15 +34,14 @@ use crate::{ }; /// The internal state of `GenericInProcessExecutor`. -pub struct GenericInProcessExecutorInner { +pub struct GenericInProcessExecutorInner { /// The observers, observing each run pub(super) observers: OT, // Crash and timeout hah - pub(super) hooks: (InProcessHooks, HT), - phantom: PhantomData, + pub(super) hooks: (InProcessHooks, HT), } -impl Debug for GenericInProcessExecutorInner +impl Debug for GenericInProcessExecutorInner where OT: Debug, { @@ -54,7 +52,7 @@ where } } -impl HasObservers for GenericInProcessExecutorInner { +impl HasObservers for GenericInProcessExecutorInner { type Observers = OT; #[inline] @@ -68,9 +66,9 @@ impl HasObservers for GenericInProcessExecutorInner { } } -impl GenericInProcessExecutorInner +impl GenericInProcessExecutorInner where - OT: ObserversTuple<::Input, S>, + OT: ObserversTuple, S: HasCorpus, { /// This function marks the boundary between the fuzzer and the target @@ -84,7 +82,7 @@ where fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, executor_ptr: *const c_void, ) { unsafe { @@ -119,7 +117,7 @@ where _fuzzer: &mut Z, _state: &mut S, _mgr: &mut EM, - _input: &::Input, + _input: &I, ) { unsafe { let data = &raw mut GLOBAL_STATE; @@ -130,10 +128,10 @@ where } } -impl GenericInProcessExecutorInner +impl GenericInProcessExecutorInner where - HT: ExecutorHooksTuple<::Input, S>, - OT: ObserversTuple<::Input, S>, + HT: ExecutorHooksTuple, + OT: ObserversTuple, S: HasCorpus + HasExecutions + HasSolutions, { /// Create a new in mem executor with the default timeout (5 sec) @@ -145,17 +143,14 @@ where event_mgr: &mut EM, ) -> Result where - E: Executor::Input, S, Z> + HasObservers + HasInProcessHooks, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasObservers + HasInProcessHooks, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasCurrentTestcase - + HasCorpus - + HasSolutions - + UsesInput::Input>, + I: Input + Clone, + OF: Feedback, + S: HasCurrentTestcase + HasCorpus + HasSolutions + UsesInput, + S::Solutions: Corpus, Z: HasObjective, - S::Solutions: Corpus::Input>, - ::Input: Input + Clone, { Self::with_timeout_generic::( user_hooks, @@ -178,17 +173,14 @@ where exec_tmout: Duration, ) -> Result where - E: Executor::Input, S, Z> + HasObservers + HasInProcessHooks, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasObservers + HasInProcessHooks, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasCurrentTestcase - + HasCorpus - + HasSolutions - + UsesInput::Input>, + I: Input + Clone, + OF: Feedback, + S: HasCurrentTestcase + HasCorpus + HasSolutions + UsesInput, + S::Solutions: Corpus, Z: HasObjective, - S::Solutions: Corpus::Input>, - ::Input: Input + Clone, { let mut me = Self::with_timeout_generic::( user_hooks, observers, fuzzer, state, event_mgr, exec_tmout, @@ -214,17 +206,14 @@ where timeout: Duration, ) -> Result where - E: Executor::Input, S, Z> + HasObservers + HasInProcessHooks, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasObservers + HasInProcessHooks, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasCurrentTestcase - + HasCorpus - + HasSolutions - + UsesInput::Input>, + OF: Feedback, + S: HasCurrentTestcase + HasCorpus + HasSolutions + UsesInput, Z: HasObjective, - S::Solutions: Corpus::Input>, - ::Input: Input + Clone, + S::Solutions: Corpus, + I: Input + Clone, { let default = InProcessHooks::new::(timeout)?; let mut hooks = tuple_list!(default).merge(user_hooks); @@ -253,36 +242,32 @@ where *hooks.0.millis_sec_mut() = timeout.as_millis() as i64; } - Ok(Self { - observers, - hooks, - phantom: PhantomData, - }) + Ok(Self { observers, hooks }) } /// The inprocess handlers #[inline] - pub fn hooks(&self) -> &(InProcessHooks, HT) { + pub fn hooks(&self) -> &(InProcessHooks, HT) { &self.hooks } /// The inprocess handlers (mutable) #[inline] - pub fn hooks_mut(&mut self) -> &mut (InProcessHooks, HT) { + pub fn hooks_mut(&mut self) -> &mut (InProcessHooks, HT) { &mut self.hooks } } -impl HasInProcessHooks for GenericInProcessExecutorInner { +impl HasInProcessHooks for GenericInProcessExecutorInner { /// the timeout handler #[inline] - fn inprocess_hooks(&self) -> &InProcessHooks { + fn inprocess_hooks(&self) -> &InProcessHooks { &self.hooks.0 } /// the timeout handler #[inline] - fn inprocess_hooks_mut(&mut self) -> &mut InProcessHooks { + fn inprocess_hooks_mut(&mut self) -> &mut InProcessHooks { &mut self.hooks.0 } } diff --git a/libafl/src/executors/inprocess/mod.rs b/libafl/src/executors/inprocess/mod.rs index d6644f0c1c..70136fd16c 100644 --- a/libafl/src/executors/inprocess/mod.rs +++ b/libafl/src/executors/inprocess/mod.rs @@ -40,28 +40,29 @@ pub mod inner; pub mod stateful; /// The process executor simply calls a target function, as mutable reference to a closure. -pub type InProcessExecutor<'a, H, OT, S> = GenericInProcessExecutor; +pub type InProcessExecutor<'a, H, I, OT, S> = GenericInProcessExecutor; /// The inprocess executor that allows hooks -pub type HookableInProcessExecutor<'a, H, HT, OT, S> = - GenericInProcessExecutor; +pub type HookableInProcessExecutor<'a, H, HT, I, OT, S> = + GenericInProcessExecutor; /// The process executor simply calls a target function, as boxed `FnMut` trait object -pub type OwnedInProcessExecutor = GenericInProcessExecutor< - dyn FnMut(&::Input) -> ExitKind, - Box::Input) -> ExitKind>, +pub type OwnedInProcessExecutor = GenericInProcessExecutor< + dyn FnMut(&I) -> ExitKind, + Box ExitKind>, (), + I, OT, S, >; /// The inmem executor simply calls a target function, then returns afterwards. -pub struct GenericInProcessExecutor { +pub struct GenericInProcessExecutor { harness_fn: HB, - inner: GenericInProcessExecutorInner, + inner: GenericInProcessExecutorInner, phantom: PhantomData<(*const H, HB)>, } -impl Debug for GenericInProcessExecutor +impl Debug for GenericInProcessExecutor where OT: Debug, { @@ -73,21 +74,21 @@ where } } -impl Executor::Input, S, Z> - for GenericInProcessExecutor +impl Executor + for GenericInProcessExecutor where S: HasCorpus + HasExecutions, - OT: ObserversTuple<::Input, S>, - HT: ExecutorHooksTuple<::Input, S>, + OT: ObserversTuple, + HT: ExecutorHooksTuple, HB: BorrowMut, - H: FnMut(&::Input) -> ExitKind + Sized, + H: FnMut(&I) -> ExitKind + Sized, { fn run_target( &mut self, fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { *state.executions_mut() += 1; unsafe { @@ -105,7 +106,7 @@ where } } -impl HasObservers for GenericInProcessExecutor { +impl HasObservers for GenericInProcessExecutor { type Observers = OT; #[inline] @@ -119,17 +120,13 @@ impl HasObservers for GenericInProcessExecutor InProcessExecutor<'a, H, OT, S> +impl<'a, H, I, OT, S> InProcessExecutor<'a, H, I, OT, S> where - H: FnMut(&::Input) -> ExitKind + Sized, - OT: ObserversTuple<::Input, S>, - S: HasCorpus - + HasCurrentTestcase - + UsesInput::Input> - + HasExecutions - + HasSolutions, - S::Solutions: Corpus::Input>, - ::Input: Input, + H: FnMut(&I) -> ExitKind + Sized, + OT: ObserversTuple, + S: HasCorpus + HasCurrentTestcase + UsesInput + HasExecutions + HasSolutions, + S::Solutions: Corpus, + I: Input, { /// Create a new in mem executor with the default timeout (5 sec) pub fn new( @@ -141,7 +138,7 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback::Input, OT, S>, + OF: Feedback, Z: HasObjective, { Self::with_timeout_generic::( @@ -167,7 +164,7 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback::Input, OT, S>, + OF: Feedback, Z: HasObjective, { let inner = GenericInProcessExecutorInner::batched_timeout_generic::( @@ -204,7 +201,7 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback::Input, OT, S>, + OF: Feedback, Z: HasObjective, { let inner = GenericInProcessExecutorInner::with_timeout_generic::( @@ -224,19 +221,15 @@ where } } -impl GenericInProcessExecutor +impl GenericInProcessExecutor where - H: FnMut(&::Input) -> ExitKind + Sized, + H: FnMut(&I) -> ExitKind + Sized, HB: BorrowMut, - HT: ExecutorHooksTuple<::Input, S>, - OT: ObserversTuple<::Input, S>, - S: HasCorpus - + HasCurrentTestcase - + UsesInput::Input> - + HasExecutions - + HasSolutions, - S::Solutions: Corpus::Input>, - ::Input: Input, + HT: ExecutorHooksTuple, + OT: ObserversTuple, + S: HasCorpus + HasCurrentTestcase + UsesInput + HasExecutions + HasSolutions, + S::Solutions: Corpus, + I: Input, { /// Create a new in mem executor with the default timeout (5 sec) pub fn generic( @@ -249,7 +242,7 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback::Input, OT, S>, + OF: Feedback, Z: HasObjective, { Self::with_timeout_generic::( @@ -276,7 +269,7 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback::Input, OT, S>, + OF: Feedback, Z: HasObjective, { let inner = GenericInProcessExecutorInner::batched_timeout_generic::( @@ -309,7 +302,7 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback::Input, OT, S>, + OF: Feedback, Z: HasObjective, { let inner = GenericInProcessExecutorInner::with_timeout_generic::( @@ -337,62 +330,60 @@ where /// The inprocess handlers #[inline] - pub fn hooks(&self) -> &(InProcessHooks, HT) { + pub fn hooks(&self) -> &(InProcessHooks, HT) { self.inner.hooks() } /// The inprocess handlers (mutable) #[inline] - pub fn hooks_mut(&mut self) -> &mut (InProcessHooks, HT) { + pub fn hooks_mut(&mut self) -> &mut (InProcessHooks, HT) { self.inner.hooks_mut() } } /// The struct has [`InProcessHooks`]. -pub trait HasInProcessHooks { +pub trait HasInProcessHooks { /// Get the in-process handlers. - fn inprocess_hooks(&self) -> &InProcessHooks; + fn inprocess_hooks(&self) -> &InProcessHooks; /// Get the mut in-process handlers. - fn inprocess_hooks_mut(&mut self) -> &mut InProcessHooks; + fn inprocess_hooks_mut(&mut self) -> &mut InProcessHooks; } -impl HasInProcessHooks for GenericInProcessExecutor { +impl HasInProcessHooks + for GenericInProcessExecutor +{ /// the timeout handler #[inline] - fn inprocess_hooks(&self) -> &InProcessHooks { + fn inprocess_hooks(&self) -> &InProcessHooks { self.inner.inprocess_hooks() } /// the timeout handler #[inline] - fn inprocess_hooks_mut(&mut self) -> &mut InProcessHooks { + fn inprocess_hooks_mut(&mut self) -> &mut InProcessHooks { self.inner.inprocess_hooks_mut() } } #[inline] /// Save state if it is an objective -pub fn run_observers_and_save_state( +pub fn run_observers_and_save_state( executor: &mut E, state: &mut S, - input: &::Input, + input: &I, fuzzer: &mut Z, event_mgr: &mut EM, exitkind: ExitKind, ) where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasObservers, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasExecutions - + HasSolutions - + HasCorpus - + HasCurrentTestcase - + UsesInput::Input>, + OF: Feedback, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, Z: HasObjective, - ::Input: Input + Clone, - S::Solutions: Corpus::Input>, + I: Input + Clone, + S::Solutions: Corpus, { let mut observers = executor.observers_mut(); @@ -445,21 +436,16 @@ pub fn run_observers_and_save_state( /// # Safety /// This will directly access `GLOBAL_STATE` and related data pointers #[cfg(any(unix, feature = "std"))] -pub unsafe fn generic_inproc_crash_handler() +pub unsafe fn generic_inproc_crash_handler() where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasObservers, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, - S: HasExecutions - + HasSolutions - + HasCorpus - + HasCurrentTestcase - + UsesInput::Input>, - ::Input: Input + Clone, - S::Solutions: Corpus::Input>, - Z: HasObjective - + ExecutionProcessor::Input, E::Observers, S>, + OF: Feedback, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, + I: Input + Clone, + S::Solutions: Corpus, + Z: HasObjective + ExecutionProcessor, { let data = &raw mut GLOBAL_STATE; let in_handler = (*data).set_in_handler(true); @@ -469,9 +455,9 @@ where let state = (*data).state_mut::(); let event_mgr = (*data).event_mgr_mut::(); let fuzzer = (*data).fuzzer_mut::(); - let input = (*data).take_current_input::<::Input>(); + let input = (*data).take_current_input::(); - run_observers_and_save_state::( + run_observers_and_save_state::( executor, state, input, diff --git a/libafl/src/executors/inprocess/stateful.rs b/libafl/src/executors/inprocess/stateful.rs index c47aec1e71..a4c88334fd 100644 --- a/libafl/src/executors/inprocess/stateful.rs +++ b/libafl/src/executors/inprocess/stateful.rs @@ -28,15 +28,16 @@ use crate::{ /// The process executor simply calls a target function, as mutable reference to a closure /// The internal state of the executor is made available to the harness. -pub type StatefulInProcessExecutor<'a, H, OT, S, ES> = - StatefulGenericInProcessExecutor; +pub type StatefulInProcessExecutor<'a, H, I, OT, S, ES> = + StatefulGenericInProcessExecutor; /// The process executor simply calls a target function, as boxed `FnMut` trait object /// The internal state of the executor is made available to the harness. -pub type OwnedInProcessExecutor = StatefulGenericInProcessExecutor< - dyn FnMut(&mut ES, &::Input) -> ExitKind, - Box::Input) -> ExitKind>, +pub type OwnedInProcessExecutor = StatefulGenericInProcessExecutor< + dyn FnMut(&mut ES, &I) -> ExitKind, + Box ExitKind>, (), + I, OT, S, ES, @@ -44,17 +45,17 @@ pub type OwnedInProcessExecutor = StatefulGenericInProcessExecutor< /// The inmem executor simply calls a target function, then returns afterwards. /// The harness can access the internal state of the executor. -pub struct StatefulGenericInProcessExecutor { +pub struct StatefulGenericInProcessExecutor { /// The harness function, being executed for each fuzzing loop execution harness_fn: HB, /// The state used as argument of the harness pub exposed_executor_state: ES, /// Inner state of the executor - pub inner: GenericInProcessExecutorInner, + pub inner: GenericInProcessExecutorInner, phantom: PhantomData<(ES, *const H)>, } -impl Debug for StatefulGenericInProcessExecutor +impl Debug for StatefulGenericInProcessExecutor where OT: Debug, { @@ -66,13 +67,13 @@ where } } -impl Executor::Input, S, Z> - for StatefulGenericInProcessExecutor +impl Executor + for StatefulGenericInProcessExecutor where - H: FnMut(&mut ES, &mut S, &::Input) -> ExitKind + Sized, + H: FnMut(&mut ES, &mut S, &I) -> ExitKind + Sized, HB: BorrowMut, - HT: ExecutorHooksTuple<::Input, S>, - OT: ObserversTuple<::Input, S>, + HT: ExecutorHooksTuple, + OT: ObserversTuple, S: HasCorpus + HasExecutions, { fn run_target( @@ -80,7 +81,7 @@ where fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { *state.executions_mut() += 1; unsafe { @@ -98,12 +99,13 @@ where } } -impl HasObservers for StatefulGenericInProcessExecutor +impl HasObservers + for StatefulGenericInProcessExecutor where - H: FnMut(&mut ES, &mut S, &::Input) -> ExitKind + Sized, + H: FnMut(&mut ES, &mut S, &I) -> ExitKind + Sized, HB: BorrowMut, - HT: ExecutorHooksTuple<::Input, S>, - OT: ObserversTuple<::Input, S>, + HT: ExecutorHooksTuple, + OT: ObserversTuple, S: HasCorpus, { type Observers = OT; @@ -118,17 +120,13 @@ where } } -impl<'a, H, OT, S, ES> StatefulInProcessExecutor<'a, H, OT, S, ES> +impl<'a, H, I, OT, S, ES> StatefulInProcessExecutor<'a, H, I, OT, S, ES> where - H: FnMut(&mut ES, &mut S, &::Input) -> ExitKind + Sized, - OT: ObserversTuple<::Input, S>, - S: HasExecutions - + HasSolutions - + HasCorpus - + HasCurrentTestcase - + UsesInput::Input>, - ::Input: Clone + Input, - S::Solutions: Corpus::Input>, + H: FnMut(&mut ES, &mut S, &I) -> ExitKind + Sized, + OT: ObserversTuple, + S: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase + UsesInput, + I: Clone + Input, + S::Solutions: Corpus, { /// Create a new in mem executor with the default timeout (5 sec) pub fn new( @@ -141,7 +139,7 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback::Input, OT, S>, + OF: Feedback, Z: HasObjective, { Self::with_timeout_generic( @@ -169,7 +167,7 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback::Input, OT, S>, + OF: Feedback, Z: HasObjective, { let inner = GenericInProcessExecutorInner::batched_timeout_generic::( @@ -208,7 +206,7 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback::Input, OT, S>, + OF: Feedback, Z: HasObjective, { let inner = GenericInProcessExecutorInner::with_timeout_generic::( @@ -229,7 +227,7 @@ where } } -impl StatefulGenericInProcessExecutor { +impl StatefulGenericInProcessExecutor { /// The executor state given to the harness pub fn exposed_executor_state(&self) -> &ES { &self.exposed_executor_state @@ -241,20 +239,20 @@ impl StatefulGenericInProcessExecutor StatefulGenericInProcessExecutor +impl StatefulGenericInProcessExecutor where - H: FnMut(&mut ES, &mut S, &::Input) -> ExitKind + Sized, + H: FnMut(&mut ES, &mut S, &I) -> ExitKind + Sized, HB: BorrowMut, - HT: ExecutorHooksTuple<::Input, S>, - OT: ObserversTuple<::Input, S>, + HT: ExecutorHooksTuple, + I: Input + Clone, + OT: ObserversTuple, S: HasCorpus + HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase - + UsesInput::Input>, - S::Solutions: Corpus::Input>, - ::Input: Input + Clone, + + UsesInput, + S::Solutions: Corpus, { /// Create a new in mem executor with the default timeout (5 sec) pub fn generic( @@ -268,7 +266,7 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback::Input, OT, S>, + OF: Feedback, Z: HasObjective, { Self::with_timeout_generic( @@ -298,7 +296,7 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback::Input, OT, S>, + OF: Feedback, Z: HasObjective, { let inner = GenericInProcessExecutorInner::batched_timeout_generic::( @@ -334,7 +332,7 @@ where ) -> Result where EM: EventFirer + EventRestarter, - OF: Feedback::Input, OT, S>, + OF: Feedback, Z: HasObjective, { let inner = GenericInProcessExecutorInner::with_timeout_generic::( @@ -363,29 +361,29 @@ where /// The inprocess handlers #[inline] - pub fn hooks(&self) -> &(InProcessHooks, HT) { + pub fn hooks(&self) -> &(InProcessHooks, HT) { self.inner.hooks() } /// The inprocess handlers (mutable) #[inline] - pub fn hooks_mut(&mut self) -> &mut (InProcessHooks, HT) { + pub fn hooks_mut(&mut self) -> &mut (InProcessHooks, HT) { self.inner.hooks_mut() } } -impl HasInProcessHooks - for StatefulGenericInProcessExecutor +impl HasInProcessHooks + for StatefulGenericInProcessExecutor { /// the timeout handler #[inline] - fn inprocess_hooks(&self) -> &InProcessHooks { + fn inprocess_hooks(&self) -> &InProcessHooks { self.inner.inprocess_hooks() } /// the timeout handler #[inline] - fn inprocess_hooks_mut(&mut self) -> &mut InProcessHooks { + fn inprocess_hooks_mut(&mut self) -> &mut InProcessHooks { self.inner.inprocess_hooks_mut() } } diff --git a/libafl/src/executors/inprocess_fork/inner.rs b/libafl/src/executors/inprocess_fork/inner.rs index 50b9bfa53a..778d571036 100644 --- a/libafl/src/executors/inprocess_fork/inner.rs +++ b/libafl/src/executors/inprocess_fork/inner.rs @@ -20,7 +20,6 @@ use nix::{ #[cfg(all(unix, not(target_os = "linux")))] use crate::executors::hooks::timer::{setitimer, Itimerval, Timeval, ITIMER_REAL}; use crate::{ - corpus::Corpus, executors::{ hooks::{ inprocess_fork::{InChildProcessHooks, FORK_EXECUTOR_GLOBAL_DATA}, @@ -34,18 +33,18 @@ use crate::{ }; /// Inner state of GenericInProcessExecutor-like structures. -pub struct GenericInProcessForkExecutorInner { - pub(super) hooks: (InChildProcessHooks, HT), +pub struct GenericInProcessForkExecutorInner { + pub(super) hooks: (InChildProcessHooks, HT), pub(super) shmem_provider: SP, pub(super) observers: OT, #[cfg(target_os = "linux")] pub(super) itimerspec: libc::itimerspec, #[cfg(all(unix, not(target_os = "linux")))] pub(super) itimerval: Itimerval, - pub(super) phantom: PhantomData<(S, EM, Z)>, + pub(super) phantom: PhantomData<(I, S, EM, Z)>, } -impl Debug for GenericInProcessForkExecutorInner +impl Debug for GenericInProcessForkExecutorInner where HT: Debug, OT: Debug, @@ -106,19 +105,19 @@ fn parse_itimerval(timeout: Duration) -> Itimerval { } } -impl GenericInProcessForkExecutorInner +impl GenericInProcessForkExecutorInner where - HT: ExecutorHooksTuple<::Input, S>, + HT: ExecutorHooksTuple, S: HasCorpus, SP: ShMemProvider, - OT: ObserversTuple<::Input, S>, + OT: ObserversTuple, { pub(super) unsafe fn pre_run_target_child( &mut self, fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result<(), Error> { self.shmem_provider.post_fork(true)?; @@ -153,7 +152,7 @@ where fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) { self.observers .post_exec_child_all(state, input, &ExitKind::Ok) @@ -198,21 +197,15 @@ where } } -impl GenericInProcessForkExecutorInner +impl GenericInProcessForkExecutorInner where - HT: ExecutorHooksTuple<::Input, S>, - OT: ObserversTuple<::Input, S>, + HT: ExecutorHooksTuple, + OT: ObserversTuple, S: HasCorpus, { #[inline] /// This function marks the boundary between the fuzzer and the target. - pub fn enter_target( - &mut self, - _fuzzer: &mut Z, - state: &mut S, - _event_mgr: &mut EM, - input: &::Input, - ) { + pub fn enter_target(&mut self, _fuzzer: &mut Z, state: &mut S, _event_mgr: &mut EM, input: &I) { unsafe { let data = &raw mut FORK_EXECUTOR_GLOBAL_DATA; write_volatile( @@ -238,7 +231,7 @@ where _fuzzer: &mut Z, _state: &mut S, _event_mgr: &mut EM, - _input: &::Input, + _input: &I, ) { // do nothing } @@ -294,8 +287,8 @@ where } } -impl HasObservers - for GenericInProcessForkExecutorInner +impl HasObservers + for GenericInProcessForkExecutorInner { type Observers = OT; diff --git a/libafl/src/executors/inprocess_fork/mod.rs b/libafl/src/executors/inprocess_fork/mod.rs index 56f21d1d64..bd02ac8455 100644 --- a/libafl/src/executors/inprocess_fork/mod.rs +++ b/libafl/src/executors/inprocess_fork/mod.rs @@ -14,7 +14,6 @@ use nix::unistd::{fork, ForkResult}; use super::hooks::ExecutorHooksTuple; use crate::{ - corpus::Corpus, executors::{ hooks::inprocess_fork::InProcessForkExecutorGlobalData, inprocess_fork::inner::GenericInProcessForkExecutorInner, Executor, ExitKind, HasObservers, @@ -40,12 +39,12 @@ pub mod stateful; /// /// On Linux, when fuzzing a Rust target, set `panic = "abort"` in your `Cargo.toml` (see [Cargo documentation](https://doc.rust-lang.org/cargo/reference/profiles.html#panic)). /// Else panics can not be caught by `LibAFL`. -pub type InProcessForkExecutor<'a, H, OT, S, SP, EM, Z> = - GenericInProcessForkExecutor<'a, H, (), OT, S, SP, EM, Z>; +pub type InProcessForkExecutor<'a, H, I, OT, S, SP, EM, Z> = + GenericInProcessForkExecutor<'a, H, (), I, OT, S, SP, EM, Z>; -impl<'a, H, OT, S, SP, EM, Z> InProcessForkExecutor<'a, H, OT, S, SP, EM, Z> +impl<'a, H, I, OT, S, SP, EM, Z> InProcessForkExecutor<'a, H, I, OT, S, SP, EM, Z> where - OT: ObserversTuple<::Input, S>, + OT: ObserversTuple, S: HasCorpus, { /// The constructor for `InProcessForkExecutor` @@ -75,12 +74,13 @@ where /// /// On Linux, when fuzzing a Rust target, set `panic = "abort"` in your `Cargo.toml` (see [Cargo documentation](https://doc.rust-lang.org/cargo/reference/profiles.html#panic)). /// Else panics can not be caught by `LibAFL`. -pub struct GenericInProcessForkExecutor<'a, H, HT, OT, S, SP, EM, Z> { +pub struct GenericInProcessForkExecutor<'a, H, HT, I, OT, S, SP, EM, Z> { harness_fn: &'a mut H, - inner: GenericInProcessForkExecutorInner, + inner: GenericInProcessForkExecutorInner, } -impl Debug for GenericInProcessForkExecutor<'_, H, HT, OT, S, SP, EM, Z> +impl Debug + for GenericInProcessForkExecutor<'_, H, HT, I, OT, S, SP, EM, Z> where HT: Debug, OT: Debug, @@ -103,14 +103,14 @@ where } } -impl Executor::Input, S, Z> - for GenericInProcessForkExecutor<'_, H, HT, OT, S, SP, EM, Z> +impl Executor + for GenericInProcessForkExecutor<'_, H, HT, I, OT, S, SP, EM, Z> where - H: FnMut(&::Input) -> ExitKind + Sized, + H: FnMut(&I) -> ExitKind + Sized, S: HasCorpus + HasExecutions, SP: ShMemProvider, - HT: ExecutorHooksTuple<::Input, S>, - OT: ObserversTuple<::Input, S>, + HT: ExecutorHooksTuple, + OT: ObserversTuple, { #[inline] fn run_target( @@ -118,7 +118,7 @@ where fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { *state.executions_mut() += 1; @@ -142,10 +142,10 @@ where } } -impl<'a, H, HT, OT, S, SP, EM, Z> GenericInProcessForkExecutor<'a, H, HT, OT, S, SP, EM, Z> +impl<'a, H, HT, I, OT, S, SP, EM, Z> GenericInProcessForkExecutor<'a, H, HT, I, OT, S, SP, EM, Z> where - HT: ExecutorHooksTuple<::Input, S>, - OT: ObserversTuple<::Input, S>, + HT: ExecutorHooksTuple, + OT: ObserversTuple, S: HasCorpus, { /// Creates a new [`GenericInProcessForkExecutor`] with custom hooks @@ -188,8 +188,8 @@ where { } } -impl HasObservers - for GenericInProcessForkExecutor<'_, H, HT, OT, S, SP, EM, Z> +impl HasObservers + for GenericInProcessForkExecutor<'_, H, HT, I, OT, S, SP, EM, Z> { type Observers = OT; #[inline] @@ -356,7 +356,7 @@ mod tests { }; let mut harness = |_buf: &NopInput| ExitKind::Ok; - let default = InChildProcessHooks::nop(); + let default = InChildProcessHooks::>::nop(); #[cfg(target_os = "linux")] let mut in_process_fork_executor = GenericInProcessForkExecutor { harness_fn: &mut harness, diff --git a/libafl/src/executors/inprocess_fork/stateful.rs b/libafl/src/executors/inprocess_fork/stateful.rs index 547f5497b5..56cbaa7ffc 100644 --- a/libafl/src/executors/inprocess_fork/stateful.rs +++ b/libafl/src/executors/inprocess_fork/stateful.rs @@ -15,7 +15,6 @@ use libafl_bolts::{ use nix::unistd::{fork, ForkResult}; use crate::{ - corpus::Corpus, executors::{ hooks::ExecutorHooksTuple, inprocess_fork::GenericInProcessForkExecutorInner, Executor, ExitKind, HasObservers, @@ -26,12 +25,12 @@ use crate::{ }; /// The `StatefulInProcessForkExecutor` with no user hooks -pub type StatefulInProcessForkExecutor<'a, H, OT, S, SP, ES, EM, Z> = - StatefulGenericInProcessForkExecutor<'a, H, (), OT, S, SP, ES, EM, Z>; +pub type StatefulInProcessForkExecutor<'a, H, I, OT, S, SP, ES, EM, Z> = + StatefulGenericInProcessForkExecutor<'a, H, (), I, OT, S, SP, ES, EM, Z>; -impl<'a, H, OT, S, SP, ES, EM, Z> StatefulInProcessForkExecutor<'a, H, OT, S, SP, ES, EM, Z> +impl<'a, H, I, OT, S, SP, ES, EM, Z> StatefulInProcessForkExecutor<'a, H, I, OT, S, SP, ES, EM, Z> where - OT: ObserversTuple<::Input, S>, + OT: ObserversTuple, S: HasCorpus, { #[expect(clippy::too_many_arguments)] @@ -61,18 +60,18 @@ where } /// [`StatefulGenericInProcessForkExecutor`] is an executor that forks the current process before each execution. Harness can access some internal state. -pub struct StatefulGenericInProcessForkExecutor<'a, H, HT, OT, S, SP, ES, EM, Z> { +pub struct StatefulGenericInProcessForkExecutor<'a, H, HT, I, OT, S, SP, ES, EM, Z> { /// The harness function, being executed for each fuzzing loop execution harness_fn: &'a mut H, /// The state used as argument of the harness pub exposed_executor_state: ES, /// Inner state of the executor - pub inner: GenericInProcessForkExecutorInner, + pub inner: GenericInProcessForkExecutorInner, phantom: PhantomData, } -impl Debug - for StatefulGenericInProcessForkExecutor<'_, H, HT, OT, S, SP, ES, EM, Z> +impl Debug + for StatefulGenericInProcessForkExecutor<'_, H, HT, I, OT, S, SP, ES, EM, Z> where HT: Debug, OT: Debug, @@ -95,14 +94,14 @@ where } } -impl Executor::Input, S, Z> - for StatefulGenericInProcessForkExecutor<'_, H, HT, OT, S, SP, ES, EM, Z> +impl Executor + for StatefulGenericInProcessForkExecutor<'_, H, HT, I, OT, S, SP, ES, EM, Z> where - H: FnMut(&mut ES, &::Input) -> ExitKind + Sized, - HT: ExecutorHooksTuple<<::Corpus as Corpus>::Input, S>, + H: FnMut(&mut ES, &I) -> ExitKind + Sized, + HT: ExecutorHooksTuple, S: HasCorpus + HasExecutions, SP: ShMemProvider, - OT: ObserversTuple<<::Corpus as Corpus>::Input, S>, + OT: ObserversTuple, { #[inline] fn run_target( @@ -110,7 +109,7 @@ where fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { *state.executions_mut() += 1; @@ -134,11 +133,11 @@ where } } -impl<'a, H, HT, OT, S, SP, ES, EM, Z> - StatefulGenericInProcessForkExecutor<'a, H, HT, OT, S, SP, ES, EM, Z> +impl<'a, H, HT, I, OT, S, SP, ES, EM, Z> + StatefulGenericInProcessForkExecutor<'a, H, HT, I, OT, S, SP, ES, EM, Z> where - HT: ExecutorHooksTuple<::Input, S>, - OT: ObserversTuple<::Input, S>, + HT: ExecutorHooksTuple, + OT: ObserversTuple, S: HasCorpus, { /// Creates a new [`StatefulGenericInProcessForkExecutor`] with custom hooks @@ -183,8 +182,8 @@ where } } -impl HasObservers - for StatefulGenericInProcessForkExecutor<'_, H, HT, OT, S, SP, ES, EM, Z> +impl HasObservers + for StatefulGenericInProcessForkExecutor<'_, H, HT, I, OT, S, SP, ES, EM, Z> { type Observers = OT; diff --git a/libafl_frida/src/executor.rs b/libafl_frida/src/executor.rs index 1a74b3acb0..d16a71446b 100644 --- a/libafl_frida/src/executor.rs +++ b/libafl_frida/src/executor.rs @@ -7,20 +7,20 @@ use frida_gum::{ stalker::{NoneEventSink, Stalker}, Gum, MemoryRange, NativePointer, }; +#[cfg(windows)] use libafl::{ corpus::Corpus, + executors::{hooks::inprocess::InProcessHooks, inprocess::HasInProcessHooks}, + inputs::Input, + state::{HasCurrentTestcase, HasSolutions}, +}; +use libafl::{ executors::{Executor, ExitKind, HasObservers, InProcessExecutor}, inputs::{NopTargetBytesConverter, TargetBytesConverter, UsesInput}, observers::ObserversTuple, state::{HasCorpus, HasExecutions, UsesState}, Error, }; -#[cfg(windows)] -use libafl::{ - executors::{hooks::inprocess::InProcessHooks, inprocess::HasInProcessHooks}, - inputs::Input, - state::{HasCurrentTestcase, HasSolutions}, -}; use libafl_bolts::{tuples::RefIndexable, AsSlice}; #[cfg(not(test))] @@ -30,8 +30,8 @@ use crate::helper::{FridaInstrumentationHelper, FridaRuntimeTuple}; use crate::windows_hooks::initialize; /// The [`FridaInProcessExecutor`] is an [`Executor`] that executes the target in the same process, usinig [`frida`](https://frida.re/) for binary-only instrumentation. -pub struct FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC> { - base: InProcessExecutor<'a, H, OT, S>, +pub struct FridaInProcessExecutor<'a, 'b, 'c, H, I, OT, RT, S, TC> { + base: InProcessExecutor<'a, H, I, OT, S>, /// `thread_id` for the Stalker thread_id: Option, /// Frida's dynamic rewriting engine @@ -43,7 +43,7 @@ pub struct FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC> { _phantom: PhantomData<&'b u8>, } -impl Debug for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC> +impl Debug for FridaInProcessExecutor<'_, '_, '_, H, I, OT, RT, S, TC> where OT: Debug, { @@ -56,14 +56,14 @@ where } } -impl Executor::Input, S, Z> - for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC> +impl Executor + for FridaInProcessExecutor<'_, '_, '_, H, I, OT, RT, S, TC> where EM: UsesState, - H: FnMut(&::Input) -> ExitKind, - S: HasCorpus + HasExecutions + UsesInput::Input>, - TC: TargetBytesConverter::Input>, - OT: ObserversTuple<::Input, S>, + H: FnMut(&I) -> ExitKind, + S: HasCorpus + HasExecutions + UsesInput, + TC: TargetBytesConverter, + OT: ObserversTuple, RT: FridaRuntimeTuple, { /// Instruct the target about the input and run @@ -73,7 +73,7 @@ where fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { let target_bytes = self.target_bytes_converter.to_target_bytes(input); self.helper.pre_exec(target_bytes.as_slice())?; @@ -113,7 +113,7 @@ where } } -impl HasObservers for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC> { +impl HasObservers for FridaInProcessExecutor<'_, '_, '_, H, I, OT, RT, S, TC> { type Observers = OT; #[inline] fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> { @@ -126,17 +126,8 @@ impl HasObservers for FridaInProcessExecutor<'_, '_, '_, H, OT } } -impl<'a, 'b, 'c, H, OT, RT, S> - FridaInProcessExecutor< - 'a, - 'b, - 'c, - H, - OT, - RT, - S, - NopTargetBytesConverter<::Input>, - > +impl<'a, 'b, 'c, H, I, OT, RT, S> + FridaInProcessExecutor<'a, 'b, 'c, H, I, OT, RT, S, NopTargetBytesConverter> where S: HasCorpus, RT: FridaRuntimeTuple, @@ -144,7 +135,7 @@ where /// Creates a new [`FridaInProcessExecutor`]. pub fn new( gum: &'a Gum, - base: InProcessExecutor<'a, H, OT, S>, + base: InProcessExecutor<'a, H, I, OT, S>, helper: &'c mut FridaInstrumentationHelper<'b, RT>, ) -> Self { FridaInProcessExecutor::with_target_bytes_converter( @@ -159,7 +150,7 @@ where /// Creates a new [`FridaInProcessExecutor`] tracking the given `thread_id`. pub fn on_thread( gum: &'a Gum, - base: InProcessExecutor<'a, H, OT, S>, + base: InProcessExecutor<'a, H, I, OT, S>, helper: &'c mut FridaInstrumentationHelper<'b, RT>, thread_id: u32, ) -> Self { @@ -173,14 +164,14 @@ where } } -impl<'a, 'b, 'c, H, OT, RT, S, TC> FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC> +impl<'a, 'b, 'c, H, I, OT, RT, S, TC> FridaInProcessExecutor<'a, 'b, 'c, H, I, OT, RT, S, TC> where RT: FridaRuntimeTuple, { /// Creates a new [`FridaInProcessExecutor`]. pub fn with_target_bytes_converter( gum: &'a Gum, - base: InProcessExecutor<'a, H, OT, S>, + base: InProcessExecutor<'a, H, I, OT, S>, helper: &'c mut FridaInstrumentationHelper<'b, RT>, thread_id: Option, target_bytes_converter: TC, @@ -231,30 +222,26 @@ where } #[cfg(windows)] -impl<'a, 'b, 'c, H, OT, RT, S, TC> HasInProcessHooks - for FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC> +impl<'a, 'b, 'c, H, I, OT, RT, S, TC> HasInProcessHooks + for FridaInProcessExecutor<'a, 'b, 'c, H, I, OT, RT, S, TC> where - H: FnMut(&::Input) -> ExitKind, - S: HasSolutions - + HasCorpus - + HasCurrentTestcase - + HasExecutions - + UsesInput::Input>, - S::Solutions: Corpus::Input>, - ::Input: Input, - TC: TargetBytesConverter::Input>, - OT: ObserversTuple<::Input, S>, + H: FnMut(&I) -> ExitKind, + S: HasSolutions + HasCorpus + HasCurrentTestcase + HasExecutions + UsesInput, + S::Solutions: Corpus, + I: Input, + TC: TargetBytesConverter, + OT: ObserversTuple, RT: FridaRuntimeTuple, { /// the timeout handler #[inline] - fn inprocess_hooks(&self) -> &InProcessHooks { + fn inprocess_hooks(&self) -> &InProcessHooks { &self.base.hooks().0 } /// the timeout handler #[inline] - fn inprocess_hooks_mut(&mut self) -> &mut InProcessHooks { + fn inprocess_hooks_mut(&mut self) -> &mut InProcessHooks { &mut self.base.hooks_mut().0 } } diff --git a/libafl_qemu/src/breakpoint.rs b/libafl_qemu/src/breakpoint.rs index e6c1c1ef2c..efdefb005a 100644 --- a/libafl_qemu/src/breakpoint.rs +++ b/libafl_qemu/src/breakpoint.rs @@ -8,49 +8,25 @@ use std::{ }, }; -use libafl::inputs::UsesInput; use libafl_qemu_sys::GuestAddr; -use crate::{command::CommandManager, Qemu}; +use crate::Qemu; #[repr(transparent)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct BreakpointId(u64); // TODO: distinguish breakpoints with IDs instead of addresses to avoid collisions. -pub struct Breakpoint -where - CM: CommandManager, - S: UsesInput, -{ +#[derive(Clone)] +pub struct Breakpoint { id: BreakpointId, addr: GuestAddr, - cmd: Option, + cmd: Option, disable_on_trigger: bool, enabled: bool, } -impl Clone for Breakpoint -where - CM: CommandManager, - S: UsesInput, -{ - fn clone(&self) -> Self { - Self { - id: self.id, - addr: self.addr, - cmd: self.cmd.clone(), - disable_on_trigger: self.disable_on_trigger, - enabled: self.enabled, - } - } -} - -impl Debug for Breakpoint -where - CM: CommandManager, - S: UsesInput, -{ +impl Debug for Breakpoint { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "BP {:?} @ addr {:?}", self.id, self.addr) } @@ -71,68 +47,39 @@ impl Default for BreakpointId { } } -impl Hash for Breakpoint -where - CM: CommandManager, - S: UsesInput, -{ +impl Hash for Breakpoint { fn hash(&self, state: &mut H) { self.id.hash(state); } } -impl PartialEq for Breakpoint -where - CM: CommandManager, - S: UsesInput, -{ +impl PartialEq for Breakpoint { fn eq(&self, other: &Self) -> bool { self.id == other.id } } -impl Eq for Breakpoint -where - CM: CommandManager, - S: UsesInput, -{ -} +impl Eq for Breakpoint {} -impl Display for Breakpoint -where - CM: CommandManager, - S: UsesInput, -{ +impl Display for Breakpoint { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "Breakpoint @vaddr 0x{:x}", self.addr) } } -impl Borrow for Breakpoint -where - CM: CommandManager, - S: UsesInput, -{ +impl Borrow for Breakpoint { fn borrow(&self) -> &BreakpointId { &self.id } } -impl Borrow for Breakpoint -where - CM: CommandManager, - S: UsesInput, -{ +impl Borrow for Breakpoint { fn borrow(&self) -> &GuestAddr { &self.addr } } -impl Breakpoint -where - CM: CommandManager, - S: UsesInput, -{ +impl Breakpoint { // Emu will return with the breakpoint as exit reason. #[must_use] pub fn without_command(addr: GuestAddr, disable_on_trigger: bool) -> Self { @@ -147,7 +94,7 @@ where // Emu will execute the command when it meets the breakpoint. #[must_use] - pub fn with_command(addr: GuestAddr, cmd: CM::Commands, disable_on_trigger: bool) -> Self { + pub fn with_command(addr: GuestAddr, cmd: C, disable_on_trigger: bool) -> Self { Self { id: BreakpointId::new(), addr, @@ -181,7 +128,10 @@ where } } - pub fn trigger(&mut self, qemu: Qemu) -> Option { + pub fn trigger(&mut self, qemu: Qemu) -> Option + where + C: Clone, + { if self.disable_on_trigger { self.disable(qemu); } diff --git a/libafl_qemu/src/command/mod.rs b/libafl_qemu/src/command/mod.rs index a0b517087d..50ccc3a15a 100644 --- a/libafl_qemu/src/command/mod.rs +++ b/libafl_qemu/src/command/mod.rs @@ -6,10 +6,7 @@ use std::{ }; use enum_map::{Enum, EnumMap}; -use libafl::{ - executors::ExitKind, - inputs::{HasTargetBytes, UsesInput}, -}; +use libafl::{executors::ExitKind, inputs::HasTargetBytes}; use libafl_bolts::AsSlice; use libafl_qemu_sys::GuestAddr; #[cfg(feature = "systemmode")] @@ -99,11 +96,11 @@ macro_rules! define_std_command_manager { } } - impl CommandManager for $name + impl CommandManager for $name where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { type Commands = [<$name Commands>]; @@ -115,7 +112,7 @@ macro_rules! define_std_command_manager { match cmd_id { // >::COMMAND_ID => Ok(StdCommandManagerCommands::StartPhysCommandParserCmd(>::parse(qemu, arch_regs_map)?)), - $(<$native_command_parser as NativeCommandParser>::COMMAND_ID => Ok(<$native_command_parser as NativeCommandParser>::parse(qemu, arch_regs_map)?.into())),+, + $(<$native_command_parser as NativeCommandParser>::COMMAND_ID => Ok(<$native_command_parser as NativeCommandParser>::parse(qemu, arch_regs_map)?.into())),+, _ => Err(CommandError::UnknownCommand(cmd_id.into())), } } @@ -128,25 +125,25 @@ macro_rules! define_std_command_manager { $($command($command)),+, } - impl IsCommand<$name, StdEmulatorDriver, ET, S, SM> for [<$name Commands>] + impl IsCommand, StdEmulatorDriver, ET, I, S, SM> for [<$name Commands>] where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { match self { - $([<$name Commands>]::$command(cmd) => <$command as IsCommand<$name, StdEmulatorDriver, ET, S, SM>>::usable_at_runtime(cmd)),+ + $([<$name Commands>]::$command(cmd) => <$command as IsCommand, StdEmulatorDriver, ET, I, S, SM>>::usable_at_runtime(cmd)),+ } } fn run(&self, - emu: &mut Emulator<$name, StdEmulatorDriver, ET, S, SM>, + emu: &mut Emulator, StdEmulatorDriver, ET, I, S, SM>, state: &mut S, - input: &S::Input, + input: &I, ret_reg: Option - ) -> Result, StdEmulatorDriver, ET, S, SM>>, EmulatorDriverError> { + ) -> Result>, EmulatorDriverError> { match self { $([<$name Commands>]::$command(cmd) => cmd.run(emu, state, input, ret_reg)),+ } @@ -164,21 +161,15 @@ macro_rules! define_std_command_manager { }; } -pub trait CommandManager: Sized + Debug -where - S: UsesInput, -{ - type Commands: IsCommand; +pub trait CommandManager: Sized + Debug { + type Commands: IsCommand; fn parse(&self, qemu: Qemu) -> Result; } #[derive(Clone, Debug)] pub struct NopCommandManager; -impl CommandManager for NopCommandManager -where - S: UsesInput, -{ +impl CommandManager for NopCommandManager { type Commands = NopCommand; fn parse(&self, _qemu: Qemu) -> Result { @@ -222,13 +213,10 @@ pub enum NativeExitKind { Crash = bindings::LibaflQemuEndStatus_LIBAFL_QEMU_END_CRASH.0 as u64, // Crash reported in the VM } -pub trait IsCommand: Clone + Debug -where - CM: CommandManager, - S: UsesInput, -{ +pub trait IsCommand: Clone + Debug { /// Used to know whether the command can be run during a backdoor, or if it is necessary to go out of /// the QEMU VM to run the command. + // TODO: Use const when stabilized fn usable_at_runtime(&self) -> bool; /// Command handler. @@ -236,14 +224,13 @@ where /// - `ret_reg`: The register in which the guest return value should be written, if any. /// Returns /// - `InnerHandlerResult`: How the high-level handler should behave - #[expect(clippy::type_complexity)] fn run( &self, - emu: &mut Emulator, + emu: &mut Emulator, state: &mut S, - input: &S::Input, + input: &I, ret_reg: Option, - ) -> Result>, EmulatorDriverError>; + ) -> Result>, EmulatorDriverError>; } #[derive(Debug, Clone)] @@ -272,33 +259,29 @@ impl Display for NopCommand { } } -impl IsCommand for NopCommand -where - CM: CommandManager, - S: UsesInput, -{ +impl IsCommand for NopCommand { fn usable_at_runtime(&self) -> bool { true } fn run( &self, - _emu: &mut Emulator, + _emu: &mut Emulator, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result>, EmulatorDriverError> { + ) -> Result>, EmulatorDriverError> { Ok(None) } } #[derive(Debug, Clone)] pub struct SaveCommand; -impl IsCommand for SaveCommand +impl IsCommand for SaveCommand where - ET: EmulatorModuleTuple, - CM: CommandManager, - S: UsesInput + Unpin, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { @@ -307,12 +290,11 @@ where fn run( &self, - emu: &mut Emulator, + emu: &mut Emulator, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result>, EmulatorDriverError> - { + ) -> Result>, EmulatorDriverError> { let qemu = emu.qemu(); let snapshot_id = emu.snapshot_manager_mut().save(qemu); @@ -327,10 +309,10 @@ where #[derive(Debug, Clone)] pub struct LoadCommand; -impl IsCommand for LoadCommand +impl IsCommand for LoadCommand where - CM: CommandManager, - S: UsesInput, + // CM: CommandManager, + // ET: EmulatorModuleTuple, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { @@ -339,12 +321,11 @@ where fn run( &self, - emu: &mut Emulator, + emu: &mut Emulator, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result>, EmulatorDriverError> - { + ) -> Result>, EmulatorDriverError> { let qemu = emu.qemu(); let snapshot_id = emu @@ -367,11 +348,9 @@ pub struct InputCommand { cpu: CPU, } -impl IsCommand for InputCommand +impl IsCommand for InputCommand where - CM: CommandManager, - S: UsesInput, - S::Input: HasTargetBytes, + I: HasTargetBytes, { fn usable_at_runtime(&self) -> bool { true @@ -379,11 +358,11 @@ where fn run( &self, - emu: &mut Emulator, + emu: &mut Emulator, _state: &mut S, - input: &S::Input, + input: &I, ret_reg: Option, - ) -> Result>, EmulatorDriverError> { + ) -> Result>, EmulatorDriverError> { let qemu = emu.qemu(); let ret_value = self @@ -403,11 +382,12 @@ where pub struct StartCommand { input_location: QemuMemoryChunk, } -impl IsCommand, StdEmulatorDriver, ET, S, SM> for StartCommand +impl IsCommand, StdEmulatorDriver, ET, I, S, SM> + for StartCommand where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { @@ -416,14 +396,11 @@ where fn run( &self, - emu: &mut Emulator, StdEmulatorDriver, ET, S, SM>, + emu: &mut Emulator, StdEmulatorDriver, ET, I, S, SM>, state: &mut S, - input: &S::Input, + input: &I, ret_reg: Option, - ) -> Result< - Option, StdEmulatorDriver, ET, S, SM>>, - EmulatorDriverError, - > { + ) -> Result>, EmulatorDriverError> { if emu.command_manager_mut().start() { return Err(EmulatorDriverError::CommandError( CommandError::StartedTwice, @@ -490,11 +467,12 @@ pub struct EndCommand { exit_kind: Option, } -impl IsCommand, StdEmulatorDriver, ET, S, SM> for EndCommand +impl IsCommand, StdEmulatorDriver, ET, I, S, SM> + for EndCommand where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { @@ -503,14 +481,11 @@ where fn run( &self, - emu: &mut Emulator, StdEmulatorDriver, ET, S, SM>, + emu: &mut Emulator, StdEmulatorDriver, ET, I, S, SM>, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result< - Option, StdEmulatorDriver, ET, S, SM>>, - EmulatorDriverError, - > { + ) -> Result>, EmulatorDriverError> { let qemu = emu.qemu(); if !emu.command_manager_mut().has_started() { @@ -538,22 +513,18 @@ where #[derive(Debug, Clone)] pub struct VersionCommand(u64); -impl IsCommand for VersionCommand -where - CM: CommandManager, - S: UsesInput, -{ +impl IsCommand for VersionCommand { fn usable_at_runtime(&self) -> bool { true } fn run( &self, - _emu: &mut Emulator, + _emu: &mut Emulator, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result>, EmulatorDriverError> { + ) -> Result>, EmulatorDriverError> { let guest_version = self.0; if VERSION == guest_version { @@ -573,11 +544,11 @@ pub struct PageAllowCommand { } #[cfg(feature = "systemmode")] -impl IsCommand for PageAllowCommand +impl IsCommand for PageAllowCommand where - ET: EmulatorModuleTuple, - CM: CommandManager, - S: UsesInput + Unpin, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { fn usable_at_runtime(&self) -> bool { true @@ -585,11 +556,11 @@ where fn run( &self, - emu: &mut Emulator, + emu: &mut Emulator, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result>, EmulatorDriverError> { + ) -> Result>, EmulatorDriverError> { emu.modules_mut() .modules_mut() .allow_page_id_all(self.page_id); @@ -601,11 +572,11 @@ where pub struct AddressAllowCommand { address_range: Range, } -impl IsCommand for AddressAllowCommand +impl IsCommand for AddressAllowCommand where - ET: EmulatorModuleTuple, - CM: CommandManager, - S: UsesInput + Unpin, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { fn usable_at_runtime(&self) -> bool { true @@ -613,11 +584,11 @@ where fn run( &self, - emu: &mut Emulator, + emu: &mut Emulator, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result>, EmulatorDriverError> { + ) -> Result>, EmulatorDriverError> { emu.modules_mut() .modules_mut() .allow_address_range_all(self.address_range.clone()); @@ -629,11 +600,11 @@ where pub struct LqprintfCommand { content: String, } -impl IsCommand for LqprintfCommand +impl IsCommand for LqprintfCommand where - ET: EmulatorModuleTuple, - CM: CommandManager, - S: UsesInput + Unpin, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { fn usable_at_runtime(&self) -> bool { true @@ -641,11 +612,11 @@ where fn run( &self, - _emu: &mut Emulator, + _emu: &mut Emulator, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result>, EmulatorDriverError> { + ) -> Result>, EmulatorDriverError> { print!("LQPRINTF: {}", self.content); Ok(None) } @@ -656,11 +627,11 @@ pub struct TestCommand { expected_value: GuestReg, received_value: GuestReg, } -impl IsCommand for TestCommand +impl IsCommand for TestCommand where - ET: EmulatorModuleTuple, - CM: CommandManager, - S: UsesInput + Unpin, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { fn usable_at_runtime(&self) -> bool { true @@ -668,11 +639,11 @@ where fn run( &self, - _emu: &mut Emulator, + _emu: &mut Emulator, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result>, EmulatorDriverError> { + ) -> Result>, EmulatorDriverError> { if self.expected_value == self.received_value { Ok(None) } else { diff --git a/libafl_qemu/src/command/nyx.rs b/libafl_qemu/src/command/nyx.rs index 4138fbd473..575fb655ea 100644 --- a/libafl_qemu/src/command/nyx.rs +++ b/libafl_qemu/src/command/nyx.rs @@ -16,10 +16,7 @@ use std::{ }; use enum_map::EnumMap; -use libafl::{ - executors::ExitKind, - inputs::{HasTargetBytes, UsesInput}, -}; +use libafl::{executors::ExitKind, inputs::HasTargetBytes}; use libafl_qemu_sys::{GuestAddr, GuestVirtAddr}; use libc::c_uint; use paste::paste; @@ -99,11 +96,11 @@ macro_rules! define_nyx_command_manager { } } - impl CommandManager for $name + impl CommandManager for $name where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { type Commands = [<$name Commands>]; @@ -121,7 +118,7 @@ macro_rules! define_nyx_command_manager { match cmd_id { // >::COMMAND_ID => Ok(StdCommandManagerCommands::StartPhysCommandParserCmd(>::parse(qemu, arch_regs_map)?)), - $(<$native_command_parser as NativeCommandParser>::COMMAND_ID => Ok(<$native_command_parser as NativeCommandParser>::parse(qemu, arch_regs_map)?.into())),+, + $(<$native_command_parser as NativeCommandParser>::COMMAND_ID => Ok(<$native_command_parser as NativeCommandParser>::parse(qemu, arch_regs_map)?.into())),+, _ => Err(CommandError::UnknownCommand(cmd_id.into())), } } @@ -134,25 +131,25 @@ macro_rules! define_nyx_command_manager { $($command($command)),+, } - impl IsCommand<$name, NyxEmulatorDriver, ET, S, SM> for [<$name Commands>] + impl IsCommand, NyxEmulatorDriver, ET, I, S, SM> for [<$name Commands>] where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { match self { - $([<$name Commands>]::$command(cmd) => <$command as IsCommand<$name, NyxEmulatorDriver, ET, S, SM>>::usable_at_runtime(cmd)),+ + $([<$name Commands>]::$command(cmd) => <$command as IsCommand, NyxEmulatorDriver, ET, I, S, SM>>::usable_at_runtime(cmd)),+ } } fn run(&self, - emu: &mut Emulator<$name, NyxEmulatorDriver, ET, S, SM>, + emu: &mut Emulator, NyxEmulatorDriver, ET, I, S, SM>, state: &mut S, - input: &S::Input, + input: &I, ret_reg: Option - ) -> Result, NyxEmulatorDriver, ET, S, SM>>, EmulatorDriverError> { + ) -> Result>, EmulatorDriverError> { match self { $([<$name Commands>]::$command(cmd) => cmd.run(emu, state, input, ret_reg)),+ } @@ -204,22 +201,18 @@ define_nyx_command_manager!( #[derive(Debug, Clone)] pub struct AcquireCommand; -impl IsCommand for AcquireCommand -where - CM: CommandManager, - S: UsesInput, -{ +impl IsCommand for AcquireCommand { fn usable_at_runtime(&self) -> bool { false } fn run( &self, - _emu: &mut Emulator, + _emu: &mut Emulator, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result>, EmulatorDriverError> { + ) -> Result>, EmulatorDriverError> { Ok(None) } } @@ -238,11 +231,12 @@ impl GetPayloadCommand { } } -impl IsCommand, NyxEmulatorDriver, ET, S, SM> for GetPayloadCommand +impl IsCommand, NyxEmulatorDriver, ET, I, S, SM> + for GetPayloadCommand where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { @@ -251,14 +245,11 @@ where fn run( &self, - emu: &mut Emulator, NyxEmulatorDriver, ET, S, SM>, + emu: &mut Emulator, NyxEmulatorDriver, ET, I, S, SM>, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result< - Option, NyxEmulatorDriver, ET, S, SM>>, - EmulatorDriverError, - > { + ) -> Result>, EmulatorDriverError> { let qemu = emu.qemu(); let struct_addr = self.input_struct_location; @@ -301,11 +292,12 @@ where #[derive(Debug, Clone)] pub struct NextPayloadCommand; -impl IsCommand, NyxEmulatorDriver, ET, S, SM> for NextPayloadCommand +impl IsCommand, NyxEmulatorDriver, ET, I, S, SM> + for NextPayloadCommand where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { @@ -314,14 +306,11 @@ where fn run( &self, - emu: &mut Emulator, NyxEmulatorDriver, ET, S, SM>, + emu: &mut Emulator, NyxEmulatorDriver, ET, I, S, SM>, state: &mut S, - input: &S::Input, + input: &I, _ret_reg: Option, - ) -> Result< - Option, NyxEmulatorDriver, ET, S, SM>>, - EmulatorDriverError, - > { + ) -> Result>, EmulatorDriverError> { let qemu = emu.qemu(); if !emu.command_manager_mut().start() { @@ -367,11 +356,12 @@ where #[derive(Debug, Clone)] pub struct SubmitCR3Command; -impl IsCommand, NyxEmulatorDriver, ET, S, SM> for SubmitCR3Command +impl IsCommand, NyxEmulatorDriver, ET, I, S, SM> + for SubmitCR3Command where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { @@ -380,14 +370,11 @@ where fn run( &self, - emu: &mut Emulator, NyxEmulatorDriver, ET, S, SM>, + emu: &mut Emulator, NyxEmulatorDriver, ET, I, S, SM>, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result< - Option, NyxEmulatorDriver, ET, S, SM>>, - EmulatorDriverError, - > { + ) -> Result>, EmulatorDriverError> { let qemu = emu.qemu(); if let Some(current_cpu) = qemu.current_cpu() { @@ -417,11 +404,12 @@ impl RangeSubmitCommand { } } -impl IsCommand, NyxEmulatorDriver, ET, S, SM> for RangeSubmitCommand +impl IsCommand, NyxEmulatorDriver, ET, I, S, SM> + for RangeSubmitCommand where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { @@ -430,14 +418,11 @@ where fn run( &self, - emu: &mut Emulator, NyxEmulatorDriver, ET, S, SM>, + emu: &mut Emulator, NyxEmulatorDriver, ET, I, S, SM>, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result< - Option, NyxEmulatorDriver, ET, S, SM>>, - EmulatorDriverError, - > { + ) -> Result>, EmulatorDriverError> { log::info!("Allow address range: {:#x?}", self.allowed_range); const EMPTY_RANGE: Range = 0..0; @@ -457,11 +442,12 @@ where #[derive(Debug, Clone)] pub struct PanicCommand; -impl IsCommand, NyxEmulatorDriver, ET, S, SM> for PanicCommand +impl IsCommand, NyxEmulatorDriver, ET, I, S, SM> + for PanicCommand where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { @@ -470,14 +456,11 @@ where fn run( &self, - emu: &mut Emulator, NyxEmulatorDriver, ET, S, SM>, + emu: &mut Emulator, NyxEmulatorDriver, ET, I, S, SM>, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result< - Option, NyxEmulatorDriver, ET, S, SM>>, - EmulatorDriverError, - > { + ) -> Result>, EmulatorDriverError> { let qemu = emu.qemu(); if !emu.command_manager_mut().has_started() { @@ -503,11 +486,12 @@ where #[derive(Debug, Clone)] pub struct SubmitPanicCommand; -impl IsCommand, NyxEmulatorDriver, ET, S, SM> for SubmitPanicCommand +impl IsCommand, NyxEmulatorDriver, ET, I, S, SM> + for SubmitPanicCommand where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { @@ -516,14 +500,11 @@ where fn run( &self, - _emu: &mut Emulator, NyxEmulatorDriver, ET, S, SM>, + _emu: &mut Emulator, NyxEmulatorDriver, ET, I, S, SM>, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result< - Option, NyxEmulatorDriver, ET, S, SM>>, - EmulatorDriverError, - > { + ) -> Result>, EmulatorDriverError> { // TODO: add breakpoint to submit panic addr / page and associate it with a panic command unimplemented!() } @@ -540,11 +521,12 @@ impl UserAbortCommand { } } -impl IsCommand, NyxEmulatorDriver, ET, S, SM> for UserAbortCommand +impl IsCommand, NyxEmulatorDriver, ET, I, S, SM> + for UserAbortCommand where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { @@ -553,14 +535,11 @@ where fn run( &self, - _emu: &mut Emulator, NyxEmulatorDriver, ET, S, SM>, + _emu: &mut Emulator, NyxEmulatorDriver, ET, I, S, SM>, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result< - Option, NyxEmulatorDriver, ET, S, SM>>, - EmulatorDriverError, - > { + ) -> Result>, EmulatorDriverError> { log::error!("Nyx Guest Abort: {}", self.content); Ok(Some(EmulatorDriverResult::ShutdownRequest)) @@ -569,11 +548,12 @@ where #[derive(Debug, Clone)] pub struct ReleaseCommand; -impl IsCommand, NyxEmulatorDriver, ET, S, SM> for ReleaseCommand +impl IsCommand, NyxEmulatorDriver, ET, I, S, SM> + for ReleaseCommand where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { fn usable_at_runtime(&self) -> bool { @@ -582,14 +562,11 @@ where fn run( &self, - emu: &mut Emulator, NyxEmulatorDriver, ET, S, SM>, + emu: &mut Emulator, NyxEmulatorDriver, ET, I, S, SM>, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result< - Option, NyxEmulatorDriver, ET, S, SM>>, - EmulatorDriverError, - > { + ) -> Result>, EmulatorDriverError> { let qemu = emu.qemu(); if emu.command_manager().has_started() { @@ -629,22 +606,18 @@ impl GetHostConfigCommand { } } -impl IsCommand for GetHostConfigCommand -where - CM: CommandManager, - S: UsesInput, -{ +impl IsCommand for GetHostConfigCommand { fn usable_at_runtime(&self) -> bool { false } fn run( &self, - emu: &mut Emulator, + emu: &mut Emulator, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result>, EmulatorDriverError> { + ) -> Result>, EmulatorDriverError> { // TODO: check this against fuzzer code let host_config = bindings::host_config_t { bitmap_size: 0, @@ -684,22 +657,18 @@ impl PrintfCommand { } } -impl IsCommand for PrintfCommand -where - CM: CommandManager, - S: UsesInput, -{ +impl IsCommand for PrintfCommand { fn usable_at_runtime(&self) -> bool { false } fn run( &self, - _emu: &mut Emulator, + _emu: &mut Emulator, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result>, EmulatorDriverError> { + ) -> Result>, EmulatorDriverError> { println!("hprintf: {}", self.content); Ok(None) } @@ -717,22 +686,18 @@ impl SetAgentConfigCommand { } } -impl IsCommand for SetAgentConfigCommand -where - CM: CommandManager, - S: UsesInput, -{ +impl IsCommand for SetAgentConfigCommand { fn usable_at_runtime(&self) -> bool { false } fn run( &self, - _emu: &mut Emulator, + _emu: &mut Emulator, _state: &mut S, - _input: &S::Input, + _input: &I, _ret_reg: Option, - ) -> Result>, EmulatorDriverError> { + ) -> Result>, EmulatorDriverError> { let agent_magic = self.agent_config.agent_magic; let agent_version = self.agent_config.agent_version; diff --git a/libafl_qemu/src/command/parser/mod.rs b/libafl_qemu/src/command/parser/mod.rs index 3a9ba121f4..58c2944fa6 100644 --- a/libafl_qemu/src/command/parser/mod.rs +++ b/libafl_qemu/src/command/parser/mod.rs @@ -1,10 +1,7 @@ use std::{ffi::CStr, sync::OnceLock}; use enum_map::{enum_map, EnumMap}; -use libafl::{ - executors::ExitKind, - inputs::{HasTargetBytes, UsesInput}, -}; +use libafl::{executors::ExitKind, inputs::HasTargetBytes}; use libafl_qemu_sys::{GuestAddr, GuestPhysAddr, GuestVirtAddr}; use libc::c_uint; @@ -27,12 +24,8 @@ pub mod nyx; pub static EMU_EXIT_KIND_MAP: OnceLock>> = OnceLock::new(); -pub trait NativeCommandParser -where - CM: CommandManager, - S: UsesInput, -{ - type OutputCommand: IsCommand; +pub trait NativeCommandParser { + type OutputCommand: IsCommand; const COMMAND_ID: c_uint; @@ -43,11 +36,10 @@ where } pub struct InputPhysCommandParser; -impl NativeCommandParser for InputPhysCommandParser +impl NativeCommandParser + for InputPhysCommandParser where - CM: CommandManager, - S: UsesInput, - S::Input: HasTargetBytes, + I: HasTargetBytes, { type OutputCommand = InputCommand; @@ -72,11 +64,10 @@ where } pub struct InputVirtCommandParser; -impl NativeCommandParser for InputVirtCommandParser +impl NativeCommandParser + for InputVirtCommandParser where - CM: CommandManager, - S: UsesInput, - S::Input: HasTargetBytes, + I: HasTargetBytes, { type OutputCommand = InputCommand; @@ -98,12 +89,12 @@ where pub struct StartPhysCommandParser; -impl NativeCommandParser, StdEmulatorDriver, ET, S, SM> +impl NativeCommandParser, StdEmulatorDriver, ET, I, S, SM> for StartPhysCommandParser where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { type OutputCommand = StartCommand; @@ -127,12 +118,12 @@ where pub struct StartVirtCommandParser; -impl NativeCommandParser, StdEmulatorDriver, ET, S, SM> +impl NativeCommandParser, StdEmulatorDriver, ET, I, S, SM> for StartVirtCommandParser where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { type OutputCommand = StartCommand; @@ -155,11 +146,12 @@ where } pub struct SaveCommandParser; -impl NativeCommandParser for SaveCommandParser +impl NativeCommandParser + for SaveCommandParser where - ET: EmulatorModuleTuple, - CM: CommandManager, - S: UsesInput + Unpin, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, SM: IsSnapshotManager, { type OutputCommand = SaveCommand; @@ -175,10 +167,10 @@ where } pub struct LoadCommandParser; -impl NativeCommandParser for LoadCommandParser +impl NativeCommandParser + for LoadCommandParser where - CM: CommandManager, - S: UsesInput, + CM: CommandManager, SM: IsSnapshotManager, { type OutputCommand = LoadCommand; @@ -195,12 +187,12 @@ where pub struct EndCommandParser; -impl NativeCommandParser, StdEmulatorDriver, ET, S, SM> +impl NativeCommandParser, StdEmulatorDriver, ET, I, S, SM> for EndCommandParser where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { type OutputCommand = EndCommand; @@ -229,10 +221,8 @@ where } pub struct VersionCommandParser; -impl NativeCommandParser for VersionCommandParser -where - CM: CommandManager, - S: UsesInput, +impl NativeCommandParser + for VersionCommandParser { type OutputCommand = VersionCommand; @@ -249,12 +239,12 @@ where } pub struct VaddrFilterAllowRangeCommandParser; -impl NativeCommandParser +impl NativeCommandParser for VaddrFilterAllowRangeCommandParser where - ET: EmulatorModuleTuple, - CM: CommandManager, - S: UsesInput + Unpin, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { type OutputCommand = AddressAllowCommand; @@ -272,11 +262,11 @@ where } pub struct LqprintfCommandParser; -impl NativeCommandParser for LqprintfCommandParser +impl NativeCommandParser for LqprintfCommandParser where - ET: EmulatorModuleTuple, - CM: CommandManager, - S: UsesInput + Unpin, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { type OutputCommand = LqprintfCommand; const COMMAND_ID: c_uint = bindings::LibaflQemuCommand_LIBAFL_QEMU_COMMAND_LQPRINTF.0; @@ -306,11 +296,11 @@ where } pub struct TestCommandParser; -impl NativeCommandParser for TestCommandParser +impl NativeCommandParser for TestCommandParser where - ET: EmulatorModuleTuple, - CM: CommandManager, - S: UsesInput + Unpin, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { type OutputCommand = TestCommand; const COMMAND_ID: c_uint = bindings::LibaflQemuCommand_LIBAFL_QEMU_COMMAND_TEST.0; diff --git a/libafl_qemu/src/command/parser/nyx.rs b/libafl_qemu/src/command/parser/nyx.rs index 8c1e359910..99c303626b 100644 --- a/libafl_qemu/src/command/parser/nyx.rs +++ b/libafl_qemu/src/command/parser/nyx.rs @@ -1,10 +1,7 @@ use std::{ffi::CStr, sync::OnceLock}; use enum_map::EnumMap; -use libafl::{ - executors::ExitKind, - inputs::{HasTargetBytes, UsesInput}, -}; +use libafl::{executors::ExitKind, inputs::HasTargetBytes}; use libafl_qemu_sys::GuestVirtAddr; use libc::c_uint; @@ -16,7 +13,7 @@ use crate::{ SetAgentConfigCommand, SubmitCR3Command, SubmitPanicCommand, UserAbortCommand, }, parser::NativeCommandParser, - CommandError, CommandManager, NativeExitKind, + CommandError, NativeExitKind, }, modules::EmulatorModuleTuple, sync_exit::ExitArgs, @@ -40,11 +37,9 @@ fn get_guest_string(qemu: Qemu, string_ptr_reg: Regs) -> Result>> = OnceLock::new(); pub struct AcquireCommandParser; -impl NativeCommandParser for AcquireCommandParser +impl NativeCommandParser for AcquireCommandParser where - CM: CommandManager, - S: UsesInput, - S::Input: HasTargetBytes, + I: HasTargetBytes, { type OutputCommand = AcquireCommand; @@ -59,12 +54,12 @@ where } pub struct GetPayloadCommandParser; -impl NativeCommandParser, NyxEmulatorDriver, ET, S, SM> +impl NativeCommandParser, NyxEmulatorDriver, ET, I, S, SM> for GetPayloadCommandParser where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { type OutputCommand = GetPayloadCommand; @@ -82,12 +77,12 @@ where } pub struct SubmitCR3CommandParser; -impl NativeCommandParser, NyxEmulatorDriver, ET, S, SM> +impl NativeCommandParser, NyxEmulatorDriver, ET, I, S, SM> for SubmitCR3CommandParser where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { type OutputCommand = SubmitCR3Command; @@ -102,12 +97,12 @@ where } pub struct RangeSubmitCommandParser; -impl NativeCommandParser, NyxEmulatorDriver, ET, S, SM> +impl NativeCommandParser, NyxEmulatorDriver, ET, I, S, SM> for RangeSubmitCommandParser where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { type OutputCommand = RangeSubmitCommand; @@ -128,12 +123,12 @@ where } pub struct SubmitPanicCommandParser; -impl NativeCommandParser, NyxEmulatorDriver, ET, S, SM> +impl NativeCommandParser, NyxEmulatorDriver, ET, I, S, SM> for SubmitPanicCommandParser where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { type OutputCommand = SubmitPanicCommand; @@ -148,12 +143,12 @@ where } pub struct PanicCommandParser; -impl NativeCommandParser, NyxEmulatorDriver, ET, S, SM> +impl NativeCommandParser, NyxEmulatorDriver, ET, I, S, SM> for PanicCommandParser where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { type OutputCommand = PanicCommand; @@ -168,12 +163,12 @@ where } pub struct UserAbortCommandParser; -impl NativeCommandParser, NyxEmulatorDriver, ET, S, SM> +impl NativeCommandParser, NyxEmulatorDriver, ET, I, S, SM> for UserAbortCommandParser where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { type OutputCommand = UserAbortCommand; @@ -190,12 +185,12 @@ where } pub struct NextPayloadCommandParser; -impl NativeCommandParser, NyxEmulatorDriver, ET, S, SM> +impl NativeCommandParser, NyxEmulatorDriver, ET, I, S, SM> for NextPayloadCommandParser where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { type OutputCommand = NextPayloadCommand; @@ -211,12 +206,12 @@ where } pub struct ReleaseCommandParser; -impl NativeCommandParser, NyxEmulatorDriver, ET, S, SM> +impl NativeCommandParser, NyxEmulatorDriver, ET, I, S, SM> for ReleaseCommandParser where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { type OutputCommand = ReleaseCommand; @@ -232,11 +227,10 @@ where } pub struct GetHostConfigCommandParser; -impl NativeCommandParser for GetHostConfigCommandParser +impl NativeCommandParser + for GetHostConfigCommandParser where - CM: CommandManager, - S: UsesInput, - S::Input: HasTargetBytes, + I: HasTargetBytes, { type OutputCommand = GetHostConfigCommand; @@ -257,11 +251,10 @@ where } pub struct SetAgentConfigCommandParser; -impl NativeCommandParser for SetAgentConfigCommandParser +impl NativeCommandParser + for SetAgentConfigCommandParser where - CM: CommandManager, - S: UsesInput, - S::Input: HasTargetBytes, + I: HasTargetBytes, { type OutputCommand = SetAgentConfigCommand; @@ -283,11 +276,9 @@ where } pub struct PrintfCommandParser; -impl NativeCommandParser for PrintfCommandParser +impl NativeCommandParser for PrintfCommandParser where - CM: CommandManager, - S: UsesInput, - S::Input: HasTargetBytes, + I: HasTargetBytes, { type OutputCommand = PrintfCommand; diff --git a/libafl_qemu/src/emu/builder.rs b/libafl_qemu/src/emu/builder.rs index c82b6013f5..dec5e32bfe 100644 --- a/libafl_qemu/src/emu/builder.rs +++ b/libafl_qemu/src/emu/builder.rs @@ -1,7 +1,7 @@ use std::marker::PhantomData; use libafl::{ - inputs::{HasTargetBytes, UsesInput}, + inputs::HasTargetBytes, state::{HasExecutions, State}, }; use libafl_bolts::tuples::{tuple_list, Append, Prepend}; @@ -9,7 +9,7 @@ use libafl_bolts::tuples::{tuple_list, Append, Prepend}; #[cfg(feature = "systemmode")] use crate::FastSnapshotManager; use crate::{ - command::{CommandManager, NopCommandManager, StdCommandManager}, + command::{NopCommandManager, StdCommandManager}, config::QemuConfigBuilder, modules::{EmulatorModule, EmulatorModuleTuple}, Emulator, NopEmulatorDriver, NopSnapshotManager, QemuInitError, QemuParams, StdEmulatorDriver, @@ -27,29 +27,26 @@ use crate::{config::QemuConfig, Qemu}; /// - with a QEMU-compatible CLI. It will be given to QEMU as-is. The first argument should always be a path to the running binary, as expected by execve. /// - with an instance of [`QemuConfig`]. It is a more programmatic way to configure [`Qemu`]. It should be built using [`QemuConfigBuilder`]. #[derive(Clone)] -pub struct EmulatorBuilder -where - S: UsesInput, -{ +pub struct EmulatorBuilder { modules: ET, driver: ED, snapshot_manager: SM, command_manager: CM, qemu_parameters: Option, - phantom: PhantomData, + phantom: PhantomData<(C, I, S)>, } -impl +impl EmulatorBuilder< + C, NopCommandManager, NopEmulatorDriver, (), QemuConfigBuilder, + I, S, NopSnapshotManager, > -where - S: UsesInput, { #[must_use] pub fn empty() -> Self { @@ -65,18 +62,20 @@ where } #[cfg(feature = "usermode")] -impl +impl EmulatorBuilder< + C, StdCommandManager, StdEmulatorDriver, (), QemuConfigBuilder, + I, S, StdSnapshotManager, > where S: State + HasExecutions + Unpin, - S::Input: HasTargetBytes, + I: HasTargetBytes, { #[must_use] #[expect(clippy::should_implement_trait)] @@ -93,18 +92,20 @@ where } #[cfg(feature = "systemmode")] -impl +impl EmulatorBuilder< + C, StdCommandManager, StdEmulatorDriver, (), QemuConfigBuilder, + I, S, StdSnapshotManager, > where S: State + HasExecutions + Unpin, - S::Input: HasTargetBytes, + I: HasTargetBytes, { #[expect(clippy::should_implement_trait)] #[must_use] @@ -119,9 +120,10 @@ where } } } -impl EmulatorBuilder +impl EmulatorBuilder where - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { fn new( modules: ET, @@ -140,10 +142,10 @@ where } } - pub fn build(self) -> Result, QemuInitError> + #[allow(clippy::type_complexity)] + pub fn build(self) -> Result, QemuInitError> where - CM: CommandManager, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, QP: TryInto, QemuInitError: From, { @@ -162,16 +164,16 @@ where } } -impl EmulatorBuilder +impl EmulatorBuilder where - CM: CommandManager, - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { #[must_use] pub fn qemu_parameters( self, qemu_parameters: QP2, - ) -> EmulatorBuilder + ) -> EmulatorBuilder where QP2: Into, { @@ -184,10 +186,13 @@ where ) } - pub fn prepend_module(self, module: EM) -> EmulatorBuilder + pub fn prepend_module( + self, + module: EM, + ) -> EmulatorBuilder where - EM: EmulatorModule + Unpin, - ET: EmulatorModuleTuple, + EM: EmulatorModule + Unpin, + ET: EmulatorModuleTuple, { EmulatorBuilder::new( self.modules.prepend(module), @@ -198,10 +203,10 @@ where ) } - pub fn append_module(self, module: EM) -> EmulatorBuilder + pub fn append_module(self, module: EM) -> EmulatorBuilder where - EM: EmulatorModule + Unpin, - ET: EmulatorModuleTuple, + EM: EmulatorModule + Unpin, + ET: EmulatorModuleTuple, { EmulatorBuilder::new( self.modules.append(module), @@ -212,7 +217,7 @@ where ) } - pub fn driver(self, driver: ED2) -> EmulatorBuilder { + pub fn driver(self, driver: ED2) -> EmulatorBuilder { EmulatorBuilder::new( self.modules, driver, @@ -225,10 +230,7 @@ where pub fn command_manager( self, command_manager: CM2, - ) -> EmulatorBuilder - where - CM2: CommandManager, - { + ) -> EmulatorBuilder { EmulatorBuilder::new( self.modules, self.driver, @@ -238,7 +240,7 @@ where ) } - pub fn modules(self, modules: ET2) -> EmulatorBuilder { + pub fn modules(self, modules: ET2) -> EmulatorBuilder { EmulatorBuilder::new( modules, self.driver, @@ -251,7 +253,7 @@ where pub fn snapshot_manager( self, snapshot_manager: SM2, - ) -> EmulatorBuilder { + ) -> EmulatorBuilder { EmulatorBuilder::new( self.modules, self.driver, diff --git a/libafl_qemu/src/emu/drivers/mod.rs b/libafl_qemu/src/emu/drivers/mod.rs index 5eb8616937..0b61094a3b 100644 --- a/libafl_qemu/src/emu/drivers/mod.rs +++ b/libafl_qemu/src/emu/drivers/mod.rs @@ -3,11 +3,7 @@ use std::{cell::OnceCell, fmt::Debug}; -use libafl::{ - executors::ExitKind, - inputs::{HasTargetBytes, UsesInput}, - observers::ObserversTuple, -}; +use libafl::{executors::ExitKind, inputs::HasTargetBytes, observers::ObserversTuple}; use libafl_bolts::os::{unix_signals::Signal, CTRL_C_EXIT}; use typed_builder::TypedBuilder; @@ -30,13 +26,9 @@ pub mod nyx; pub use nyx::{NyxEmulatorDriver, NyxEmulatorDriverBuilder}; #[derive(Debug, Clone)] -pub enum EmulatorDriverResult -where - CM: CommandManager, - S: UsesInput, -{ +pub enum EmulatorDriverResult { /// Return to the harness immediately. Can happen at any point of the run when the handler is not supposed to handle a request. - ReturnToHarness(EmulatorExitResult), + ReturnToHarness(EmulatorExitResult), /// The run is over and the emulator is ready for the next iteration. EndOfRun(ExitKind), @@ -66,36 +58,37 @@ impl From for EmulatorDriverError { /// An Emulator Driver. // TODO remove 'static when specialization will be stable -pub trait EmulatorDriver: 'static + Sized +pub trait EmulatorDriver: 'static + Sized where - CM: CommandManager, - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, + C: Clone, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { /// Just before calling user's harness for the first time. /// Called only once - fn first_harness_exec(emulator: &mut Emulator, state: &mut S) { + fn first_harness_exec(emulator: &mut Emulator, state: &mut S) { emulator.modules.first_exec_all(emulator.qemu, state); } /// Just before calling user's harness fn pre_harness_exec( - emulator: &mut Emulator, + emulator: &mut Emulator, state: &mut S, - input: &S::Input, + input: &I, ) { emulator.modules.pre_exec_all(emulator.qemu, state, input); } /// Just after returning from user's harness fn post_harness_exec( - emulator: &mut Emulator, - input: &S::Input, + emulator: &mut Emulator, + input: &I, observers: &mut OT, state: &mut S, exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, + OT: ObserversTuple, { emulator .modules @@ -103,16 +96,15 @@ where } /// Just before entering QEMU - fn pre_qemu_exec(_emulator: &mut Emulator, _input: &S::Input) {} + fn pre_qemu_exec(_emulator: &mut Emulator, _input: &I) {} /// Just after QEMU exits - #[expect(clippy::type_complexity)] fn post_qemu_exec( - _emulator: &mut Emulator, + _emulator: &mut Emulator, _state: &mut S, - exit_reason: &mut Result, EmulatorExitError>, - _input: &S::Input, - ) -> Result>, EmulatorDriverError> { + exit_reason: &mut Result, EmulatorExitError>, + _input: &I, + ) -> Result>, EmulatorDriverError> { match exit_reason { Ok(reason) => Ok(Some(EmulatorDriverResult::ReturnToHarness(reason.clone()))), Err(error) => Err(error.clone().into()), @@ -121,11 +113,12 @@ where } pub struct NopEmulatorDriver; -impl EmulatorDriver for NopEmulatorDriver +impl EmulatorDriver for NopEmulatorDriver where - CM: CommandManager, - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, + C: Clone, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { } @@ -180,24 +173,25 @@ impl StdEmulatorDriver { } // TODO: replace handlers with generics to permit compile-time customization of handlers -impl EmulatorDriver for StdEmulatorDriver +impl EmulatorDriver for StdEmulatorDriver where - CM: CommandManager, - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + C: IsCommand, + CM: CommandManager, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { - fn first_harness_exec(emulator: &mut Emulator, state: &mut S) { + fn first_harness_exec(emulator: &mut Emulator, state: &mut S) { if !emulator.driver.hooks_locked { emulator.modules.first_exec_all(emulator.qemu, state); } } fn pre_harness_exec( - emulator: &mut Emulator, + emulator: &mut Emulator, state: &mut S, - input: &S::Input, + input: &I, ) { if !emulator.driver.hooks_locked { emulator.modules.pre_exec_all(emulator.qemu, state, input); @@ -216,13 +210,13 @@ where } fn post_harness_exec( - emulator: &mut Emulator, - input: &S::Input, + emulator: &mut Emulator, + input: &I, observers: &mut OT, state: &mut S, exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, + OT: ObserversTuple, { if !emulator.driver.hooks_locked { emulator @@ -231,16 +225,17 @@ where } } - fn pre_qemu_exec(_emulator: &mut Emulator, _input: &S::Input) {} + fn pre_qemu_exec(_emulator: &mut Emulator, _input: &I) {} fn post_qemu_exec( - emulator: &mut Emulator, + emulator: &mut Emulator, state: &mut S, - exit_reason: &mut Result, EmulatorExitError>, - input: &S::Input, - ) -> Result>, EmulatorDriverError> { + exit_reason: &mut Result, EmulatorExitError>, + input: &I, + ) -> Result>, EmulatorDriverError> { let qemu = emulator.qemu(); + // Check if QEMU existed because of an error or to handle some request let mut exit_reason = match exit_reason { Ok(exit_reason) => exit_reason, Err(exit_error) => match exit_error { @@ -254,7 +249,8 @@ where }, }; - let (command, ret_reg): (Option, Option) = match &mut exit_reason { + // If QEMU stopped because of a request, handle it here + let (command, ret_reg): (Option, Option) = match &mut exit_reason { EmulatorExitResult::QemuExit(shutdown_cause) => match shutdown_cause { QemuShutdownCause::HostSignal(signal) => { signal.handle(); @@ -279,6 +275,7 @@ where } }; + // If QEMU requested to handle a command, run it here. if let Some(cmd) = command { if emulator.driver.print_commands { println!("Received command: {cmd:?}"); @@ -292,14 +289,13 @@ where } } -impl TryFrom> for ExitKind +impl TryFrom> for ExitKind where - CM: CommandManager, - S: UsesInput, + C: Debug, { type Error = String; - fn try_from(value: EmulatorDriverResult) -> Result { + fn try_from(value: EmulatorDriverResult) -> Result { match value { EmulatorDriverResult::ReturnToHarness(unhandled_qemu_exit) => { Err(format!("Unhandled QEMU exit: {:?}", &unhandled_qemu_exit)) diff --git a/libafl_qemu/src/emu/drivers/nyx.rs b/libafl_qemu/src/emu/drivers/nyx.rs index 1a3ec39e6d..07e658d82c 100644 --- a/libafl_qemu/src/emu/drivers/nyx.rs +++ b/libafl_qemu/src/emu/drivers/nyx.rs @@ -1,10 +1,6 @@ use std::{cell::OnceCell, cmp::min, ptr, slice::from_raw_parts}; -use libafl::{ - executors::ExitKind, - inputs::{HasTargetBytes, UsesInput}, - observers::ObserversTuple, -}; +use libafl::{executors::ExitKind, inputs::HasTargetBytes, observers::ObserversTuple}; use libafl_bolts::os::CTRL_C_EXIT; use typed_builder::TypedBuilder; @@ -107,24 +103,25 @@ impl NyxEmulatorDriver { } } -impl EmulatorDriver for NyxEmulatorDriver +impl EmulatorDriver for NyxEmulatorDriver where - CM: CommandManager, - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, - S::Input: HasTargetBytes, + C: IsCommand, + CM: CommandManager, + ET: EmulatorModuleTuple, + I: HasTargetBytes + Unpin, + S: Unpin, SM: IsSnapshotManager, { - fn first_harness_exec(emulator: &mut Emulator, state: &mut S) { + fn first_harness_exec(emulator: &mut Emulator, state: &mut S) { if !emulator.driver.hooks_locked { emulator.modules.first_exec_all(emulator.qemu, state); } } fn pre_harness_exec( - emulator: &mut Emulator, + emulator: &mut Emulator, state: &mut S, - input: &S::Input, + input: &I, ) { if !emulator.driver.hooks_locked { emulator.modules.pre_exec_all(emulator.qemu, state, input); @@ -138,13 +135,13 @@ where } fn post_harness_exec( - emulator: &mut Emulator, - input: &S::Input, + emulator: &mut Emulator, + input: &I, observers: &mut OT, state: &mut S, exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, + OT: ObserversTuple, { if !emulator.driver.hooks_locked { emulator @@ -153,14 +150,14 @@ where } } - fn pre_qemu_exec(_emulator: &mut Emulator, _input: &S::Input) {} + fn pre_qemu_exec(_emulator: &mut Emulator, _input: &I) {} fn post_qemu_exec( - emulator: &mut Emulator, + emulator: &mut Emulator, state: &mut S, - exit_reason: &mut Result, EmulatorExitError>, - input: &S::Input, - ) -> Result>, EmulatorDriverError> { + exit_reason: &mut Result, EmulatorExitError>, + input: &I, + ) -> Result>, EmulatorDriverError> { let qemu = emulator.qemu(); let mut exit_reason = match exit_reason { @@ -176,7 +173,7 @@ where }, }; - let (command, ret_reg): (Option, Option) = match &mut exit_reason { + let (command, ret_reg): (Option, Option) = match &mut exit_reason { EmulatorExitResult::QemuExit(shutdown_cause) => match shutdown_cause { QemuShutdownCause::HostSignal(signal) => { signal.handle(); diff --git a/libafl_qemu/src/emu/hooks.rs b/libafl_qemu/src/emu/hooks.rs index 88b8c00350..f561d78463 100644 --- a/libafl_qemu/src/emu/hooks.rs +++ b/libafl_qemu/src/emu/hooks.rs @@ -2,7 +2,7 @@ use std::{fmt::Debug, marker::PhantomData, mem::transmute, pin::Pin, ptr}; -use libafl::{executors::ExitKind, inputs::UsesInput, observers::ObserversTuple}; +use libafl::{executors::ExitKind, observers::ObserversTuple}; use libafl_qemu_sys::{CPUStatePtr, FatPtr, GuestAddr, GuestUsize, TCGTemp}; #[cfg(feature = "usermode")] @@ -73,13 +73,13 @@ macro_rules! hook_to_repr { static mut EMULATOR_MODULES: *mut () = ptr::null_mut(); #[cfg(feature = "usermode")] -pub extern "C" fn crash_hook_wrapper(target_sig: i32) +pub extern "C" fn crash_hook_wrapper(target_sig: i32) where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput, + ET: EmulatorModuleTuple, + S: Unpin, { unsafe { - let emulator_modules = EmulatorModules::::emulator_modules_mut().unwrap(); + let emulator_modules = EmulatorModules::::emulator_modules_mut().unwrap(); let qemu = Qemu::get_unchecked(); let crash_hooks_ptr = &raw mut emulator_modules.hooks.hook_collection.crash_hooks; @@ -87,12 +87,12 @@ where for crash_hook in &mut (*crash_hooks_ptr) { match crash_hook { HookRepr::Function(ptr) => { - let func: CrashHookFn = transmute(*ptr); + let func: CrashHookFn = transmute(*ptr); func(qemu, emulator_modules, target_sig); } HookRepr::Closure(ptr) => { - let func: &mut CrashHookClosure = - &mut *(ptr::from_mut::(ptr) as *mut CrashHookClosure); + let func: &mut CrashHookClosure = + &mut *(ptr::from_mut::(ptr) as *mut CrashHookClosure); func(qemu, emulator_modules, target_sig); } HookRepr::Empty => (), @@ -103,14 +103,13 @@ where /// High-level `Emulator` modules, using `QemuHooks`. #[derive(Debug)] -pub struct EmulatorModules { +pub struct EmulatorModules { modules: Pin>, - hooks: EmulatorHooks, - phantom: PhantomData, + hooks: EmulatorHooks, } #[derive(Debug)] -struct EmulatorHookCollection { +struct EmulatorHookCollection { instruction_hooks: Vec>>, backdoor_hooks: Vec>>, edge_hooks: Vec>>>, @@ -132,10 +131,10 @@ struct EmulatorHookCollection { #[cfg(feature = "usermode")] crash_hooks: Vec, - phantom: PhantomData<(ET, S)>, + phantom: PhantomData<(ET, I, S)>, } -impl Default for EmulatorHookCollection { +impl Default for EmulatorHookCollection { fn default() -> Self { Self { instruction_hooks: Vec::default(), @@ -166,14 +165,15 @@ impl Default for EmulatorHookCollection { /// Hook collection, #[derive(Debug)] -pub struct EmulatorHooks { +pub struct EmulatorHooks { qemu_hooks: QemuHooks, - hook_collection: EmulatorHookCollection, + hook_collection: EmulatorHookCollection, } -impl EmulatorHooks +impl EmulatorHooks where - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { #[must_use] pub fn new(qemu_hooks: QemuHooks) -> Self { @@ -191,7 +191,7 @@ where pub fn instruction_closure( &mut self, addr: GuestAddr, - hook: InstructionHookClosure, + hook: InstructionHookClosure, invalidate_block: bool, ) -> InstructionHookId { let fat: FatPtr = unsafe { transmute(hook) }; @@ -213,7 +213,7 @@ where let id = self.qemu_hooks.add_instruction_hooks( &mut *hook_state, addr, - closure_instruction_hook_wrapper::, + closure_instruction_hook_wrapper::, invalidate_block, ); self.hook_collection @@ -230,7 +230,7 @@ where pub fn instructions( &mut self, addr: GuestAddr, - hook: InstructionHook, + hook: InstructionHook, invalidate_block: bool, ) -> Option { match hook { @@ -250,14 +250,14 @@ where pub fn instruction_function( &mut self, addr: GuestAddr, - hook: InstructionHookFn, + hook: InstructionHookFn, invalidate_block: bool, ) -> InstructionHookId { unsafe { self.qemu_hooks.add_instruction_hooks( transmute(hook), addr, - func_instruction_hook_wrapper::, + func_instruction_hook_wrapper::, invalidate_block, ) } @@ -265,13 +265,13 @@ where pub fn edges( &mut self, - generation_hook: EdgeGenHook, - execution_hook: EdgeExecHook, + generation_hook: EdgeGenHook, + execution_hook: EdgeExecHook, ) -> EdgeHookId { unsafe { let gen = get_raw_hook!( generation_hook, - edge_gen_hook_wrapper::, + edge_gen_hook_wrapper::, unsafe extern "C" fn( &mut TcgHookState<1, EdgeHookId>, src: GuestAddr, @@ -281,7 +281,7 @@ where let exec = get_raw_hook!( execution_hook, - edge_0_exec_hook_wrapper::, + edge_0_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<1, EdgeHookId>, id: u64) ); @@ -319,20 +319,20 @@ where pub fn blocks( &mut self, - generation_hook: BlockGenHook, - post_generation_hook: BlockPostGenHook, - execution_hook: BlockExecHook, + generation_hook: BlockGenHook, + post_generation_hook: BlockPostGenHook, + execution_hook: BlockExecHook, ) -> BlockHookId { unsafe { let gen = get_raw_hook!( generation_hook, - block_gen_hook_wrapper::, + block_gen_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<1, BlockHookId>, pc: GuestAddr) -> u64 ); let postgen = get_raw_hook!( post_generation_hook, - block_post_gen_hook_wrapper::, + block_post_gen_hook_wrapper::, unsafe extern "C" fn( &mut TcgHookState<1, BlockHookId>, pc: GuestAddr, @@ -342,7 +342,7 @@ where let exec = get_raw_hook!( execution_hook, - block_0_exec_hook_wrapper::, + block_0_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<1, BlockHookId>, id: u64) ); @@ -382,19 +382,19 @@ where pub fn cpu_runs( &mut self, - pre_exec_hook: CpuPreRunHook, - post_exec_hook: CpuPostRunHook, + pre_exec_hook: CpuPreRunHook, + post_exec_hook: CpuPostRunHook, ) -> CpuRunHookId { unsafe { let pre_run = get_raw_hook!( pre_exec_hook, - cpu_run_pre_exec_hook_wrapper::, + cpu_run_pre_exec_hook_wrapper::, unsafe extern "C" fn(&mut HookState, cpu: CPUStatePtr) ); let post_run = get_raw_hook!( post_exec_hook, - cpu_run_post_exec_hook_wrapper::, + cpu_run_post_exec_hook_wrapper::, unsafe extern "C" fn(&mut HookState, cpu: CPUStatePtr) ); @@ -434,17 +434,17 @@ where #[expect(clippy::similar_names)] pub fn reads( &mut self, - generation_hook: ReadGenHook, - execution_hook_1: ReadExecHook, - execution_hook_2: ReadExecHook, - execution_hook_4: ReadExecHook, - execution_hook_8: ReadExecHook, - execution_hook_n: ReadExecNHook, + generation_hook: ReadGenHook, + execution_hook_1: ReadExecHook, + execution_hook_2: ReadExecHook, + execution_hook_4: ReadExecHook, + execution_hook_8: ReadExecHook, + execution_hook_n: ReadExecNHook, ) -> ReadHookId { unsafe { let gen = get_raw_hook!( generation_hook, - read_gen_hook_wrapper::, + read_gen_hook_wrapper::, unsafe extern "C" fn( &mut TcgHookState<5, ReadHookId>, pc: GuestAddr, @@ -454,27 +454,27 @@ where ); let exec1 = get_raw_hook!( execution_hook_1, - read_0_exec_hook_wrapper::, + read_0_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<5, ReadHookId>, id: u64, addr: GuestAddr) ); let exec2 = get_raw_hook!( execution_hook_2, - read_1_exec_hook_wrapper::, + read_1_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<5, ReadHookId>, id: u64, addr: GuestAddr) ); let exec4 = get_raw_hook!( execution_hook_4, - read_2_exec_hook_wrapper::, + read_2_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<5, ReadHookId>, id: u64, addr: GuestAddr) ); let exec8 = get_raw_hook!( execution_hook_8, - read_3_exec_hook_wrapper::, + read_3_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<5, ReadHookId>, id: u64, addr: GuestAddr) ); let execn = get_raw_hook!( execution_hook_n, - read_4_exec_hook_wrapper::, + read_4_exec_hook_wrapper::, unsafe extern "C" fn( &mut TcgHookState<5, ReadHookId>, id: u64, @@ -526,17 +526,17 @@ where #[expect(clippy::similar_names)] pub fn writes( &mut self, - generation_hook: WriteGenHook, - execution_hook_1: WriteExecHook, - execution_hook_2: WriteExecHook, - execution_hook_4: WriteExecHook, - execution_hook_8: WriteExecHook, - execution_hook_n: WriteExecNHook, + generation_hook: WriteGenHook, + execution_hook_1: WriteExecHook, + execution_hook_2: WriteExecHook, + execution_hook_4: WriteExecHook, + execution_hook_8: WriteExecHook, + execution_hook_n: WriteExecNHook, ) -> WriteHookId { unsafe { let gen = get_raw_hook!( generation_hook, - write_gen_hook_wrapper::, + write_gen_hook_wrapper::, unsafe extern "C" fn( &mut TcgHookState<5, WriteHookId>, pc: GuestAddr, @@ -546,27 +546,27 @@ where ); let exec1 = get_raw_hook!( execution_hook_1, - write_0_exec_hook_wrapper::, + write_0_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<5, WriteHookId>, id: u64, addr: GuestAddr) ); let exec2 = get_raw_hook!( execution_hook_2, - write_1_exec_hook_wrapper::, + write_1_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<5, WriteHookId>, id: u64, addr: GuestAddr) ); let exec4 = get_raw_hook!( execution_hook_4, - write_2_exec_hook_wrapper::, + write_2_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<5, WriteHookId>, id: u64, addr: GuestAddr) ); let exec8 = get_raw_hook!( execution_hook_8, - write_3_exec_hook_wrapper::, + write_3_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<5, WriteHookId>, id: u64, addr: GuestAddr) ); let execn = get_raw_hook!( execution_hook_n, - write_4_exec_hook_wrapper::, + write_4_exec_hook_wrapper::, unsafe extern "C" fn( &mut TcgHookState<5, WriteHookId>, id: u64, @@ -617,16 +617,16 @@ where pub fn cmps( &mut self, - generation_hook: CmpGenHook, - execution_hook_1: CmpExecHook, - execution_hook_2: CmpExecHook, - execution_hook_4: CmpExecHook, - execution_hook_8: CmpExecHook, + generation_hook: CmpGenHook, + execution_hook_1: CmpExecHook, + execution_hook_2: CmpExecHook, + execution_hook_4: CmpExecHook, + execution_hook_8: CmpExecHook, ) -> CmpHookId { unsafe { let gen = get_raw_hook!( generation_hook, - cmp_gen_hook_wrapper::, + cmp_gen_hook_wrapper::, unsafe extern "C" fn( &mut TcgHookState<4, CmpHookId>, pc: GuestAddr, @@ -635,22 +635,22 @@ where ); let exec1 = get_raw_hook!( execution_hook_1, - cmp_0_exec_hook_wrapper::, + cmp_0_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<4, CmpHookId>, id: u64, v0: u8, v1: u8) ); let exec2 = get_raw_hook!( execution_hook_2, - cmp_1_exec_hook_wrapper::, + cmp_1_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<4, CmpHookId>, id: u64, v0: u16, v1: u16) ); let exec4 = get_raw_hook!( execution_hook_4, - cmp_2_exec_hook_wrapper::, + cmp_2_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<4, CmpHookId>, id: u64, v0: u32, v1: u32) ); let exec8 = get_raw_hook!( execution_hook_8, - cmp_3_exec_hook_wrapper::, + cmp_3_exec_hook_wrapper::, unsafe extern "C" fn(&mut TcgHookState<4, CmpHookId>, id: u64, v0: u64, v1: u64) ); @@ -695,7 +695,10 @@ where /// # Safety /// Will dereference the hook as [`FatPtr`]. - pub unsafe fn backdoor_closure(&mut self, hook: BackdoorHookClosure) -> BackdoorHookId { + pub unsafe fn backdoor_closure( + &mut self, + hook: BackdoorHookClosure, + ) -> BackdoorHookId { unsafe { let fat: FatPtr = transmute(hook); self.hook_collection @@ -713,7 +716,7 @@ where let id = self .qemu_hooks - .add_backdoor_hook(&mut *hook_state, closure_backdoor_hook_wrapper::); + .add_backdoor_hook(&mut *hook_state, closure_backdoor_hook_wrapper::); self.hook_collection .backdoor_hooks @@ -727,16 +730,16 @@ where } } - pub fn backdoor_function(&self, hook: BackdoorHookFn) -> BackdoorHookId { + pub fn backdoor_function(&self, hook: BackdoorHookFn) -> BackdoorHookId { unsafe { self.qemu_hooks - .add_backdoor_hook(transmute(hook), func_backdoor_hook_wrapper::) + .add_backdoor_hook(transmute(hook), func_backdoor_hook_wrapper::) } } /// # Safety /// This can call through to a potentialy unsafe `backtoor_function` - pub unsafe fn backdoor(&mut self, hook: BackdoorHook) -> Option { + pub unsafe fn backdoor(&mut self, hook: BackdoorHook) -> Option { match hook { Hook::Function(f) => Some(self.backdoor_function(f)), Hook::Closure(c) => Some(self.backdoor_closure(c)), @@ -748,7 +751,7 @@ where } } - pub fn thread_creation(&mut self, hook: NewThreadHook) -> Option { + pub fn thread_creation(&mut self, hook: NewThreadHook) -> Option { match hook { Hook::Function(f) => Some(self.thread_creation_function(f)), Hook::Closure(c) => Some(self.thread_creation_closure(c)), @@ -760,16 +763,16 @@ where } } - pub fn thread_creation_function(&mut self, hook: NewThreadHookFn) -> NewThreadHookId { + pub fn thread_creation_function(&mut self, hook: NewThreadHookFn) -> NewThreadHookId { unsafe { self.qemu_hooks - .add_new_thread_hook(transmute(hook), func_new_thread_hook_wrapper::) + .add_new_thread_hook(transmute(hook), func_new_thread_hook_wrapper::) } } pub fn thread_creation_closure( &mut self, - hook: NewThreadHookClosure, + hook: NewThreadHookClosure, ) -> NewThreadHookId { unsafe { let fat: FatPtr = transmute(hook); @@ -786,9 +789,10 @@ where .get_unchecked_mut() .1; - let id = self - .qemu_hooks - .add_new_thread_hook(&mut *hook_state, closure_new_thread_hook_wrapper::); + let id = self.qemu_hooks.add_new_thread_hook( + &mut *hook_state, + closure_new_thread_hook_wrapper::, + ); self.hook_collection .new_thread_hooks .last_mut() @@ -802,12 +806,13 @@ where } #[cfg(feature = "usermode")] -impl EmulatorHooks +impl EmulatorHooks where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { - pub fn pre_syscalls(&mut self, hook: PreSyscallHook) -> Option { + pub fn pre_syscalls(&mut self, hook: PreSyscallHook) -> Option { match hook { Hook::Function(f) => Some(self.pre_syscalls_function(f)), Hook::Closure(c) => Some(self.pre_syscalls_closure(c)), @@ -819,16 +824,19 @@ where } } - pub fn pre_syscalls_function(&mut self, hook: PreSyscallHookFn) -> PreSyscallHookId { + pub fn pre_syscalls_function(&mut self, hook: PreSyscallHookFn) -> PreSyscallHookId { // # Safety // Will dereference the hook as [`FatPtr`]. unsafe { self.qemu_hooks - .add_pre_syscall_hook(transmute(hook), func_pre_syscall_hook_wrapper::) + .add_pre_syscall_hook(transmute(hook), func_pre_syscall_hook_wrapper::) } } - pub fn pre_syscalls_closure(&mut self, hook: PreSyscallHookClosure) -> PreSyscallHookId { + pub fn pre_syscalls_closure( + &mut self, + hook: PreSyscallHookClosure, + ) -> PreSyscallHookId { // # Safety // Will dereference the hook as [`FatPtr`]. unsafe { @@ -847,9 +855,10 @@ where .get_unchecked_mut() .1; - let id = self - .qemu_hooks - .add_pre_syscall_hook(&mut *hook_state, closure_pre_syscall_hook_wrapper::); + let id = self.qemu_hooks.add_pre_syscall_hook( + &mut *hook_state, + closure_pre_syscall_hook_wrapper::, + ); self.hook_collection .pre_syscall_hooks @@ -862,7 +871,7 @@ where } } - pub fn post_syscalls(&mut self, hook: PostSyscallHook) -> Option { + pub fn post_syscalls(&mut self, hook: PostSyscallHook) -> Option { match hook { Hook::Function(f) => Some(self.post_syscalls_function(f)), Hook::Closure(c) => Some(self.post_syscalls_closure(c)), @@ -874,18 +883,21 @@ where } } - pub fn post_syscalls_function(&mut self, hook: PostSyscallHookFn) -> PostSyscallHookId { + pub fn post_syscalls_function( + &mut self, + hook: PostSyscallHookFn, + ) -> PostSyscallHookId { // # Safety // Will dereference the hook as [`FatPtr`]. This should be ok. unsafe { self.qemu_hooks - .add_post_syscall_hook(transmute(hook), func_post_syscall_hook_wrapper::) + .add_post_syscall_hook(transmute(hook), func_post_syscall_hook_wrapper::) } } pub fn post_syscalls_closure( &mut self, - hook: PostSyscallHookClosure, + hook: PostSyscallHookClosure, ) -> PostSyscallHookId { unsafe { let fat: FatPtr = transmute(hook); @@ -904,7 +916,7 @@ where let id = self.qemu_hooks.add_post_syscall_hook( &mut *hooks_state, - closure_post_syscall_hook_wrapper::, + closure_post_syscall_hook_wrapper::, ); self.hook_collection .post_syscall_hooks @@ -917,20 +929,22 @@ where } } - pub fn crash_function(&mut self, hook: CrashHookFn) { + pub fn crash_function(&mut self, hook: CrashHookFn) { // # Safety // Will cast the valid hook to a ptr. - self.qemu_hooks.set_crash_hook(crash_hook_wrapper::); + self.qemu_hooks + .set_crash_hook(crash_hook_wrapper::); self.hook_collection .crash_hooks .push(HookRepr::Function(hook as *const libc::c_void)); } - pub fn crash_closure(&mut self, hook: CrashHookClosure) { + pub fn crash_closure(&mut self, hook: CrashHookClosure) { // # Safety // Will cast the hook to a [`FatPtr`]. unsafe { - self.qemu_hooks.set_crash_hook(crash_hook_wrapper::); + self.qemu_hooks + .set_crash_hook(crash_hook_wrapper::); self.hook_collection .crash_hooks .push(HookRepr::Closure(transmute(hook))); @@ -938,10 +952,7 @@ where } } -impl EmulatorModules -where - S: UsesInput, -{ +impl EmulatorModules { /// Get a mutable reference to `EmulatorModules` (supposedly initialized beforehand). /// /// # Safety @@ -951,17 +962,17 @@ where /// The user should also be consistent with the generic use (it will suppose they are the same /// as the ones used at initialization time). #[must_use] - pub unsafe fn emulator_modules_mut_unchecked<'a>() -> &'a mut EmulatorModules { + pub unsafe fn emulator_modules_mut_unchecked<'a>() -> &'a mut EmulatorModules { #[cfg(debug_assertions)] { - (EMULATOR_MODULES as *mut EmulatorModules) + (EMULATOR_MODULES as *mut EmulatorModules) .as_mut() .unwrap() } #[cfg(not(debug_assertions))] { - &mut *(EMULATOR_MODULES as *mut EmulatorModules) + &mut *(EMULATOR_MODULES as *mut EmulatorModules) } } @@ -974,15 +985,16 @@ where /// This version still presents some unsafeness: The user should be consistent with the /// generic use (it will suppose they are the same as the ones used at initialization time). #[must_use] - pub unsafe fn emulator_modules_mut<'a>() -> Option<&'a mut EmulatorModules> { - unsafe { (EMULATOR_MODULES as *mut EmulatorModules).as_mut() } + pub unsafe fn emulator_modules_mut<'a>() -> Option<&'a mut EmulatorModules> { + unsafe { (EMULATOR_MODULES as *mut EmulatorModules).as_mut() } } } -impl EmulatorModules +impl EmulatorModules where ET: Unpin, - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { pub fn modules_mut(&mut self) -> &mut ET { self.modules.as_mut().get_mut() @@ -991,7 +1003,7 @@ where pub fn instructions( &mut self, addr: GuestAddr, - hook: InstructionHook, + hook: InstructionHook, invalidate_block: bool, ) -> Option { self.hooks.instructions(addr, hook, invalidate_block) @@ -1000,7 +1012,7 @@ where pub fn instruction_function( &mut self, addr: GuestAddr, - hook: InstructionHookFn, + hook: InstructionHookFn, invalidate_block: bool, ) -> InstructionHookId { self.hooks @@ -1010,7 +1022,7 @@ where pub fn instruction_closure( &mut self, addr: GuestAddr, - hook: InstructionHookClosure, + hook: InstructionHookClosure, invalidate_block: bool, ) -> InstructionHookId { self.hooks.instruction_closure(addr, hook, invalidate_block) @@ -1018,17 +1030,17 @@ where pub fn edges( &mut self, - generation_hook: EdgeGenHook, - execution_hook: EdgeExecHook, + generation_hook: EdgeGenHook, + execution_hook: EdgeExecHook, ) -> EdgeHookId { self.hooks.edges(generation_hook, execution_hook) } pub fn blocks( &mut self, - generation_hook: BlockGenHook, - post_generation_hook: BlockPostGenHook, - execution_hook: BlockExecHook, + generation_hook: BlockGenHook, + post_generation_hook: BlockPostGenHook, + execution_hook: BlockExecHook, ) -> BlockHookId { self.hooks .blocks(generation_hook, post_generation_hook, execution_hook) @@ -1036,12 +1048,12 @@ where pub fn reads( &mut self, - generation_hook: ReadGenHook, - execution_hook_1: ReadExecHook, - execution_hook_2: ReadExecHook, - execution_hook_4: ReadExecHook, - execution_hook_8: ReadExecHook, - execution_hook_n: ReadExecNHook, + generation_hook: ReadGenHook, + execution_hook_1: ReadExecHook, + execution_hook_2: ReadExecHook, + execution_hook_4: ReadExecHook, + execution_hook_8: ReadExecHook, + execution_hook_n: ReadExecNHook, ) -> ReadHookId { self.hooks.reads( generation_hook, @@ -1055,12 +1067,12 @@ where pub fn writes( &mut self, - generation_hook: WriteGenHook, - execution_hook_1: WriteExecHook, - execution_hook_2: WriteExecHook, - execution_hook_4: WriteExecHook, - execution_hook_8: WriteExecHook, - execution_hook_n: WriteExecNHook, + generation_hook: WriteGenHook, + execution_hook_1: WriteExecHook, + execution_hook_2: WriteExecHook, + execution_hook_4: WriteExecHook, + execution_hook_8: WriteExecHook, + execution_hook_n: WriteExecNHook, ) -> WriteHookId { self.hooks.writes( generation_hook, @@ -1074,11 +1086,11 @@ where pub fn cmps( &mut self, - generation_hook: CmpGenHook, - execution_hook_1: CmpExecHook, - execution_hook_2: CmpExecHook, - execution_hook_4: CmpExecHook, - execution_hook_8: CmpExecHook, + generation_hook: CmpGenHook, + execution_hook_1: CmpExecHook, + execution_hook_2: CmpExecHook, + execution_hook_4: CmpExecHook, + execution_hook_8: CmpExecHook, ) -> CmpHookId { self.hooks.cmps( generation_hook, @@ -1091,51 +1103,57 @@ where /// # Safety /// This will potentially call an unsafe backdoor hook - pub unsafe fn backdoor(&mut self, hook: BackdoorHook) -> Option { + pub unsafe fn backdoor(&mut self, hook: BackdoorHook) -> Option { self.hooks.backdoor(hook) } - pub fn backdoor_function(&mut self, hook: BackdoorHookFn) -> BackdoorHookId { + pub fn backdoor_function(&mut self, hook: BackdoorHookFn) -> BackdoorHookId { self.hooks.backdoor_function(hook) } /// # Safety /// Calls through to the potentially unsafe `backdoor_closure` - pub unsafe fn backdoor_closure(&mut self, hook: BackdoorHookClosure) -> BackdoorHookId { + pub unsafe fn backdoor_closure( + &mut self, + hook: BackdoorHookClosure, + ) -> BackdoorHookId { self.hooks.backdoor_closure(hook) } - pub fn thread_creation(&mut self, hook: NewThreadHook) -> Option { + pub fn thread_creation(&mut self, hook: NewThreadHook) -> Option { self.hooks.thread_creation(hook) } - pub fn thread_creation_function(&mut self, hook: NewThreadHookFn) -> NewThreadHookId { + pub fn thread_creation_function(&mut self, hook: NewThreadHookFn) -> NewThreadHookId { self.hooks.thread_creation_function(hook) } pub fn thread_creation_closure( &mut self, - hook: NewThreadHookClosure, + hook: NewThreadHookClosure, ) -> NewThreadHookId { self.hooks.thread_creation_closure(hook) } } -impl EmulatorModules +impl EmulatorModules where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { /// Create a new [`EmulatorModules`] /// /// # Safety /// /// Only one such struct should be ever created. - pub(super) unsafe fn new(emulator_hooks: EmulatorHooks, modules: ET) -> Pin> { + pub(super) unsafe fn new( + emulator_hooks: EmulatorHooks, + modules: ET, + ) -> Pin> { let mut modules = Box::pin(Self { modules: Box::pin(modules), hooks: emulator_hooks, - phantom: PhantomData, }); // re-translate blocks with hooks @@ -1173,7 +1191,7 @@ where } } - pub fn pre_exec_all(&mut self, qemu: Qemu, state: &mut S, input: &S::Input) { + pub fn pre_exec_all(&mut self, qemu: Qemu, state: &mut S, input: &I) { // # Safety // We assume that the emulator was initialized correctly unsafe { @@ -1190,11 +1208,11 @@ where &mut self, qemu: Qemu, state: &mut S, - input: &S::Input, + input: &I, observers: &mut OT, exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, + OT: ObserversTuple, { unsafe { self.modules_mut().post_exec_all( @@ -1212,7 +1230,7 @@ where #[must_use] pub fn get(&self) -> Option<&T> where - T: EmulatorModule, + T: EmulatorModule, { self.modules.match_first_type::() } @@ -1220,38 +1238,36 @@ where /// Get a mutable reference to the first (type) matching member of the tuple. pub fn get_mut(&mut self) -> Option<&mut T> where - T: EmulatorModule, + T: EmulatorModule, { self.modules.match_first_type_mut::() } } -impl EmulatorModules -where - S: UsesInput, -{ +impl EmulatorModules { #[must_use] pub fn modules(&self) -> &ET { self.modules.as_ref().get_ref() } - pub fn hooks(&mut self) -> &EmulatorHooks { + pub fn hooks(&mut self) -> &EmulatorHooks { &self.hooks } - pub fn hooks_mut(&mut self) -> &mut EmulatorHooks { + pub fn hooks_mut(&mut self) -> &mut EmulatorHooks { &mut self.hooks } } /// Usermode-only high-level functions #[cfg(feature = "usermode")] -impl EmulatorModules +impl EmulatorModules where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { - pub fn pre_syscalls(&mut self, hook: PreSyscallHook) -> Option { + pub fn pre_syscalls(&mut self, hook: PreSyscallHook) -> Option { self.hooks.pre_syscalls(hook) } @@ -1260,7 +1276,7 @@ where #[allow(clippy::type_complexity)] pub unsafe fn pre_syscalls_function( &mut self, - hook: PreSyscallHookFn, + hook: PreSyscallHookFn, ) -> PreSyscallHookId { self.hooks.pre_syscalls_function(hook) } @@ -1270,12 +1286,12 @@ where #[allow(clippy::type_complexity)] pub unsafe fn pre_syscalls_closure( &mut self, - hook: PreSyscallHookClosure, + hook: PreSyscallHookClosure, ) -> PreSyscallHookId { self.hooks.pre_syscalls_closure(hook) } - pub fn post_syscalls(&mut self, hook: PostSyscallHook) -> Option { + pub fn post_syscalls(&mut self, hook: PostSyscallHook) -> Option { self.hooks.post_syscalls(hook) } @@ -1284,7 +1300,7 @@ where #[allow(clippy::type_complexity)] pub unsafe fn post_syscalls_function( &mut self, - hook: PostSyscallHookFn, + hook: PostSyscallHookFn, ) -> PostSyscallHookId { self.hooks.post_syscalls_function(hook) } @@ -1292,23 +1308,23 @@ where #[allow(clippy::type_complexity)] pub fn post_syscalls_closure( &mut self, - hook: PostSyscallHookClosure, + hook: PostSyscallHookClosure, ) -> PostSyscallHookId { self.hooks.post_syscalls_closure(hook) } - pub fn crash_function(&mut self, hook: CrashHookFn) { + pub fn crash_function(&mut self, hook: CrashHookFn) { self.hooks.crash_function(hook); } /// # Safety /// Calls through to the, potentially unsafe, registered `crash_closure` - pub unsafe fn crash_closure(&mut self, hook: CrashHookClosure) { + pub unsafe fn crash_closure(&mut self, hook: CrashHookClosure) { self.hooks.crash_closure(hook); } } -impl Drop for EmulatorModules { +impl Drop for EmulatorModules { fn drop(&mut self) { // Make the global pointer null at drop time // # Safety diff --git a/libafl_qemu/src/emu/mod.rs b/libafl_qemu/src/emu/mod.rs index 73ad47a9bc..7ee0f0edae 100644 --- a/libafl_qemu/src/emu/mod.rs +++ b/libafl_qemu/src/emu/mod.rs @@ -8,7 +8,7 @@ use std::{cell::RefCell, ops::Add, pin::Pin}; use hashbrown::HashMap; use libafl::{ executors::ExitKind, - inputs::{HasTargetBytes, UsesInput}, + inputs::HasTargetBytes, observers::ObserversTuple, state::{HasExecutions, State}, }; @@ -55,40 +55,17 @@ pub enum GuestAddrKind { Virtual(GuestVirtAddr), } -pub enum EmulatorExitResult -where - CM: CommandManager, - S: UsesInput, -{ - QemuExit(QemuShutdownCause), // QEMU ended for some reason. - Breakpoint(Breakpoint), // Breakpoint triggered. Contains the address of the trigger. - CustomInsn(CustomInsn), // Synchronous backdoor: The guest triggered a backdoor and should return to LibAFL. - Timeout, // Timeout +#[derive(Clone)] +pub enum EmulatorExitResult { + QemuExit(QemuShutdownCause), // QEMU ended for some reason. + Breakpoint(Breakpoint), // Breakpoint triggered. Contains the address of the trigger. + CustomInsn(CustomInsn), // Synchronous backdoor: The guest triggered a backdoor and should return to LibAFL. + Timeout, // Timeout } -impl Clone for EmulatorExitResult +impl Debug for EmulatorExitResult where - CM: CommandManager, - S: UsesInput, -{ - fn clone(&self) -> Self { - match self { - EmulatorExitResult::QemuExit(qemu_exit) => { - EmulatorExitResult::QemuExit(qemu_exit.clone()) - } - EmulatorExitResult::Breakpoint(bp) => EmulatorExitResult::Breakpoint(bp.clone()), - EmulatorExitResult::CustomInsn(sync_exit) => { - EmulatorExitResult::CustomInsn(sync_exit.clone()) - } - EmulatorExitResult::Timeout => EmulatorExitResult::Timeout, - } - } -} - -impl Debug for EmulatorExitResult -where - CM: CommandManager, - S: UsesInput, + C: Debug, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { @@ -140,26 +117,17 @@ pub struct InputLocation { /// /// Please check the documentation of [`EmulatorBuilder`] for more details. #[derive(Debug)] -#[expect(clippy::type_complexity)] -pub struct Emulator -where - CM: CommandManager, - S: UsesInput, -{ +pub struct Emulator { snapshot_manager: SM, - modules: Pin>>, + modules: Pin>>, command_manager: CM, driver: ED, - breakpoints_by_addr: RefCell>>, // TODO: change to RC here - breakpoints_by_id: RefCell>>, + breakpoints_by_addr: RefCell>>, // TODO: change to RC here + breakpoints_by_id: RefCell>>, qemu: Qemu, } -impl EmulatorDriverResult -where - CM: CommandManager, - S: UsesInput, -{ +impl EmulatorDriverResult { #[must_use] pub fn end_of_run(&self) -> Option { match self { @@ -243,10 +211,9 @@ impl From for EmulatorDriverError { } } -impl Display for EmulatorExitResult +impl Display for EmulatorExitResult where - CM: CommandManager, - S: UsesInput, + C: Debug, { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self { @@ -268,16 +235,15 @@ impl From for EmulatorExitError { } } -impl Emulator -where - S: UsesInput, -{ +impl Emulator { #[must_use] pub fn empty() -> EmulatorBuilder< + C, NopCommandManager, NopEmulatorDriver, (), QemuConfigBuilder, + I, S, NopSnapshotManager, > { @@ -285,17 +251,19 @@ where } } -impl Emulator, StdEmulatorDriver, (), S, StdSnapshotManager> +impl Emulator, StdEmulatorDriver, (), I, S, StdSnapshotManager> where S: State + HasExecutions + Unpin, - S::Input: HasTargetBytes, + I: HasTargetBytes, { #[must_use] pub fn builder() -> EmulatorBuilder< + C, StdCommandManager, StdEmulatorDriver, (), QemuConfigBuilder, + I, S, StdSnapshotManager, > { @@ -303,12 +271,8 @@ where } } -impl Emulator -where - CM: CommandManager, - S: UsesInput, -{ - pub fn modules(&self) -> &EmulatorModules { +impl Emulator { + pub fn modules(&self) -> &EmulatorModules { &self.modules } @@ -346,22 +310,22 @@ where } } -impl Emulator +impl Emulator where - CM: CommandManager, ET: Unpin, - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { - pub fn modules_mut(&mut self) -> &mut EmulatorModules { + pub fn modules_mut(&mut self) -> &mut EmulatorModules { self.modules.as_mut().get_mut() } } -impl Emulator +impl Emulator where - CM: CommandManager, - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { #[allow(clippy::must_use_candidate, clippy::similar_names)] pub fn new( @@ -393,7 +357,7 @@ where // TODO: fix things there properly. The biggest issue being that it creates 2 mut ref to the module with the callback being called unsafe { emulator_modules.modules_mut().pre_qemu_init_all( - EmulatorModules::::emulator_modules_mut_unchecked(), + EmulatorModules::::emulator_modules_mut_unchecked(), &mut qemu_params, ); } @@ -421,7 +385,7 @@ where /// pre-init qemu hooks should be run before calling this. unsafe fn new_with_qemu( qemu: Qemu, - emulator_modules: Pin>>, + emulator_modules: Pin>>, driver: ED, snapshot_manager: SM, command_manager: CM, @@ -442,12 +406,14 @@ where } } -impl Emulator +impl Emulator where - CM: CommandManager, - ED: EmulatorDriver, - ET: EmulatorModuleTuple + Unpin, - S: UsesInput + Unpin, + C: Clone, + CM: CommandManager, + ED: EmulatorDriver, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { /// This function will run the emulator until the exit handler decides to stop the execution for /// whatever reason, depending on the choosen handler. @@ -460,8 +426,8 @@ where pub unsafe fn run( &mut self, state: &mut S, - input: &S::Input, - ) -> Result, EmulatorDriverError> { + input: &I, + ) -> Result, EmulatorDriverError> { loop { // Insert input if the location is already known ED::pre_qemu_exec(self, input); @@ -485,9 +451,7 @@ where /// /// Should, in general, be safe to call. /// Of course, the emulated target is not contained securely and can corrupt state or interact with the operating system. - pub unsafe fn run_qemu( - &self, - ) -> Result, EmulatorExitError> { + pub unsafe fn run_qemu(&self) -> Result, EmulatorExitError> { match self.qemu.run() { Ok(qemu_exit_reason) => Ok(match qemu_exit_reason { QemuExitReason::End(qemu_shutdown_cause) => { @@ -520,34 +484,29 @@ where } /// Pre exec of Emulator, called before calling to user harness - pub fn pre_exec(&mut self, state: &mut S, input: &S::Input) { + pub fn pre_exec(&mut self, state: &mut S, input: &I) { ED::pre_harness_exec(self, state, input); } /// Post exec of Emulator, called before calling to user harness pub fn post_exec( &mut self, - input: &S::Input, + input: &I, observers: &mut OT, state: &mut S, exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, + OT: ObserversTuple, { ED::post_harness_exec(self, input, observers, state, exit_kind); } } -impl Emulator -where - CM: CommandManager, - S: UsesInput, -{ - pub fn add_breakpoint( - &self, - mut bp: Breakpoint, - enable: bool, - ) -> BreakpointId { +impl Emulator { + pub fn add_breakpoint(&self, mut bp: Breakpoint, enable: bool) -> BreakpointId + where + C: Clone, + { if enable { bp.enable(self.qemu); } diff --git a/libafl_qemu/src/emu/systemmode.rs b/libafl_qemu/src/emu/systemmode.rs index 786a32cfe1..f282ef324d 100644 --- a/libafl_qemu/src/emu/systemmode.rs +++ b/libafl_qemu/src/emu/systemmode.rs @@ -1,11 +1,9 @@ use std::fmt::Debug; use hashbrown::HashMap; -use libafl::inputs::UsesInput; use libafl_qemu_sys::GuestPhysAddr; use crate::{ - command::CommandManager, emu::{IsSnapshotManager, QemuSnapshotCheckResult}, DeviceSnapshotFilter, Emulator, Qemu, SnapshotId, SnapshotManagerError, }; @@ -166,11 +164,7 @@ impl IsSnapshotManager for FastSnapshotManager { } } -impl Emulator -where - CM: CommandManager, - S: UsesInput, -{ +impl Emulator { /// Write a value to a phsical guest address, including ROM areas. #[allow(clippy::missing_safety_doc)] pub unsafe fn write_phys_mem(&self, paddr: GuestPhysAddr, buf: &[u8]) { diff --git a/libafl_qemu/src/emu/usermode.rs b/libafl_qemu/src/emu/usermode.rs index a7ceeffa52..dd4428a96a 100644 --- a/libafl_qemu/src/emu/usermode.rs +++ b/libafl_qemu/src/emu/usermode.rs @@ -1,15 +1,10 @@ -use libafl::inputs::UsesInput; use libafl_qemu_sys::{GuestAddr, MmapPerms, VerifyAccess}; -use crate::{command::CommandManager, Emulator, GuestMaps, NopSnapshotManager}; +use crate::{Emulator, GuestMaps, NopSnapshotManager}; pub type StdSnapshotManager = NopSnapshotManager; -impl Emulator -where - CM: CommandManager, - S: UsesInput, -{ +impl Emulator { /// This function gets the memory mappings from the emulator. #[must_use] pub fn mappings(&self) -> GuestMaps { diff --git a/libafl_qemu/src/executor.rs b/libafl_qemu/src/executor.rs index fcbb0e1e0a..170d1a5559 100644 --- a/libafl_qemu/src/executor.rs +++ b/libafl_qemu/src/executor.rs @@ -43,15 +43,11 @@ use crate::EmulatorModules; use crate::Qemu; use crate::{command::CommandManager, modules::EmulatorModuleTuple, Emulator, EmulatorDriver}; -pub struct QemuExecutor<'a, CM, ED, ET, H, OT, S, SM> -where - CM: CommandManager, - ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &mut S, &S::Input) -> ExitKind, - OT: ObserversTuple, - S: State, -{ - inner: StatefulInProcessExecutor<'a, H, OT, S, Emulator>, +type EmulatorInProcessExecutor<'a, C, CM, ED, ET, H, I, OT, S, SM> = + StatefulInProcessExecutor<'a, H, I, OT, S, Emulator>; + +pub struct QemuExecutor<'a, C, CM, ED, ET, H, I, OT, S, SM> { + inner: EmulatorInProcessExecutor<'a, C, CM, ED, ET, H, I, OT, S, SM>, first_exec: bool, } @@ -59,14 +55,15 @@ where /// /// This should be used as a crash handler, and nothing else. #[cfg(feature = "usermode")] -unsafe fn inproc_qemu_crash_handler( +unsafe fn inproc_qemu_crash_handler( signal: Signal, info: &mut siginfo_t, mut context: Option<&mut ucontext_t>, _data: &mut InProcessExecutorHandlerData, ) where - ET: EmulatorModuleTuple, - S: UsesInput + Unpin, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let puc = match &mut context { Some(v) => ptr::from_mut::(*v) as *mut c_void, @@ -74,7 +71,7 @@ unsafe fn inproc_qemu_crash_handler( }; // run modules' crash callback - if let Some(emulator_modules) = EmulatorModules::::emulator_modules_mut() { + if let Some(emulator_modules) = EmulatorModules::::emulator_modules_mut() { emulator_modules.modules_mut().on_crash_all(); } @@ -87,25 +84,21 @@ pub(crate) static BREAK_ON_TMOUT: AtomicBool = AtomicBool::new(false); /// # Safety /// Can call through the `unix_signal_handler::inproc_timeout_handler`. /// Calling this method multiple times concurrently can lead to race conditions. -pub unsafe fn inproc_qemu_timeout_handler( +pub unsafe fn inproc_qemu_timeout_handler( signal: Signal, info: &mut siginfo_t, context: Option<&mut ucontext_t>, data: &mut InProcessExecutorHandlerData, ) where - E: HasObservers + HasInProcessHooks + Executor::Input, S, Z>, - E::Observers: ObserversTuple<::Input, S>, - S: HasExecutions - + HasSolutions - + HasCorpus - + Unpin - + HasCurrentTestcase - + UsesInput::Input>, - ::Input: Input, - S::Solutions: Corpus::Input>, + E: HasObservers + HasInProcessHooks + Executor, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - ET: EmulatorModuleTuple, - OF: Feedback::Input, E::Observers, S>, + ET: EmulatorModuleTuple, + I: Unpin, + OF: Feedback, + S: HasExecutions + HasSolutions + HasCorpus + Unpin + HasCurrentTestcase + UsesInput, + I: Input, + S::Solutions: Corpus, Z: HasObjective, { #[cfg(feature = "systemmode")] @@ -116,6 +109,7 @@ pub unsafe fn inproc_qemu_timeout_handler( libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::< E, EM, + I, OF, S, Z, @@ -126,13 +120,14 @@ pub unsafe fn inproc_qemu_timeout_handler( #[cfg(feature = "usermode")] { // run modules' crash callback - if let Some(emulator_modules) = EmulatorModules::::emulator_modules_mut() { + if let Some(emulator_modules) = EmulatorModules::::emulator_modules_mut() { emulator_modules.modules_mut().on_timeout_all(); } libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::< E, EM, + I, OF, S, Z, @@ -140,13 +135,9 @@ pub unsafe fn inproc_qemu_timeout_handler( } } -impl Debug for QemuExecutor<'_, CM, ED, ET, H, OT, S, SM> +impl Debug for QemuExecutor<'_, C, CM, ED, ET, H, I, OT, S, SM> where - CM: CommandManager, - ET: EmulatorModuleTuple + Debug, - H: FnMut(&mut Emulator, &mut S, &S::Input) -> ExitKind, - OT: ObserversTuple + Debug, - S: State, + OT: Debug, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QemuExecutor") @@ -155,23 +146,17 @@ where } } -impl<'a, CM, ED, ET, H, OT, S, SM> QemuExecutor<'a, CM, ED, ET, H, OT, S, SM> +impl<'a, C, CM, ED, ET, H, I, OT, S, SM> QemuExecutor<'a, C, CM, ED, ET, H, I, OT, S, SM> where - CM: CommandManager, - ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &mut S, &::Input) -> ExitKind, - OT: ObserversTuple<::Input, S>, - S: HasCorpus - + Unpin - + HasExecutions - + HasSolutions - + UsesInput::Input> - + State, - S::Solutions: Corpus::Input>, - ::Input: Input, + ET: EmulatorModuleTuple, + H: FnMut(&mut Emulator, &mut S, &I) -> ExitKind, + I: Input + Unpin, + OT: ObserversTuple, + S: HasCorpus + Unpin + HasExecutions + HasSolutions + State, + S::Solutions: Corpus, { pub fn new( - emulator: Emulator, + emulator: Emulator, harness_fn: &'a mut H, observers: OT, fuzzer: &mut Z, @@ -180,12 +165,13 @@ where timeout: Duration, ) -> Result where - ED: EmulatorDriver, + C: Clone, + CM: CommandManager, + ED: EmulatorDriver, EM: EventFirer + EventRestarter, - OF: Feedback, - Z: HasObjective - + HasScheduler<::Input, S> - + ExecutionProcessor::Input, OT, S>, + OF: Feedback, + Z: HasObjective + HasScheduler + ExecutionProcessor, + ::Corpus: Corpus, { let mut inner = StatefulInProcessExecutor::with_timeout( harness_fn, emulator, observers, fuzzer, state, event_mgr, timeout, @@ -194,18 +180,25 @@ where #[cfg(feature = "usermode")] { inner.inprocess_hooks_mut().crash_handler = - inproc_qemu_crash_handler:: as *const c_void; + inproc_qemu_crash_handler:: as *const c_void; - let handler = |qemu: Qemu, _emulator_modules: &mut EmulatorModules, host_sig| { - eprintln!("Crashed with signal {host_sig}"); - unsafe { - libafl::executors::inprocess::generic_inproc_crash_handler::( - ); - } - if let Some(cpu) = qemu.current_cpu() { - eprint!("Context:\n{}", cpu.display_context()); - } - }; + let handler = + |qemu: Qemu, _emulator_modules: &mut EmulatorModules, host_sig| { + eprintln!("Crashed with signal {host_sig}"); + unsafe { + libafl::executors::inprocess::generic_inproc_crash_handler::< + Self, + EM, + I, + OF, + S, + Z, + >(); + } + if let Some(cpu) = qemu.current_cpu() { + eprint!("Context:\n{}", cpu.display_context()); + } + }; // # Safety // We assume our crash handlers to be safe/quit after execution. @@ -218,9 +211,10 @@ where } inner.inprocess_hooks_mut().timeout_handler = inproc_qemu_timeout_handler::< - StatefulInProcessExecutor<'a, H, OT, S, Emulator>, + StatefulInProcessExecutor<'a, H, I, OT, S, Emulator>, EM, ET, + I, OF, S, Z, @@ -232,7 +226,7 @@ where }) } - pub fn inner(&self) -> &StatefulInProcessExecutor<'a, H, OT, S, Emulator> { + pub fn inner(&self) -> &EmulatorInProcessExecutor<'a, C, CM, ED, ET, H, I, OT, S, SM> { &self.inner } @@ -243,28 +237,30 @@ where pub fn inner_mut( &mut self, - ) -> &mut StatefulInProcessExecutor<'a, H, OT, S, Emulator> { + ) -> &mut EmulatorInProcessExecutor<'a, C, CM, ED, ET, H, I, OT, S, SM> { &mut self.inner } } -impl Executor::Input, S, Z> - for QemuExecutor<'_, CM, ED, ET, H, OT, S, SM> +impl Executor + for QemuExecutor<'_, C, CM, ED, ET, H, I, OT, S, SM> where - CM: CommandManager, - ED: EmulatorDriver, + C: Clone, + CM: CommandManager, + ED: EmulatorDriver, EM: UsesState, - ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &mut S, &::Input) -> ExitKind, - OT: ObserversTuple<::Input, S>, - S: State + HasExecutions + Unpin + HasCorpus + UsesInput::Input>, + ET: EmulatorModuleTuple, + H: FnMut(&mut Emulator, &mut S, &I) -> ExitKind, + I: Unpin, + OT: ObserversTuple, + S: State + HasExecutions + Unpin + HasCorpus, { fn run_target( &mut self, fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { if self.first_exec { self.inner.exposed_executor_state_mut().first_exec(state); @@ -288,13 +284,13 @@ where } } -impl HasObservers for QemuExecutor<'_, CM, ED, ET, H, OT, S, SM> +impl HasObservers + for QemuExecutor<'_, C, CM, ED, ET, H, I, OT, S, SM> where - CM: CommandManager, - ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &mut S, &::Input) -> ExitKind, - OT: ObserversTuple<::Input, S>, - S: State + HasCorpus + UsesInput::Input>, + ET: EmulatorModuleTuple, + H: FnMut(&mut Emulator, &mut S, &I) -> ExitKind, + OT: ObserversTuple, + S: State + HasCorpus, { type Observers = OT; #[inline] @@ -308,33 +304,26 @@ where } } -pub type QemuInProcessForkExecutor<'a, CM, ED, EM, ET, H, OT, S, SM, SP, Z> = - StatefulInProcessForkExecutor<'a, H, OT, S, SP, Emulator, EM, Z>; +pub type QemuInProcessForkExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> = + StatefulInProcessForkExecutor<'a, H, I, OT, S, SP, Emulator, EM, Z>; #[cfg(feature = "fork")] -pub struct QemuForkExecutor<'a, CM, ED, EM, ET, H, OT, S, SM, SP, Z> -where - CM: CommandManager, - ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &S::Input) -> ExitKind + Sized, - OT: ObserversTuple, - S: UsesInput, - SP: ShMemProvider, -{ - inner: QemuInProcessForkExecutor<'a, CM, ED, EM, ET, H, OT, S, SM, SP, Z>, +pub struct QemuForkExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> { + inner: QemuInProcessForkExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z>, } #[cfg(feature = "fork")] -impl Debug - for QemuForkExecutor<'_, CM, ED, EM, ET, H, OT, S, SM, SP, Z> +impl Debug + for QemuForkExecutor<'_, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> where - CM: CommandManager + Debug, + C: Debug, + CM: Debug, EM: UsesState, ED: Debug, - ET: EmulatorModuleTuple + Debug, - H: FnMut(&mut Emulator, &S::Input) -> ExitKind + Sized, - OT: ObserversTuple + Debug, - S: UsesInput + Debug, + ET: EmulatorModuleTuple + Debug, + OT: ObserversTuple + Debug, + I: Debug, + S: UsesInput + Debug, SM: Debug, SP: ShMemProvider, { @@ -347,22 +336,20 @@ where } #[cfg(feature = "fork")] -impl<'a, CM, ED, EM, ET, H, OT, S, SM, SP, Z> - QemuForkExecutor<'a, CM, ED, EM, ET, H, OT, S, SM, SP, Z> +impl<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> + QemuForkExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> where - CM: CommandManager, EM: EventFirer + EventRestarter, - ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &::Input) -> ExitKind + Sized, - OT: ObserversTuple<::Input, S>, - S: State + HasSolutions + HasCorpus + UsesInput::Input>, + ET: EmulatorModuleTuple, + OT: ObserversTuple, + S: State + HasSolutions + HasCorpus, SP: ShMemProvider, Z: HasObjective, - Z::Objective: Feedback::Input, OT, S>, + Z::Objective: Feedback, { #[expect(clippy::too_many_arguments)] pub fn new( - emulator: Emulator, + emulator: Emulator, harness_fn: &'a mut H, observers: OT, fuzzer: &mut Z, @@ -387,37 +374,43 @@ where }) } - pub fn inner(&self) -> &QemuInProcessForkExecutor<'a, CM, ED, EM, ET, H, OT, S, SM, SP, Z> { + #[allow(clippy::type_complexity)] + pub fn inner( + &self, + ) -> &QemuInProcessForkExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> { &self.inner } + #[allow(clippy::type_complexity)] pub fn inner_mut( &mut self, - ) -> &mut QemuInProcessForkExecutor<'a, CM, ED, EM, ET, H, OT, S, SM, SP, Z> { + ) -> &mut QemuInProcessForkExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> { &mut self.inner } - pub fn emulator(&self) -> &Emulator { + pub fn emulator(&self) -> &Emulator { &self.inner.exposed_executor_state } - pub fn emulator_mut(&mut self) -> &Emulator { + pub fn emulator_mut(&mut self) -> &Emulator { &mut self.inner.exposed_executor_state } } #[cfg(feature = "fork")] -impl Executor::Input, S, Z> - for QemuForkExecutor<'_, CM, ED, EM, ET, H, OT, S, SM, SP, Z> +impl Executor + for QemuForkExecutor<'_, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> where - CM: CommandManager, - ED: EmulatorDriver, + C: Clone, + CM: CommandManager, + ED: EmulatorDriver, EM: EventFirer + EventRestarter, - ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &S::Input) -> ExitKind, - OF: Feedback, - OT: ObserversTuple + Debug, - S: State + HasExecutions + Unpin + HasCorpus + UsesInput::Input>, + ET: EmulatorModuleTuple, + H: FnMut(&mut Emulator, &I) -> ExitKind, + OF: Feedback, + OT: ObserversTuple + Debug, + I: Input + Unpin, + S: State + HasExecutions + Unpin + HasCorpus, SP: ShMemProvider, Z: HasObjective, { @@ -426,7 +419,7 @@ where fuzzer: &mut Z, state: &mut S, mgr: &mut EM, - input: &::Input, + input: &I, ) -> Result { self.inner.exposed_executor_state.first_exec(state); @@ -446,13 +439,11 @@ where } #[cfg(feature = "fork")] -impl UsesState - for QemuForkExecutor<'_, CM, ED, EM, ET, H, OT, S, SM, SP, Z> +impl UsesState + for QemuForkExecutor<'_, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> where - CM: CommandManager, - ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &S::Input) -> ExitKind + Sized, - OT: ObserversTuple, + ET: EmulatorModuleTuple, + OT: ObserversTuple, S: State, SP: ShMemProvider, { @@ -460,14 +451,12 @@ where } #[cfg(feature = "fork")] -impl HasObservers - for QemuForkExecutor<'_, CM, ED, EM, ET, H, OT, S, SM, SP, Z> +impl HasObservers + for QemuForkExecutor<'_, C, CM, ED, EM, ET, H, I, OT, S, SM, SP, Z> where - CM: CommandManager, EM: UsesState, - ET: EmulatorModuleTuple, - H: FnMut(&mut Emulator, &S::Input) -> ExitKind + Sized, - OT: ObserversTuple, + ET: EmulatorModuleTuple, + OT: ObserversTuple, S: State, SP: ShMemProvider, { diff --git a/libafl_qemu/src/modules/calls.rs b/libafl_qemu/src/modules/calls.rs index fe28cb556a..1e97da3509 100644 --- a/libafl_qemu/src/modules/calls.rs +++ b/libafl_qemu/src/modules/calls.rs @@ -3,7 +3,7 @@ use core::{cell::UnsafeCell, fmt::Debug}; use capstone::prelude::*; use libafl::{ executors::ExitKind, - inputs::{Input, UsesInput}, + inputs::Input, observers::{stacktrace::BacktraceObserver, ObserversTuple}, }; use libafl_bolts::tuples::{Handle, Handled, MatchFirstType, MatchNameRef}; @@ -23,25 +23,27 @@ use crate::{ }; pub trait CallTraceCollector: 'static { - fn on_call( + fn on_call( &mut self, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, state: Option<&mut S>, pc: GuestAddr, call_len: usize, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple; + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin; - fn on_ret( + fn on_ret( &mut self, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, state: Option<&mut S>, pc: GuestAddr, ret_addr: GuestAddr, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple; + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin; // Frowarded from the `CallTracerModule` fn pre_exec(&mut self, _qemu: Qemu, _input: &I) @@ -50,77 +52,83 @@ pub trait CallTraceCollector: 'static { { } - fn post_exec( + fn post_exec( &mut self, _qemu: Qemu, - _input: &S::Input, + _input: &I, _observers: &mut OT, _exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, - S: Unpin + UsesInput, + I: Unpin, + OT: ObserversTuple, + S: Unpin, { } } pub trait CallTraceCollectorTuple: 'static + MatchFirstType { - fn on_call_all( + fn on_call_all( &mut self, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, call_len: usize, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple; + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin; - fn on_ret_all( + fn on_ret_all( &mut self, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, _pc: GuestAddr, ret_addr: GuestAddr, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple; + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin; fn pre_exec_all(&mut self, _qemu: Qemu, input: &I) where I: Input; - fn post_exec_all( + fn post_exec_all( &mut self, _qemu: Qemu, - input: &S::Input, + input: &I, _observers: &mut OT, _exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, - S: Unpin + UsesInput; + I: Unpin, + OT: ObserversTuple, + S: Unpin; } impl CallTraceCollectorTuple for () { - fn on_call_all( + fn on_call_all( &mut self, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, _pc: GuestAddr, _call_len: usize, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { } - fn on_ret_all( + fn on_ret_all( &mut self, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, _pc: GuestAddr, _ret_addr: GuestAddr, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { } @@ -130,15 +138,16 @@ impl CallTraceCollectorTuple for () { { } - fn post_exec_all( + fn post_exec_all( &mut self, _emulator: Qemu, - _input: &S::Input, + _input: &I, _observers: &mut OT, _exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, - S: Unpin + UsesInput, + I: Unpin, + OT: ObserversTuple, + S: Unpin, { } } @@ -148,15 +157,16 @@ where Head: CallTraceCollector, Tail: CallTraceCollectorTuple, { - fn on_call_all( + fn on_call_all( &mut self, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, mut state: Option<&mut S>, pc: GuestAddr, call_len: usize, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { self.0.on_call( emulator_modules, @@ -170,15 +180,16 @@ where self.1.on_call_all(emulator_modules, state, pc, call_len); } - fn on_ret_all( + fn on_ret_all( &mut self, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, mut state: Option<&mut S>, pc: GuestAddr, ret_addr: GuestAddr, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { self.0.on_ret( emulator_modules, @@ -200,15 +211,16 @@ where self.1.pre_exec_all(qemu, input); } - fn post_exec_all( + fn post_exec_all( &mut self, qemu: Qemu, - input: &S::Input, + input: &I, observers: &mut OT, exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, - S: Unpin + UsesInput, + I: Unpin, + OT: ObserversTuple, + S: Unpin, { self.0.post_exec(qemu, input, observers, exit_kind); self.1.post_exec_all(qemu, input, observers, exit_kind); @@ -243,14 +255,15 @@ where self.filter.allowed(&addr) } - fn on_ret( + fn on_ret( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, state: Option<&mut S>, pc: GuestAddr, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Input + Unpin, + S: Unpin, { let ret_addr: GuestAddr = qemu.read_return_address().unwrap(); @@ -272,15 +285,16 @@ where } #[allow(clippy::needless_pass_by_value)] // no longer a problem in nightly - fn gen_blocks_calls( + fn gen_blocks_calls( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, ) -> Option where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Input + Unpin, + S: Unpin, { if let Some(h) = emulator_modules.get_mut::() { if !h.must_instrument(pc) { @@ -365,7 +379,7 @@ where // TODO do not use a closure, find a more efficient way to pass call_len let call_cb = Box::new( move |_qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, state: Option<&mut S>, pc| { // eprintln!("CALL @ 0x{:#x}", pc + call_len); @@ -395,21 +409,22 @@ where } } -impl EmulatorModule for CallTracerModule +impl EmulatorModule for CallTracerModule where - S: Unpin + UsesInput, + I: Input + Unpin, + S: Unpin, T: CallTraceCollectorTuple + Debug, { type ModuleAddressFilter = StdAddressFilter; #[cfg(feature = "systemmode")] type ModulePageFilter = NopPageFilter; - fn post_qemu_init(&mut self, _qemu: Qemu, emulator_modules: &mut EmulatorModules) + fn post_qemu_init(&mut self, _qemu: Qemu, emulator_modules: &mut EmulatorModules) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { emulator_modules.blocks( - Hook::Function(Self::gen_blocks_calls::), + Hook::Function(Self::gen_blocks_calls::), Hook::Empty, Hook::Empty, ); @@ -418,11 +433,11 @@ where fn pre_exec( &mut self, qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, - input: &S::Input, + input: &I, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { self.collectors.as_mut().unwrap().pre_exec_all(qemu, input); } @@ -430,14 +445,14 @@ where fn post_exec( &mut self, qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, - input: &S::Input, + input: &I, observers: &mut OT, exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, - ET: EmulatorModuleTuple, + OT: ObserversTuple, + ET: EmulatorModuleTuple, { self.collectors .as_mut() @@ -495,29 +510,31 @@ where 'a: 'static, { #[expect(clippy::unnecessary_cast)] - fn on_call( + fn on_call( &mut self, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, call_len: usize, ) where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { self.callstack_hash ^= pc as u64 + call_len as u64; } #[expect(clippy::unnecessary_cast)] - fn on_ret( + fn on_ret( &mut self, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, _pc: GuestAddr, ret_addr: GuestAddr, ) where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { self.callstack_hash ^= ret_addr as u64; } @@ -529,15 +546,16 @@ where self.reset(); } - fn post_exec( + fn post_exec( &mut self, _qemu: Qemu, - _input: &S::Input, + _input: &I, observers: &mut OT, exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, - S: Unpin + UsesInput, + I: Unpin, + OT: ObserversTuple, + S: Unpin, { let observer = observers .get_mut(&self.observer_handle) @@ -591,15 +609,16 @@ impl FullBacktraceCollector { impl CallTraceCollector for FullBacktraceCollector { #[allow(clippy::unnecessary_cast)] // dependent on the target instruction size - fn on_call( + fn on_call( &mut self, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, call_len: usize, ) where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let callstacks_ptr = &raw mut CALLSTACKS; // TODO handle Thumb @@ -610,15 +629,16 @@ impl CallTraceCollector for FullBacktraceCollector { } #[allow(clippy::unnecessary_cast)] // dependent on the target instruction size - fn on_ret( + fn on_ret( &mut self, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, _pc: GuestAddr, ret_addr: GuestAddr, ) where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let callstacks_ptr = &raw mut CALLSTACKS; unsafe { diff --git a/libafl_qemu/src/modules/cmplog.rs b/libafl_qemu/src/modules/cmplog.rs index 194942023e..510da15b00 100644 --- a/libafl_qemu/src/modules/cmplog.rs +++ b/libafl_qemu/src/modules/cmplog.rs @@ -1,7 +1,7 @@ #[cfg(feature = "usermode")] use capstone::{arch::BuildsCapstone, Capstone, InsnDetail}; use hashbrown::HashMap; -use libafl::{inputs::UsesInput, HasMetadata}; +use libafl::HasMetadata; use libafl_bolts::hash_64_fast; use libafl_qemu_sys::GuestAddr; pub use libafl_targets::{ @@ -70,9 +70,10 @@ impl Default for CmpLogModule { } } -impl EmulatorModule for CmpLogModule +impl EmulatorModule for CmpLogModule where - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: Unpin + HasMetadata, { type ModuleAddressFilter = StdAddressFilter; #[cfg(feature = "systemmode")] @@ -81,13 +82,13 @@ where fn first_exec( &mut self, _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: &mut S, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { emulator_modules.cmps( - Hook::Function(gen_unique_cmp_ids::), + Hook::Function(gen_unique_cmp_ids::), Hook::Raw(trace_cmp1_cmplog), Hook::Raw(trace_cmp2_cmplog), Hook::Raw(trace_cmp4_cmplog), @@ -137,9 +138,10 @@ impl Default for CmpLogChildModule { } } -impl EmulatorModule for CmpLogChildModule +impl EmulatorModule for CmpLogChildModule where - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: Unpin + HasMetadata, { type ModuleAddressFilter = StdAddressFilter; #[cfg(feature = "systemmode")] @@ -150,13 +152,13 @@ where fn first_exec( &mut self, _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: &mut S, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { emulator_modules.cmps( - Hook::Function(gen_hashed_cmp_ids::), + Hook::Function(gen_hashed_cmp_ids::), Hook::Raw(trace_cmp1_cmplog), Hook::Raw(trace_cmp2_cmplog), Hook::Raw(trace_cmp4_cmplog), @@ -183,16 +185,17 @@ where } } -pub fn gen_unique_cmp_ids( +pub fn gen_unique_cmp_ids( _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, state: Option<&mut S>, pc: GuestAddr, _size: usize, ) -> Option where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput + HasMetadata, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin + HasMetadata, { if let Some(h) = emulator_modules.get::() { if !h.must_instrument(pc) { @@ -216,16 +219,17 @@ where } #[allow(clippy::needless_pass_by_value)] // no longer a problem with nightly -pub fn gen_hashed_cmp_ids( +pub fn gen_hashed_cmp_ids( _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, _size: usize, ) -> Option where - S: HasMetadata + Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: HasMetadata + Unpin, { if let Some(h) = emulator_modules.get::() { if !h.must_instrument(pc) { @@ -311,15 +315,16 @@ impl CmpLogRoutinesModule { } #[allow(clippy::needless_pass_by_value)] // no longer a problem with nightly - fn gen_blocks_calls( + fn gen_blocks_calls( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, ) -> Option where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { if let Some(h) = emulator_modules.get_mut::() { if !h.must_instrument(pc) { @@ -398,9 +403,10 @@ impl CmpLogRoutinesModule { } #[cfg(feature = "usermode")] -impl EmulatorModule for CmpLogRoutinesModule +impl EmulatorModule for CmpLogRoutinesModule where - S: Unpin + UsesInput, + I: Unpin, + S: Unpin, { type ModuleAddressFilter = StdAddressFilter; #[cfg(feature = "systemmode")] @@ -409,13 +415,13 @@ where fn first_exec( &mut self, _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: &mut S, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { emulator_modules.blocks( - Hook::Function(Self::gen_blocks_calls::), + Hook::Function(Self::gen_blocks_calls::), Hook::Empty, Hook::Empty, ); diff --git a/libafl_qemu/src/modules/drcov.rs b/libafl_qemu/src/modules/drcov.rs index e6629ddbd3..a87f8bb0a6 100644 --- a/libafl_qemu/src/modules/drcov.rs +++ b/libafl_qemu/src/modules/drcov.rs @@ -1,7 +1,7 @@ use std::{path::PathBuf, sync::Mutex}; use hashbrown::{hash_map::Entry, HashMap}; -use libafl::{executors::ExitKind, inputs::UsesInput, observers::ObserversTuple, HasMetadata}; +use libafl::{executors::ExitKind, observers::ObserversTuple, HasMetadata}; use libafl_qemu_sys::{GuestAddr, GuestUsize}; use libafl_targets::drcov::{DrCovBasicBlock, DrCovWriter}; use rangemap::RangeMap; @@ -258,23 +258,24 @@ where } } -impl EmulatorModule for DrCovModule +impl EmulatorModule for DrCovModule where F: AddressFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: Unpin + HasMetadata, { type ModuleAddressFilter = F; #[cfg(feature = "systemmode")] type ModulePageFilter = NopPageFilter; - fn post_qemu_init(&mut self, _qemu: Qemu, emulator_modules: &mut EmulatorModules) + fn post_qemu_init(&mut self, _qemu: Qemu, emulator_modules: &mut EmulatorModules) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { emulator_modules.blocks( - Hook::Function(gen_unique_block_ids::), - Hook::Function(gen_block_lengths::), - Hook::Function(exec_trace_block::), + Hook::Function(gen_unique_block_ids::), + Hook::Function(gen_block_lengths::), + Hook::Function(exec_trace_block::), ); } @@ -282,10 +283,10 @@ where fn first_exec( &mut self, qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { if self.module_mapping.is_none() { log::info!("Auto-filling module mapping for DrCov module from QEMU mapping."); @@ -315,10 +316,10 @@ where fn first_exec( &mut self, _qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { assert!( self.module_mapping.is_some(), @@ -329,14 +330,14 @@ where fn post_exec( &mut self, _qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, - _input: &S::Input, + _input: &I, _observers: &mut OT, _exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, - ET: EmulatorModuleTuple, + OT: ObserversTuple, + ET: EmulatorModuleTuple, { self.write(); } @@ -368,16 +369,17 @@ where } } -pub fn gen_unique_block_ids( +pub fn gen_unique_block_ids( _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, state: Option<&mut S>, pc: GuestAddr, ) -> Option where + ET: EmulatorModuleTuple, F: AddressFilter, - S: Unpin + UsesInput + HasMetadata, - ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin + HasMetadata, { let drcov_module = emulator_modules.get::>().unwrap(); if !drcov_module.must_instrument(pc) { @@ -419,16 +421,17 @@ where } #[allow(clippy::needless_pass_by_value)] // no longer a problem with nightly -pub fn gen_block_lengths( +pub fn gen_block_lengths( _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, block_length: GuestUsize, ) where + ET: EmulatorModuleTuple, F: AddressFilter, - S: Unpin + UsesInput + HasMetadata, - ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin + HasMetadata, { let drcov_module = emulator_modules.get::>().unwrap(); if !drcov_module.must_instrument(pc) { @@ -443,15 +446,16 @@ pub fn gen_block_lengths( } #[allow(clippy::needless_pass_by_value)] // no longer a problem with nightly -pub fn exec_trace_block( +pub fn exec_trace_block( _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, id: u64, ) where + ET: EmulatorModuleTuple, F: AddressFilter, - ET: EmulatorModuleTuple, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: Unpin + HasMetadata, { if emulator_modules.get::>().unwrap().full_trace { DRCOV_IDS.lock().unwrap().as_mut().unwrap().push(id); diff --git a/libafl_qemu/src/modules/edges/child.rs b/libafl_qemu/src/modules/edges/child.rs index 6180d69d32..0f9bcbc5f4 100644 --- a/libafl_qemu/src/modules/edges/child.rs +++ b/libafl_qemu/src/modules/edges/child.rs @@ -1,4 +1,4 @@ -use libafl::{inputs::UsesInput, HasMetadata}; +use libafl::HasMetadata; use super::{ helpers::{gen_hashed_edge_ids, trace_edge_hitcount_ptr, trace_edge_single_ptr}, @@ -31,28 +31,30 @@ impl { const DO_SIDE_EFFECTS: bool = false; - fn fn_hitcount(&mut self, emulator_modules: &mut EmulatorModules) + fn fn_hitcount(&mut self, emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { emulator_modules.edges( - Hook::Function(gen_hashed_edge_ids::), + Hook::Function(gen_hashed_edge_ids::), Hook::Raw(trace_edge_hitcount_ptr), ); } - fn fn_no_hitcount(&mut self, emulator_modules: &mut EmulatorModules) + fn fn_no_hitcount(&mut self, emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { emulator_modules.edges( - Hook::Function(gen_hashed_edge_ids::), + Hook::Function(gen_hashed_edge_ids::), Hook::Raw(trace_edge_single_ptr), ); } diff --git a/libafl_qemu/src/modules/edges/classic.rs b/libafl_qemu/src/modules/edges/classic.rs index 51f9de4c6d..7a75c11eff 100644 --- a/libafl_qemu/src/modules/edges/classic.rs +++ b/libafl_qemu/src/modules/edges/classic.rs @@ -1,4 +1,4 @@ -use libafl::{inputs::UsesInput, HasMetadata}; +use libafl::HasMetadata; use super::{ helpers::{ @@ -34,15 +34,16 @@ impl { const DO_SIDE_EFFECTS: bool = false; - fn jit_hitcount(&mut self, emulator_modules: &mut EmulatorModules) + fn jit_hitcount(&mut self, emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { let hook_id = emulator_modules.blocks( - Hook::Function(gen_hashed_block_ids::), + Hook::Function(gen_hashed_block_ids::), Hook::Empty, Hook::Empty, ); @@ -55,15 +56,16 @@ impl } } - fn jit_no_hitcount(&mut self, emulator_modules: &mut EmulatorModules) + fn jit_no_hitcount(&mut self, emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { let hook_id = emulator_modules.blocks( - Hook::Function(gen_hashed_block_ids::), + Hook::Function(gen_hashed_block_ids::), Hook::Empty, Hook::Empty, ); @@ -76,29 +78,31 @@ impl } } - fn fn_hitcount(&mut self, emulator_modules: &mut EmulatorModules) + fn fn_hitcount(&mut self, emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { emulator_modules.blocks( - Hook::Function(gen_hashed_block_ids::), + Hook::Function(gen_hashed_block_ids::), Hook::Empty, Hook::Raw(trace_block_transition_hitcount), ); } - fn fn_no_hitcount(&mut self, emulator_modules: &mut EmulatorModules) + fn fn_no_hitcount(&mut self, emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { emulator_modules.blocks( - Hook::Function(gen_hashed_block_ids::), + Hook::Function(gen_hashed_block_ids::), Hook::Empty, Hook::Raw(trace_block_transition_single), ); diff --git a/libafl_qemu/src/modules/edges/full.rs b/libafl_qemu/src/modules/edges/full.rs index ccd6b061fc..9dcb368afc 100644 --- a/libafl_qemu/src/modules/edges/full.rs +++ b/libafl_qemu/src/modules/edges/full.rs @@ -1,4 +1,4 @@ -use libafl::{inputs::UsesInput, HasMetadata}; +use libafl::HasMetadata; use super::{ helpers::{gen_unique_edge_ids, trace_edge_hitcount, trace_edge_single}, @@ -30,15 +30,16 @@ pub type StdEdgeCoverageFullModuleBuilder = EdgeCoverageModuleBuilder< impl EdgeCoverageVariant for EdgeCoverageFullVariant { - fn jit_hitcount(&mut self, emulator_modules: &mut EmulatorModules) + fn jit_hitcount(&mut self, emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { let hook_id = emulator_modules.edges( - Hook::Function(gen_unique_edge_ids::), + Hook::Function(gen_unique_edge_ids::), Hook::Empty, ); unsafe { @@ -49,15 +50,16 @@ impl } } - fn jit_no_hitcount(&mut self, emulator_modules: &mut EmulatorModules) + fn jit_no_hitcount(&mut self, emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { let hook_id = emulator_modules.edges( - Hook::Function(gen_unique_edge_ids::), + Hook::Function(gen_unique_edge_ids::), Hook::Empty, ); unsafe { @@ -68,28 +70,30 @@ impl } } - fn fn_hitcount(&mut self, emulator_modules: &mut EmulatorModules) + fn fn_hitcount(&mut self, emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { emulator_modules.edges( - Hook::Function(gen_unique_edge_ids::), + Hook::Function(gen_unique_edge_ids::), Hook::Raw(trace_edge_hitcount), ); } - fn fn_no_hitcount(&mut self, emulator_modules: &mut EmulatorModules) + fn fn_no_hitcount(&mut self, emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { emulator_modules.edges( - Hook::Function(gen_unique_edge_ids::), + Hook::Function(gen_unique_edge_ids::), Hook::Raw(trace_edge_single), ); } diff --git a/libafl_qemu/src/modules/edges/helpers.rs b/libafl_qemu/src/modules/edges/helpers.rs index 82183ac0d4..5a8f58e306 100644 --- a/libafl_qemu/src/modules/edges/helpers.rs +++ b/libafl_qemu/src/modules/edges/helpers.rs @@ -51,7 +51,7 @@ mod generators { use std::{cmp::max, ptr}; use hashbrown::hash_map::Entry; - use libafl::{inputs::UsesInput, HasMetadata}; + use libafl::HasMetadata; use libafl_bolts::hash_64_fast; use libafl_qemu_sys::GuestAddr; @@ -79,18 +79,28 @@ mod generators { } #[allow(unused_variables)] - pub fn gen_unique_edge_ids( + pub fn gen_unique_edge_ids< + AF, + ET, + PF, + I, + S, + V, + const IS_CONST_MAP: bool, + const MAP_SIZE: usize, + >( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, state: Option<&mut S>, src: GuestAddr, dest: GuestAddr, ) -> Option where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, V: EdgeCoverageVariant, { if let Some(module) = @@ -157,18 +167,28 @@ mod generators { #[allow(unused_variables)] #[allow(clippy::needless_pass_by_value)] // no longer a problem with nightly - pub fn gen_hashed_edge_ids( + pub fn gen_hashed_edge_ids< + AF, + ET, + PF, + I, + S, + V, + const IS_CONST_MAP: bool, + const MAP_SIZE: usize, + >( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, src: GuestAddr, dest: GuestAddr, ) -> Option where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, V: EdgeCoverageVariant, { if let Some(module) = @@ -211,17 +231,27 @@ mod generators { #[expect(clippy::unnecessary_cast)] #[allow(unused_variables)] #[allow(clippy::needless_pass_by_value)] // no longer a problem with nightly - pub fn gen_hashed_block_ids( + pub fn gen_hashed_block_ids< + AF, + ET, + PF, + I, + S, + V, + const IS_CONST_MAP: bool, + const MAP_SIZE: usize, + >( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, ) -> Option where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, V: EdgeCoverageVariant, { // first check if we should filter diff --git a/libafl_qemu/src/modules/edges/mod.rs b/libafl_qemu/src/modules/edges/mod.rs index 7ccae4e5e8..650bd31192 100644 --- a/libafl_qemu/src/modules/edges/mod.rs +++ b/libafl_qemu/src/modules/edges/mod.rs @@ -1,6 +1,6 @@ use std::fmt::Debug; -use libafl::{inputs::UsesInput, observers::VarLenMapObserver, HasMetadata}; +use libafl::{observers::VarLenMapObserver, HasMetadata}; use libafl_bolts::Error; use libafl_qemu_sys::GuestAddr; #[cfg(feature = "systemmode")] @@ -49,42 +49,46 @@ trait EdgeCoverageVariant(&mut self, _emulator_modules: &mut EmulatorModules) + fn jit_hitcount(&mut self, _emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { panic!("JIT hitcount is not supported.") } - fn jit_no_hitcount(&mut self, _emulator_modules: &mut EmulatorModules) + fn jit_no_hitcount(&mut self, _emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { panic!("JIT no hitcount is not supported.") } - fn fn_hitcount(&mut self, _emulator_modules: &mut EmulatorModules) + fn fn_hitcount(&mut self, _emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { panic!("Func hitcount is not supported.") } - fn fn_no_hitcount(&mut self, _emulator_modules: &mut EmulatorModules) + fn fn_no_hitcount(&mut self, _emulator_modules: &mut EmulatorModules) where AF: AddressFilter, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, PF: PageFilter, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: HasMetadata + Unpin, { panic!("Func no hitcount is not supported.") } @@ -314,12 +318,13 @@ where } } -impl EmulatorModule +impl EmulatorModule for EdgeCoverageModule where AF: AddressFilter + 'static, PF: PageFilter + 'static, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: Unpin + HasMetadata, V: EdgeCoverageVariant + 'static, { type ModuleAddressFilter = AF; @@ -331,10 +336,10 @@ where fn first_exec( &mut self, _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: &mut S, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { if self.use_hitcounts { if self.use_jit { diff --git a/libafl_qemu/src/modules/mod.rs b/libafl_qemu/src/modules/mod.rs index a63f3276b4..504bc16865 100644 --- a/libafl_qemu/src/modules/mod.rs +++ b/libafl_qemu/src/modules/mod.rs @@ -1,6 +1,6 @@ use core::{fmt::Debug, ops::Range}; -use libafl::{executors::ExitKind, inputs::UsesInput, observers::ObserversTuple}; +use libafl::{executors::ExitKind, observers::ObserversTuple}; use libafl_bolts::tuples::{MatchFirstType, SplitBorrowExtractFirstType}; use libafl_qemu_sys::GuestAddr; #[cfg(feature = "systemmode")] @@ -50,10 +50,7 @@ pub mod utils; /// A module for `libafl_qemu`. // TODO remove 'static when specialization will be stable -pub trait EmulatorModule: 'static + Debug -where - S: UsesInput, -{ +pub trait EmulatorModule: 'static + Debug { type ModuleAddressFilter: AddressFilter; #[cfg(feature = "systemmode")] @@ -69,19 +66,19 @@ where /// Thus, the module can modify options for QEMU just before it gets initialized. fn pre_qemu_init( &mut self, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _qemu_params: &mut QemuParams, ) where - ET: EmulatorModuleTuple, + 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(&mut self, _qemu: Qemu, _emulator_modules: &mut EmulatorModules) + fn post_qemu_init(&mut self, _qemu: Qemu, _emulator_modules: &mut EmulatorModules) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { } @@ -92,10 +89,10 @@ where fn first_exec( &mut self, _qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { } @@ -104,11 +101,11 @@ where fn pre_exec( &mut self, _qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, - _input: &S::Input, + _input: &I, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { } @@ -116,14 +113,14 @@ where fn post_exec( &mut self, _qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, - _input: &S::Input, + _input: &I, _observers: &mut OT, _exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, - ET: EmulatorModuleTuple, + OT: ObserversTuple, + ET: EmulatorModuleTuple, { } @@ -157,52 +154,53 @@ where } } -pub trait EmulatorModuleTuple: +pub trait EmulatorModuleTuple: MatchFirstType + for<'a> SplitBorrowExtractFirstType<'a> + Unpin -where - S: UsesInput, { const HOOKS_DO_SIDE_EFFECTS: bool; fn pre_qemu_init_all( &mut self, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, qemu_params: &mut QemuParams, ) where - ET: EmulatorModuleTuple; + ET: EmulatorModuleTuple; - fn post_qemu_init_all(&mut self, qemu: Qemu, emulator_modules: &mut EmulatorModules) - where - ET: EmulatorModuleTuple; + fn post_qemu_init_all( + &mut self, + qemu: Qemu, + emulator_modules: &mut EmulatorModules, + ) where + ET: EmulatorModuleTuple; fn first_exec_all( &mut self, qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, state: &mut S, ) where - ET: EmulatorModuleTuple; + ET: EmulatorModuleTuple; fn pre_exec_all( &mut self, qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, state: &mut S, - input: &S::Input, + input: &I, ) where - ET: EmulatorModuleTuple; + ET: EmulatorModuleTuple; fn post_exec_all( &mut self, qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, state: &mut S, - input: &S::Input, + input: &I, observers: &mut OT, exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, - ET: EmulatorModuleTuple; + OT: ObserversTuple, + ET: EmulatorModuleTuple; /// # Safety /// @@ -220,62 +218,62 @@ where fn allow_page_id_all(&mut self, page_id: GuestPhysAddr); } -impl EmulatorModuleTuple for () +impl EmulatorModuleTuple for () where - S: UsesInput + Unpin, + S: Unpin, { const HOOKS_DO_SIDE_EFFECTS: bool = false; fn pre_qemu_init_all( &mut self, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _qemu_params: &mut QemuParams, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { } fn post_qemu_init_all( &mut self, _qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { } fn first_exec_all( &mut self, _qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { } fn pre_exec_all( &mut self, _qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, - _input: &S::Input, + _input: &I, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { } fn post_exec_all( &mut self, _qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, - _input: &S::Input, + _input: &I, _observers: &mut OT, _exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, - ET: EmulatorModuleTuple, + OT: ObserversTuple, + ET: EmulatorModuleTuple, { } @@ -289,28 +287,31 @@ where fn allow_page_id_all(&mut self, _page_id: GuestPhysAddr) {} } -impl EmulatorModuleTuple for (Head, Tail) +impl EmulatorModuleTuple for (Head, Tail) where - Head: EmulatorModule + Unpin, - Tail: EmulatorModuleTuple, - S: UsesInput + Unpin, + Head: EmulatorModule + Unpin, + Tail: EmulatorModuleTuple, + S: Unpin, { const HOOKS_DO_SIDE_EFFECTS: bool = Head::HOOKS_DO_SIDE_EFFECTS || Tail::HOOKS_DO_SIDE_EFFECTS; fn pre_qemu_init_all( &mut self, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, qemu_params: &mut QemuParams, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { self.0.pre_qemu_init(emulator_modules, qemu_params); self.1.pre_qemu_init_all(emulator_modules, qemu_params); } - fn post_qemu_init_all(&mut self, qemu: Qemu, emulator_modules: &mut EmulatorModules) - where - ET: EmulatorModuleTuple, + fn post_qemu_init_all( + &mut self, + qemu: Qemu, + emulator_modules: &mut EmulatorModules, + ) where + ET: EmulatorModuleTuple, { self.0.post_qemu_init(qemu, emulator_modules); self.1.post_qemu_init_all(qemu, emulator_modules); @@ -319,10 +320,10 @@ where fn first_exec_all( &mut self, qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, state: &mut S, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { self.0.first_exec(qemu, emulator_modules, state); self.1.first_exec_all(qemu, emulator_modules, state); @@ -331,11 +332,11 @@ where fn pre_exec_all( &mut self, qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, state: &mut S, - input: &S::Input, + input: &I, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { self.0.pre_exec(qemu, emulator_modules, state, input); self.1.pre_exec_all(qemu, emulator_modules, state, input); @@ -344,14 +345,14 @@ where fn post_exec_all( &mut self, qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, state: &mut S, - input: &S::Input, + input: &I, observers: &mut OT, exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, - ET: EmulatorModuleTuple, + OT: ObserversTuple, + ET: EmulatorModuleTuple, { self.0 .post_exec(qemu, emulator_modules, state, input, observers, exit_kind); diff --git a/libafl_qemu/src/modules/usermode/asan.rs b/libafl_qemu/src/modules/usermode/asan.rs index a03d8971ab..c5d8183f48 100644 --- a/libafl_qemu/src/modules/usermode/asan.rs +++ b/libafl_qemu/src/modules/usermode/asan.rs @@ -3,7 +3,7 @@ use std::{borrow::Cow, env, fs, path::PathBuf, sync::Mutex}; use hashbrown::{HashMap, HashSet}; -use libafl::{executors::ExitKind, inputs::UsesInput, observers::ObserversTuple}; +use libafl::{executors::ExitKind, observers::ObserversTuple}; use libc::{ c_void, MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_NORESERVE, MAP_PRIVATE, PROT_READ, PROT_WRITE, }; @@ -810,19 +810,20 @@ impl AsanModule { } } -impl EmulatorModule for AsanModule +impl EmulatorModule for AsanModule where - S: Unpin + UsesInput, + I: Unpin, + S: Unpin, { type ModuleAddressFilter = StdAddressFilter; const HOOKS_DO_SIDE_EFFECTS: bool = false; fn pre_qemu_init( &mut self, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, qemu_params: &mut QemuParams, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { let mut args: Vec = qemu_params.to_cli(); @@ -874,52 +875,52 @@ where *qemu_params = QemuParams::Cli(args); } - fn post_qemu_init(&mut self, _qemu: Qemu, emulator_modules: &mut EmulatorModules) + fn post_qemu_init(&mut self, _qemu: Qemu, emulator_modules: &mut EmulatorModules) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { - emulator_modules.pre_syscalls(Hook::Function(qasan_fake_syscall::)); + emulator_modules.pre_syscalls(Hook::Function(qasan_fake_syscall::)); if self.rt.error_callback.is_some() { - emulator_modules.crash_function(oncrash_asan::); + emulator_modules.crash_function(oncrash_asan::); } } fn first_exec( &mut self, _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: &mut S, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { emulator_modules.reads( - Hook::Function(gen_readwrite_asan::), - Hook::Function(trace_read_asan::), - Hook::Function(trace_read_asan::), - Hook::Function(trace_read_asan::), - Hook::Function(trace_read_asan::), - Hook::Function(trace_read_n_asan::), + Hook::Function(gen_readwrite_asan::), + Hook::Function(trace_read_asan::), + Hook::Function(trace_read_asan::), + Hook::Function(trace_read_asan::), + Hook::Function(trace_read_asan::), + Hook::Function(trace_read_n_asan::), ); if emulator_modules.get::().is_none() { emulator_modules.writes( - Hook::Function(gen_readwrite_asan::), - Hook::Function(trace_write_asan::), - Hook::Function(trace_write_asan::), - Hook::Function(trace_write_asan::), - Hook::Function(trace_write_asan::), - Hook::Function(trace_write_n_asan::), + Hook::Function(gen_readwrite_asan::), + Hook::Function(trace_write_asan::), + Hook::Function(trace_write_asan::), + Hook::Function(trace_write_asan::), + Hook::Function(trace_write_asan::), + Hook::Function(trace_write_n_asan::), ); } else { // track writes for both modules as opt emulator_modules.writes( - Hook::Function(gen_write_asan_snapshot::), - Hook::Function(trace_write_asan_snapshot::), - Hook::Function(trace_write_asan_snapshot::), - Hook::Function(trace_write_asan_snapshot::), - Hook::Function(trace_write_asan_snapshot::), - Hook::Function(trace_write_n_asan_snapshot::), + Hook::Function(gen_write_asan_snapshot::), + Hook::Function(trace_write_asan_snapshot::), + Hook::Function(trace_write_asan_snapshot::), + Hook::Function(trace_write_asan_snapshot::), + Hook::Function(trace_write_asan_snapshot::), + Hook::Function(trace_write_n_asan_snapshot::), ); } } @@ -927,11 +928,11 @@ where fn pre_exec( &mut self, qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, - _input: &S::Input, + _input: &I, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { if self.empty { self.rt.snapshot(qemu); @@ -942,14 +943,14 @@ where fn post_exec( &mut self, qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, - _input: &S::Input, + _input: &I, _observers: &mut OT, exit_kind: &mut ExitKind, ) where - OT: ObserversTuple, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + OT: ObserversTuple, { if self.reset(qemu) == AsanRollback::HasLeaks { *exit_kind = ExitKind::Crash; @@ -965,30 +966,32 @@ where } } -pub fn oncrash_asan( +pub fn oncrash_asan( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, target_sig: i32, ) where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let h = emulator_modules.get_mut::().unwrap(); let pc: GuestAddr = qemu.read_reg(Regs::Pc).unwrap(); h.rt.report(qemu, pc, AsanError::Signal(target_sig)); } -pub fn gen_readwrite_asan( +pub fn gen_readwrite_asan( _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, _addr: *mut TCGTemp, _info: MemAccessInfo, ) -> Option where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let h = emulator_modules.get_mut::().unwrap(); if h.must_instrument(pc) { @@ -998,75 +1001,80 @@ where } } -pub fn trace_read_asan( +pub fn trace_read_asan( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, id: u64, addr: GuestAddr, ) where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let h = emulator_modules.get_mut::().unwrap(); h.read::(qemu, id as GuestAddr, addr); } -pub fn trace_read_n_asan( +pub fn trace_read_n_asan( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, id: u64, addr: GuestAddr, size: usize, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let h = emulator_modules.get_mut::().unwrap(); h.read_n(qemu, id as GuestAddr, addr, size); } -pub fn trace_write_asan( +pub fn trace_write_asan( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, id: u64, addr: GuestAddr, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let h = emulator_modules.get_mut::().unwrap(); h.write::(qemu, id as GuestAddr, addr); } -pub fn trace_write_n_asan( +pub fn trace_write_n_asan( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, id: u64, addr: GuestAddr, size: usize, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let h = emulator_modules.get_mut::().unwrap(); h.read_n(qemu, id as GuestAddr, addr, size); } -pub fn gen_write_asan_snapshot( +pub fn gen_write_asan_snapshot( _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, _addr: *mut TCGTemp, _info: MemAccessInfo, ) -> Option where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let h = emulator_modules.get_mut::().unwrap(); if h.must_instrument(pc) { @@ -1076,15 +1084,16 @@ where } } -pub fn trace_write_asan_snapshot( +pub fn trace_write_asan_snapshot( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, id: u64, addr: GuestAddr, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { if id != 0 { let h = emulator_modules.get_mut::().unwrap(); @@ -1094,16 +1103,17 @@ pub fn trace_write_asan_snapshot( h.access(addr, N); } -pub fn trace_write_n_asan_snapshot( +pub fn trace_write_n_asan_snapshot( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, id: u64, addr: GuestAddr, size: usize, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { if id != 0 { let h = emulator_modules.get_mut::().unwrap(); @@ -1114,9 +1124,9 @@ pub fn trace_write_n_asan_snapshot( } #[expect(clippy::too_many_arguments)] -pub fn qasan_fake_syscall( +pub fn qasan_fake_syscall( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, sys_num: i32, a0: GuestAddr, @@ -1129,8 +1139,9 @@ pub fn qasan_fake_syscall( _a7: GuestAddr, ) -> SyscallHookResult where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { if sys_num == QASAN_FAKESYS_NR { let h = emulator_modules.get_mut::().unwrap(); diff --git a/libafl_qemu/src/modules/usermode/asan_guest.rs b/libafl_qemu/src/modules/usermode/asan_guest.rs index 9964aa75a0..c94bb8bb20 100644 --- a/libafl_qemu/src/modules/usermode/asan_guest.rs +++ b/libafl_qemu/src/modules/usermode/asan_guest.rs @@ -7,7 +7,6 @@ use std::{ path::PathBuf, }; -use libafl::inputs::UsesInput; use libafl_qemu_sys::{GuestAddr, MapInfo}; #[cfg(not(feature = "clippy"))] @@ -107,18 +106,19 @@ where } #[allow(clippy::needless_pass_by_value)] // no longer a problem with nightly -fn gen_readwrite_guest_asan( +fn gen_readwrite_guest_asan( _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, addr: *mut TCGTemp, info: MemAccessInfo, ) -> Option where + ET: EmulatorModuleTuple, F: AddressFilter, - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let h = emulator_modules.get_mut::>().unwrap(); if !h.must_instrument(pc) { @@ -154,47 +154,50 @@ where unsafe fn libafl_tcg_gen_asan(addr: *mut TCGTemp, size: usize) {} #[allow(clippy::needless_pass_by_value)] // no longer a problem with nightly -fn guest_trace_error_asan( +fn guest_trace_error_asan( _qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, _id: u64, _addr: GuestAddr, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { panic!("I really shouldn't be here"); } #[allow(clippy::needless_pass_by_value)] // no longer a problem with nightly -fn guest_trace_error_n_asan( +fn guest_trace_error_n_asan( _qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, _id: u64, _addr: GuestAddr, _n: usize, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { panic!("I really shouldn't be here either"); } -impl EmulatorModule for AsanGuestModule +impl EmulatorModule for AsanGuestModule where F: AddressFilter, - S: Unpin + UsesInput, + I: Unpin, + S: Unpin, { type ModuleAddressFilter = F; fn pre_qemu_init( &mut self, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, qemu_params: &mut QemuParams, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { let mut args = qemu_params.to_cli(); @@ -265,9 +268,9 @@ where self.asan_lib = Some(asan_lib); } - fn post_qemu_init(&mut self, qemu: Qemu, _emulator_modules: &mut EmulatorModules) + fn post_qemu_init(&mut self, qemu: Qemu, _emulator_modules: &mut EmulatorModules) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { for mapping in qemu.mappings() { println!("mapping: {mapping:#?}"); @@ -306,28 +309,29 @@ where fn first_exec( &mut self, _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: &mut S, ) where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { emulator_modules.reads( - Hook::Function(gen_readwrite_guest_asan::), - Hook::Function(guest_trace_error_asan::), - Hook::Function(guest_trace_error_asan::), - Hook::Function(guest_trace_error_asan::), - Hook::Function(guest_trace_error_asan::), - Hook::Function(guest_trace_error_n_asan::), + Hook::Function(gen_readwrite_guest_asan::), + Hook::Function(guest_trace_error_asan::), + Hook::Function(guest_trace_error_asan::), + Hook::Function(guest_trace_error_asan::), + Hook::Function(guest_trace_error_asan::), + Hook::Function(guest_trace_error_n_asan::), ); emulator_modules.writes( - Hook::Function(gen_readwrite_guest_asan::), - Hook::Function(guest_trace_error_asan::), - Hook::Function(guest_trace_error_asan::), - Hook::Function(guest_trace_error_asan::), - Hook::Function(guest_trace_error_asan::), - Hook::Function(guest_trace_error_n_asan::), + Hook::Function(gen_readwrite_guest_asan::), + Hook::Function(guest_trace_error_asan::), + Hook::Function(guest_trace_error_asan::), + Hook::Function(guest_trace_error_asan::), + Hook::Function(guest_trace_error_asan::), + Hook::Function(guest_trace_error_n_asan::), ); } diff --git a/libafl_qemu/src/modules/usermode/injections.rs b/libafl_qemu/src/modules/usermode/injections.rs index 6ccfc0d523..ca7b933c77 100644 --- a/libafl_qemu/src/modules/usermode/injections.rs +++ b/libafl_qemu/src/modules/usermode/injections.rs @@ -14,7 +14,7 @@ use std::{ffi::CStr, fmt::Display, fs, os::raw::c_char, path::Path}; use hashbrown::HashMap; -use libafl::{inputs::UsesInput, Error}; +use libafl::Error; use libafl_qemu_sys::GuestAddr; use serde::{Deserialize, Serialize}; @@ -214,14 +214,15 @@ impl InjectionModule { }) } - fn on_call_check( + fn on_call_check( qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, id: usize, parameter: u8, ) where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let reg: GuestAddr = qemu .current_cpu() @@ -262,26 +263,27 @@ impl InjectionModule { } } -impl EmulatorModule for InjectionModule +impl EmulatorModule for InjectionModule where - S: Unpin + UsesInput, + I: Unpin, + S: Unpin, { type ModuleAddressFilter = NopAddressFilter; - fn post_qemu_init(&mut self, _qemu: Qemu, emulator_modules: &mut EmulatorModules) + fn post_qemu_init(&mut self, _qemu: Qemu, emulator_modules: &mut EmulatorModules) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { - emulator_modules.pre_syscalls(Hook::Function(syscall_hook::)); + emulator_modules.pre_syscalls(Hook::Function(syscall_hook::)); } fn first_exec( &mut self, qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: &mut S, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { let mut libs: Vec = Vec::new(); @@ -354,10 +356,10 @@ where #[expect(clippy::too_many_arguments)] #[allow(clippy::needless_pass_by_value)] // no longer a problem with nightly -fn syscall_hook( +fn syscall_hook( // Our instantiated [`EmulatorModules`] _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, // Syscall number syscall: i32, @@ -372,8 +374,9 @@ fn syscall_hook( _x7: GuestAddr, ) -> SyscallHookResult where - ET: EmulatorModuleTuple, - S: Unpin + UsesInput, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { log::trace!("syscall_hook {syscall} {SYS_execve}"); debug_assert!(i32::try_from(SYS_execve).is_ok()); diff --git a/libafl_qemu/src/modules/usermode/snapshot.rs b/libafl_qemu/src/modules/usermode/snapshot.rs index 00c1fdfe3c..01068944d9 100644 --- a/libafl_qemu/src/modules/usermode/snapshot.rs +++ b/libafl_qemu/src/modules/usermode/snapshot.rs @@ -2,7 +2,6 @@ use std::{cell::UnsafeCell, mem::MaybeUninit, sync::Mutex}; use hashbrown::{HashMap, HashSet}; -use libafl::inputs::UsesInput; use libafl_qemu_sys::{GuestAddr, MmapPerms}; use meminterval::{Interval, IntervalTree}; use thread_local::ThreadLocal; @@ -694,42 +693,43 @@ impl Default for SnapshotModule { } } -impl EmulatorModule for SnapshotModule +impl EmulatorModule for SnapshotModule where - S: Unpin + UsesInput, + I: Unpin, + S: Unpin, { type ModuleAddressFilter = NopAddressFilter; - fn post_qemu_init(&mut self, _qemu: Qemu, emulator_modules: &mut EmulatorModules) + fn post_qemu_init(&mut self, _qemu: Qemu, emulator_modules: &mut EmulatorModules) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { if emulator_modules.get::().is_none() { // The ASan module, if present, will call the tracer hook for the snapshot helper as opt emulator_modules.writes( Hook::Empty, - Hook::Function(trace_write_snapshot::), - Hook::Function(trace_write_snapshot::), - Hook::Function(trace_write_snapshot::), - Hook::Function(trace_write_snapshot::), - Hook::Function(trace_write_n_snapshot::), + Hook::Function(trace_write_snapshot::), + Hook::Function(trace_write_snapshot::), + Hook::Function(trace_write_snapshot::), + Hook::Function(trace_write_snapshot::), + Hook::Function(trace_write_n_snapshot::), ); } if !self.accurate_unmap { - emulator_modules.pre_syscalls(Hook::Function(filter_mmap_snapshot::)); + emulator_modules.pre_syscalls(Hook::Function(filter_mmap_snapshot::)); } - emulator_modules.post_syscalls(Hook::Function(trace_mmap_snapshot::)); + emulator_modules.post_syscalls(Hook::Function(trace_mmap_snapshot::)); } fn pre_exec( &mut self, qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + _emulator_modules: &mut EmulatorModules, _state: &mut S, - _input: &S::Input, + _input: &I, ) where - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, { if self.empty { self.snapshot(qemu); @@ -747,39 +747,41 @@ where } } -pub fn trace_write_snapshot( +pub fn trace_write_snapshot( _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, _id: u64, addr: GuestAddr, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let h = emulator_modules.get_mut::().unwrap(); h.access(addr, SIZE); } -pub fn trace_write_n_snapshot( +pub fn trace_write_n_snapshot( _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, _id: u64, addr: GuestAddr, size: usize, ) where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { let h = emulator_modules.get_mut::().unwrap(); h.access(addr, size); } #[expect(clippy::too_many_arguments)] -pub fn filter_mmap_snapshot( +pub fn filter_mmap_snapshot( _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, sys_num: i32, a0: GuestAddr, @@ -792,8 +794,9 @@ pub fn filter_mmap_snapshot( _a7: GuestAddr, ) -> SyscallHookResult where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { if i64::from(sys_num) == SYS_munmap { let h = emulator_modules.get_mut::().unwrap(); @@ -805,9 +808,9 @@ where } #[expect(non_upper_case_globals, clippy::too_many_arguments)] -pub fn trace_mmap_snapshot( +pub fn trace_mmap_snapshot( _qemu: Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, result: GuestAddr, sys_num: i32, @@ -821,8 +824,9 @@ pub fn trace_mmap_snapshot( _a7: GuestAddr, ) -> GuestAddr where - S: Unpin + UsesInput, - ET: EmulatorModuleTuple, + ET: EmulatorModuleTuple, + I: Unpin, + S: Unpin, { // NOT A COMPLETE LIST OF MEMORY EFFECTS match i64::from(sys_num) { diff --git a/libafl_qemu/src/modules/utils/filters.rs b/libafl_qemu/src/modules/utils/filters.rs index e3b5246a44..ffcb95572a 100644 --- a/libafl_qemu/src/modules/utils/filters.rs +++ b/libafl_qemu/src/modules/utils/filters.rs @@ -260,11 +260,7 @@ pub(crate) static mut NOP_PAGE_FILTER: UnsafeCell = UnsafeCell::n #[cfg(all(feature = "systemmode", test))] mod tests { - use libafl::{ - inputs::{NopInput, UsesInput}, - state::NopState, - HasMetadata, - }; + use libafl::{inputs::NopInput, state::NopState, HasMetadata}; use libafl_bolts::tuples::tuple_list; use crate::modules::{ @@ -281,11 +277,12 @@ mod tests { page_filter: PF, } - impl EmulatorModule for DummyModule + impl EmulatorModule for DummyModule where AF: AddressFilter + 'static, PF: PageFilter + 'static, - S: Unpin + UsesInput + HasMetadata, + I: Unpin, + S: Unpin + HasMetadata, { type ModuleAddressFilter = AF; type ModulePageFilter = PF; @@ -307,14 +304,15 @@ mod tests { } } - fn gen_module( + fn gen_module( af: AF, pf: PF, - ) -> impl EmulatorModule + ) -> impl EmulatorModule where AF: AddressFilter, PF: PageFilter, - S: HasMetadata + UsesInput + Unpin, + I: Unpin, + S: HasMetadata + Unpin, { DummyModule { address_filter: af, diff --git a/libafl_qemu/src/qemu/hooks.rs b/libafl_qemu/src/qemu/hooks.rs index f7f08dcae4..f55b8caf04 100644 --- a/libafl_qemu/src/qemu/hooks.rs +++ b/libafl_qemu/src/qemu/hooks.rs @@ -5,7 +5,7 @@ use core::{ffi::c_void, fmt::Debug, mem::transmute, ptr}; -use libafl::{executors::hooks::inprocess::inprocess_get_state, inputs::UsesInput}; +use libafl::executors::hooks::inprocess::inprocess_get_state; #[cfg(feature = "usermode")] use libafl_qemu_sys::libafl_dump_core_hook; use libafl_qemu_sys::{CPUArchStatePtr, CPUStatePtr, FatPtr, GuestAddr, GuestUsize}; @@ -103,24 +103,26 @@ impl Hook { macro_rules! create_pre_init_wrapper { ($name:ident, ($($param:ident : $param_type:ty),*)) => { paste::paste! { - pub extern "C" fn [](hook: &mut (), $($param: $param_type),*) + pub extern "C" fn [](hook: &mut (), $($param: $param_type),*) where - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { unsafe { - let modules = EmulatorModules::::emulator_modules_mut_unchecked(); - let func: fn(&mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(ptr::from_mut::<()>(hook)); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let func: fn(&mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(ptr::from_mut::<()>(hook)); func(modules, inprocess_get_state::(), $($param),*); } } - pub extern "C" fn [](hook: &mut FatPtr, $($param: $param_type),*) + pub extern "C" fn [](hook: &mut FatPtr, $($param: $param_type),*) where - S: Unpin + UsesInput, + I: Unpin, + S: Unpin, { unsafe { - let modules = EmulatorModules::::emulator_modules_mut_unchecked(); - let func: &mut Box, Option<&mut S>, $($param_type),*)> = &mut *(ptr::from_mut::(hook) as *mut Box, Option<&mut S>, $($param_type),*)>); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let func: &mut Box, Option<&mut S>, $($param_type),*)> = &mut *(ptr::from_mut::(hook) as *mut Box, Option<&mut S>, $($param_type),*)>); func(modules, inprocess_get_state::(), $($param),*); } } @@ -128,24 +130,26 @@ macro_rules! create_pre_init_wrapper { }; ($name:ident, ($($param:ident : $param_type:ty),*), $ret_type:ty) => { paste::paste! { - pub extern "C" fn [](hook: &mut (), $($param: $param_type),*) -> $ret_type + pub extern "C" fn [](hook: &mut (), $($param: $param_type),*) -> $ret_type where - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { unsafe { - let modules = EmulatorModules::::emulator_modules_mut_unchecked(); - let func: fn(&mut EmulatorModules, Option<&mut S>, $($param_type),*) -> $ret_type= transmute(ptr::from_mut::<()>(hook)); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let func: fn(&mut EmulatorModules, Option<&mut S>, $($param_type),*) -> $ret_type= transmute(ptr::from_mut::<()>(hook)); func(modules, inprocess_get_state::(), $($param),*) } } - pub extern "C" fn [](hook: &mut FatPtr, $($param: $param_type),*) -> $ret_type + pub extern "C" fn [](hook: &mut FatPtr, $($param: $param_type),*) -> $ret_type where - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { unsafe { - let modules = EmulatorModules::::emulator_modules_mut_unchecked(); - let func: &mut Box, Option<&mut S>, $($param_type),*) -> $ret_type> = &mut *(ptr::from_mut::(hook) as *mut Box, Option<&mut S>, $($param_type),*) -> $ret_type>); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let func: &mut Box, Option<&mut S>, $($param_type),*) -> $ret_type> = &mut *(ptr::from_mut::(hook) as *mut Box, Option<&mut S>, $($param_type),*) -> $ret_type>); func(modules, inprocess_get_state::(), $($param),*) } } @@ -156,26 +160,28 @@ macro_rules! create_pre_init_wrapper { macro_rules! create_wrapper { ($name:ident, ($($param:ident : $param_type:ty),*)) => { paste::paste! { - pub extern "C" fn [](hook: &mut (), $($param: $param_type),*) + pub extern "C" fn [](hook: &mut (), $($param: $param_type),*) where - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { unsafe { let qemu = Qemu::get_unchecked(); - let modules = EmulatorModules::::emulator_modules_mut_unchecked(); - let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(ptr::from_mut::<()>(hook)); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(ptr::from_mut::<()>(hook)); func(qemu, modules, inprocess_get_state::(), $($param),*); } } - pub extern "C" fn [](hook: &mut FatPtr, $($param: $param_type),*) + pub extern "C" fn [](hook: &mut FatPtr, $($param: $param_type),*) where - S: Unpin + UsesInput, + I: Unpin, + S: Unpin, { unsafe { let qemu = Qemu::get_unchecked(); - let modules = EmulatorModules::::emulator_modules_mut_unchecked(); - let func: &mut Box, Option<&mut S>, $($param_type),*)> = &mut *(ptr::from_mut::(hook) as *mut Box, Option<&mut S>, $($param_type),*)>); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let func: &mut Box, Option<&mut S>, $($param_type),*)> = &mut *(ptr::from_mut::(hook) as *mut Box, Option<&mut S>, $($param_type),*)>); func(qemu, modules, inprocess_get_state::(), $($param),*); } } @@ -183,26 +189,28 @@ macro_rules! create_wrapper { }; ($name:ident, ($($param:ident : $param_type:ty),*), $ret_type:ty) => { paste::paste! { - pub extern "C" fn [](hook: &mut (), $($param: $param_type),*) -> $ret_type + pub extern "C" fn [](hook: &mut (), $($param: $param_type),*) -> $ret_type where - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { unsafe { let qemu = Qemu::get_unchecked(); - let modules = EmulatorModules::::emulator_modules_mut_unchecked(); - let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) -> $ret_type= transmute(ptr::from_mut::<()>(hook)); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) -> $ret_type= transmute(ptr::from_mut::<()>(hook)); func(qemu, modules, inprocess_get_state::(), $($param),*) } } - pub extern "C" fn [](hook: &mut FatPtr, $($param: $param_type),*) -> $ret_type + pub extern "C" fn [](hook: &mut FatPtr, $($param: $param_type),*) -> $ret_type where - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { unsafe { let qemu = Qemu::get_unchecked(); - let modules = EmulatorModules::::emulator_modules_mut_unchecked(); - let func: &mut Box, Option<&mut S>, $($param_type),*) -> $ret_type> = &mut *(ptr::from_mut::(hook) as *mut Box, Option<&mut S>, $($param_type),*) -> $ret_type>); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let func: &mut Box, Option<&mut S>, $($param_type),*) -> $ret_type> = &mut *(ptr::from_mut::(hook) as *mut Box, Option<&mut S>, $($param_type),*) -> $ret_type>); func(qemu, modules, inprocess_get_state::(), $($param),*) } } @@ -213,25 +221,26 @@ macro_rules! create_wrapper { macro_rules! create_pre_exec_wrapper { ($name:ident, ($($param:ident : $param_type:ty),*), $hook_id:ident) => { paste::paste! { - pub extern "C" fn [<$name _pre_exec_hook_wrapper>](hook: &mut HookState<$hook_id>, $($param: $param_type),*) + pub extern "C" fn [<$name _pre_exec_hook_wrapper>](hook: &mut HookState<$hook_id>, $($param: $param_type),*) where - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { unsafe { let qemu = Qemu::get_unchecked(); - let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); match &mut hook.pre_run { HookRepr::Function(ptr) => { - let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(*ptr); func(qemu, modules, inprocess_get_state::(), $($param),*) } HookRepr::Closure(ptr) => { let func: &mut Box< - dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), + dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), > = &mut *(ptr::from_mut::(ptr) as *mut Box< - dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), + dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), >); func(qemu, modules, inprocess_get_state::(), $($param),*) } @@ -246,25 +255,26 @@ macro_rules! create_pre_exec_wrapper { macro_rules! create_post_exec_wrapper { ($name:ident, ($($param:ident : $param_type:ty),*), $hook_id:ident) => { paste::paste! { - pub extern "C" fn [<$name _post_exec_hook_wrapper>](hook: &mut HookState<$hook_id>, $($param: $param_type),*) + pub extern "C" fn [<$name _post_exec_hook_wrapper>](hook: &mut HookState<$hook_id>, $($param: $param_type),*) where - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { unsafe { let qemu = Qemu::get_unchecked(); - let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); match &mut hook.post_run { HookRepr::Function(ptr) => { - let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(*ptr); func(qemu, modules, inprocess_get_state::(), $($param),*); } HookRepr::Closure(ptr) => { let func: &mut Box< - dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), + dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), > = &mut *(ptr::from_mut::(ptr) as *mut Box< - dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), + dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), >); func(qemu, modules, inprocess_get_state::(), $($param),*); } @@ -279,24 +289,25 @@ macro_rules! create_post_exec_wrapper { macro_rules! create_gen_wrapper { ($name:ident, ($($param:ident : $param_type:ty),*), $ret_type:ty, $execs:literal, $hook_id:ident) => { paste::paste! { - pub extern "C" fn [<$name _gen_hook_wrapper>](hook: &mut TcgHookState<{ $execs }, $hook_id>, $($param: $param_type),*) -> $ret_type + pub extern "C" fn [<$name _gen_hook_wrapper>](hook: &mut TcgHookState<{ $execs }, $hook_id>, $($param: $param_type),*) -> $ret_type where - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { unsafe { let qemu = Qemu::get_unchecked(); - let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); match &mut hook.gen { HookRepr::Function(ptr) => { - let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) -> Option<$ret_type> = + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) -> Option<$ret_type> = transmute(*ptr); func(qemu, modules, inprocess_get_state::(), $($param),*).map_or(SKIP_EXEC_HOOK, |id| id) } HookRepr::Closure(ptr) => { let func: &mut Box< - dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) -> Option<$ret_type>, - > = &mut *(ptr::from_mut::(ptr) as *mut Box, Option<&mut S>, $($param_type),*) -> Option<$ret_type>>); + dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) -> Option<$ret_type>, + > = &mut *(ptr::from_mut::(ptr) as *mut Box, Option<&mut S>, $($param_type),*) -> Option<$ret_type>>); func(qemu, modules, inprocess_get_state::(), $($param),*).map_or(SKIP_EXEC_HOOK, |id| id) } _ => 0, @@ -310,24 +321,25 @@ macro_rules! create_gen_wrapper { macro_rules! create_post_gen_wrapper { ($name:ident, ($($param:ident : $param_type:ty),*), $execs:literal, $hook_id:ident) => { paste::paste! { - pub extern "C" fn [<$name _post_gen_hook_wrapper>](hook: &mut TcgHookState<{ $execs }, $hook_id>, $($param: $param_type),*) + pub extern "C" fn [<$name _post_gen_hook_wrapper>](hook: &mut TcgHookState<{ $execs }, $hook_id>, $($param: $param_type),*) where - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { unsafe { let qemu = Qemu::get_unchecked(); - let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); match &mut hook.post_gen { HookRepr::Function(ptr) => { - let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(*ptr); func(qemu, modules, inprocess_get_state::(), $($param),*); } HookRepr::Closure(ptr) => { let func: &mut Box< - dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), - > = &mut *(ptr::from_mut::(ptr) as *mut Box, Option<&mut S>, $($param_type),*)>); + dyn FnMut(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*), + > = &mut *(ptr::from_mut::(ptr) as *mut Box, Option<&mut S>, $($param_type),*)>); func(qemu, modules, inprocess_get_state::(), $($param),*); } _ => (), @@ -341,22 +353,23 @@ macro_rules! create_post_gen_wrapper { macro_rules! create_exec_wrapper { ($name:ident, ($($param:ident : $param_type:ty),*), $execidx:literal, $execs:literal, $hook_id:ident) => { paste::paste! { - pub extern "C" fn [<$name _ $execidx _exec_hook_wrapper>](hook: &mut TcgHookState<{ $execs }, $hook_id>, $($param: $param_type),*) + pub extern "C" fn [<$name _ $execidx _exec_hook_wrapper>](hook: &mut TcgHookState<{ $execs }, $hook_id>, $($param: $param_type),*) where - S: UsesInput + Unpin, + I: Unpin, + S: Unpin, { unsafe { let qemu = Qemu::get_unchecked(); - let modules = EmulatorModules::::emulator_modules_mut_unchecked(); + let modules = EmulatorModules::::emulator_modules_mut_unchecked(); match &mut hook.execs[$execidx] { HookRepr::Function(ptr) => { - let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(*ptr); + let func: fn(Qemu, &mut EmulatorModules, Option<&mut S>, $($param_type),*) = transmute(*ptr); func(qemu, modules, inprocess_get_state::(), $($param),*); } HookRepr::Closure(ptr) => { - let func: &mut Box, Option<&mut S>, $($param_type),*)> = - &mut *(ptr::from_mut::(ptr) as *mut Box, Option<&mut S>, $($param_type),*)>); + let func: &mut Box, Option<&mut S>, $($param_type),*)> = + &mut *(ptr::from_mut::(ptr) as *mut Box, Option<&mut S>, $($param_type),*)>); func(qemu, modules, inprocess_get_state::(), $($param),*); } _ => (), @@ -407,13 +420,13 @@ macro_rules! create_hook_id { macro_rules! create_hook_types { ($name:ident, $fn_type:ty, $closure_type:ty, $raw_type:ty) => { paste::paste! { - pub type [<$name HookFn>] = $fn_type; - pub type [<$name HookClosure>] = $closure_type; + pub type [<$name HookFn>] = $fn_type; + pub type [<$name HookClosure>] = $closure_type; pub type [<$name HookRaw>] = $raw_type; - pub type [<$name Hook>] = Hook< - [<$name HookFn>], - [<$name HookClosure>], + pub type [<$name Hook>] = Hook< + [<$name HookFn>], + [<$name HookClosure>], [<$name HookRaw>], >; } @@ -423,8 +436,8 @@ macro_rules! create_hook_types { // Instruction hook wrappers create_hook_types!( Instruction, - fn(Qemu, &mut EmulatorModules, Option<&mut S>, GuestAddr), - Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr)>, + fn(Qemu, &mut EmulatorModules, Option<&mut S>, GuestAddr), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr)>, extern "C" fn(*const (), pc: GuestAddr) ); create_hook_id!(Instruction, libafl_qemu_remove_instruction_hook, true); @@ -433,8 +446,8 @@ create_wrapper!(instruction, (pc: GuestAddr)); // Backdoor hook wrappers create_hook_types!( Backdoor, - fn(Qemu, &mut EmulatorModules, Option<&mut S>, cpu: CPUArchStatePtr, GuestAddr), - Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr)>, + fn(Qemu, &mut EmulatorModules, Option<&mut S>, cpu: CPUArchStatePtr, GuestAddr), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr)>, extern "C" fn(libafl_qemu_opaque: *const (), cpu: CPUArchStatePtr, pc: GuestAddr) ); create_hook_id!(Backdoor, libafl_qemu_remove_backdoor_hook, true); @@ -446,7 +459,7 @@ create_hook_types!( PreSyscall, fn( Qemu, - &mut EmulatorModules, + &mut EmulatorModules, Option<&mut S>, sys_num: i32, a0: GuestAddr, @@ -461,7 +474,7 @@ create_hook_types!( Box< dyn for<'a> FnMut( Qemu, - &'a mut EmulatorModules, + &'a mut EmulatorModules, Option<&'a mut S>, i32, GuestAddr, @@ -512,7 +525,7 @@ create_hook_types!( PostSyscall, fn( Qemu, - &mut EmulatorModules, + &mut EmulatorModules, Option<&mut S>, res: GuestAddr, sys_num: i32, @@ -528,7 +541,7 @@ create_hook_types!( Box< dyn for<'a> FnMut( Qemu, - &'a mut EmulatorModules, + &'a mut EmulatorModules, Option<&mut S>, GuestAddr, i32, @@ -579,10 +592,10 @@ create_wrapper!( // New thread hook wrappers create_hook_types!( NewThread, - fn(&mut EmulatorModules, Option<&mut S>, env: CPUArchStatePtr, tid: u32) -> bool, + fn(&mut EmulatorModules, Option<&mut S>, env: CPUArchStatePtr, tid: u32) -> bool, Box< dyn for<'a> FnMut( - &'a mut EmulatorModules, + &'a mut EmulatorModules, Option<&'a mut S>, CPUArchStatePtr, u32, @@ -596,14 +609,14 @@ create_pre_init_wrapper!(new_thread, (env: CPUArchStatePtr, tid: u32), bool); // CPU Run hook wrappers create_hook_types!( CpuPreRun, - fn(Qemu, &mut EmulatorModules, Option<&mut S>, cpu: CPUStatePtr), - Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, CPUStatePtr)>, + fn(Qemu, &mut EmulatorModules, Option<&mut S>, cpu: CPUStatePtr), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, CPUStatePtr)>, extern "C" fn(libafl_qemu_opaque: *const (), cpu: CPUStatePtr) ); create_hook_types!( CpuPostRun, - fn(Qemu, &mut EmulatorModules, Option<&mut S>, cpu: CPUStatePtr), - Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, CPUStatePtr)>, + fn(Qemu, &mut EmulatorModules, Option<&mut S>, cpu: CPUStatePtr), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, CPUStatePtr)>, extern "C" fn(libafl_qemu_opaque: *const (), cpu: CPUStatePtr) ); create_hook_id!(CpuRun, libafl_qemu_remove_cpu_run_hook, false); @@ -616,7 +629,7 @@ create_hook_types!( EdgeGen, fn( Qemu, - &mut EmulatorModules, + &mut EmulatorModules, Option<&mut S>, src: GuestAddr, dest: GuestAddr, @@ -624,7 +637,7 @@ create_hook_types!( Box< dyn for<'a> FnMut( Qemu, - &'a mut EmulatorModules, + &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr, GuestAddr, @@ -634,8 +647,8 @@ create_hook_types!( ); create_hook_types!( EdgeExec, - fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64), - Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, u64)>, + fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, u64)>, unsafe extern "C" fn(libafl_qemu_opaque: *const (), id: u64) ); create_hook_id!(Edge, libafl_qemu_remove_edge_hook, true); @@ -645,11 +658,11 @@ create_exec_wrapper!(edge, (id: u64), 0, 1, EdgeHookId); // Block hook wrappers create_hook_types!( BlockGen, - fn(Qemu, &mut EmulatorModules, Option<&mut S>, pc: GuestAddr) -> Option, + fn(Qemu, &mut EmulatorModules, Option<&mut S>, pc: GuestAddr) -> Option, Box< dyn for<'a> FnMut( Qemu, - &'a mut EmulatorModules, + &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr, ) -> Option, @@ -658,11 +671,17 @@ create_hook_types!( ); create_hook_types!( BlockPostGen, - fn(Qemu, &mut EmulatorModules, Option<&mut S>, pc: GuestAddr, block_length: GuestUsize), + fn( + Qemu, + &mut EmulatorModules, + Option<&mut S>, + pc: GuestAddr, + block_length: GuestUsize, + ), Box< dyn for<'a> FnMut( Qemu, - &'a mut EmulatorModules, + &'a mut EmulatorModules, Option<&mut S>, GuestAddr, GuestUsize, @@ -672,8 +691,8 @@ create_hook_types!( ); create_hook_types!( BlockExec, - fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64), - Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, u64)>, + fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64), + Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, u64)>, unsafe extern "C" fn(libafl_qemu_opaque: *const (), id: u64) ); @@ -687,7 +706,7 @@ create_hook_types!( ReadGen, fn( Qemu, - emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, Option<&mut S>, pc: GuestAddr, addr: *mut TCGTemp, @@ -696,7 +715,7 @@ create_hook_types!( Box< dyn for<'a> FnMut( Qemu, - &'a mut EmulatorModules, + &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr, *mut TCGTemp, @@ -712,17 +731,25 @@ create_hook_types!( ); create_hook_types!( ReadExec, - fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr), - Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, u64, GuestAddr)>, + fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr), + Box< + dyn for<'a> FnMut( + Qemu, + &'a mut EmulatorModules, + Option<&'a mut S>, + u64, + GuestAddr, + ), + >, unsafe extern "C" fn(libafl_qemu_opaque: *const (), id: u64, addr: GuestAddr) ); create_hook_types!( ReadExecN, - fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr, size: usize), + fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr, size: usize), Box< dyn for<'a> FnMut( Qemu, - &'a mut EmulatorModules, + &'a mut EmulatorModules, Option<&'a mut S>, u64, GuestAddr, @@ -750,7 +777,7 @@ create_hook_types!( WriteGen, fn( Qemu, - &mut EmulatorModules, + &mut EmulatorModules, Option<&mut S>, pc: GuestAddr, addr: *mut TCGTemp, @@ -759,7 +786,7 @@ create_hook_types!( Box< dyn for<'a> FnMut( Qemu, - &'a mut EmulatorModules, + &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr, *mut TCGTemp, @@ -775,17 +802,25 @@ create_hook_types!( ); create_hook_types!( WriteExec, - fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr), - Box FnMut(Qemu, &'a mut EmulatorModules, Option<&'a mut S>, u64, GuestAddr)>, + fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr), + Box< + dyn for<'a> FnMut( + Qemu, + &'a mut EmulatorModules, + Option<&'a mut S>, + u64, + GuestAddr, + ), + >, unsafe extern "C" fn(libafl_qemu_opaque: *const (), id: u64, addr: GuestAddr) ); create_hook_types!( WriteExecN, - fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr, size: usize), + fn(Qemu, &mut EmulatorModules, Option<&mut S>, id: u64, addr: GuestAddr, size: usize), Box< dyn for<'a> FnMut( Qemu, - &'a mut EmulatorModules, + &'a mut EmulatorModules, Option<&'a mut S>, u64, GuestAddr, @@ -813,7 +848,7 @@ create_hook_types!( CmpGen, fn( Qemu, - &mut EmulatorModules, + &mut EmulatorModules, Option<&mut S>, pc: GuestAddr, size: usize, @@ -821,7 +856,7 @@ create_hook_types!( Box< dyn for<'a> FnMut( Qemu, - &'a mut EmulatorModules, + &'a mut EmulatorModules, Option<&'a mut S>, GuestAddr, usize, @@ -829,9 +864,9 @@ create_hook_types!( >, unsafe extern "C" fn(libafl_qemu_opaque: *const (), pc: GuestAddr, size: usize) -> u64 ); -pub type CmpExecHook = Hook< - fn(&mut EmulatorModules, Option<&mut S>, id: u64, v0: SZ, v1: SZ), - Box FnMut(&'a mut EmulatorModules, Option<&'a mut S>, u64, SZ, SZ)>, +pub type CmpExecHook = Hook< + fn(&mut EmulatorModules, Option<&mut S>, id: u64, v0: SZ, v1: SZ), + Box FnMut(&'a mut EmulatorModules, Option<&'a mut S>, u64, SZ, SZ)>, unsafe extern "C" fn(*const (), id: u64, v0: SZ, v1: SZ), >; create_hook_id!(Cmp, libafl_qemu_remove_cmp_hook, true); @@ -843,9 +878,9 @@ create_exec_wrapper!(cmp, (id: u64, v0: u64, v1: u64), 3, 4, CmpHookId); // Crash hook wrappers #[cfg(feature = "usermode")] -pub type CrashHookFn = fn(Qemu, &mut EmulatorModules, i32); +pub type CrashHookFn = fn(Qemu, &mut EmulatorModules, i32); #[cfg(feature = "usermode")] -pub type CrashHookClosure = Box, i32)>; +pub type CrashHookClosure = Box, i32)>; /// The thin wrapper around QEMU hooks. /// It is considered unsafe to use it directly. diff --git a/libafl_qemu/src/sync_exit.rs b/libafl_qemu/src/sync_exit.rs index 3693092d8b..d9634e758c 100644 --- a/libafl_qemu/src/sync_exit.rs +++ b/libafl_qemu/src/sync_exit.rs @@ -1,9 +1,8 @@ -use std::fmt::{Debug, Formatter}; +use std::fmt::Debug; use enum_map::Enum; -use libafl::inputs::UsesInput; -use crate::{command::CommandManager, get_exit_arch_regs, GuestReg, Regs, CPU}; +use crate::{get_exit_arch_regs, GuestReg, Regs, CPU}; #[derive(Debug, Clone, Enum)] pub enum ExitArgs { @@ -17,48 +16,19 @@ pub enum ExitArgs { Arg6, } -pub struct CustomInsn -where - CM: CommandManager, - S: UsesInput, -{ - command: CM::Commands, +#[derive(Clone, Debug)] +pub struct CustomInsn { + command: C, } -impl Clone for CustomInsn -where - CM: CommandManager, - S: UsesInput, -{ - fn clone(&self) -> Self { - Self { - command: self.command.clone(), - } - } -} - -impl Debug for CustomInsn -where - CM: CommandManager, - S: UsesInput, -{ - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "Sync Exit") - } -} - -impl CustomInsn -where - CM: CommandManager, - S: UsesInput, -{ +impl CustomInsn { #[must_use] - pub fn new(command: CM::Commands) -> Self { + pub fn new(command: C) -> Self { Self { command } } #[must_use] - pub fn command(&self) -> &CM::Commands { + pub fn command(&self) -> &C { &self.command } diff --git a/libafl_sugar/src/qemu.rs b/libafl_sugar/src/qemu.rs index 097b6e9587..9fd46972da 100644 --- a/libafl_sugar/src/qemu.rs +++ b/libafl_sugar/src/qemu.rs @@ -231,7 +231,7 @@ where } }; - let mut harness = |_emulator: &mut Emulator<_, _, _, _, _>, + let mut harness = |_emulator: &mut Emulator<_, _, _, _, _, _, _>, _state: &mut _, input: &BytesInput| { let target = input.target_bytes(); @@ -352,7 +352,7 @@ where .build() .unwrap()); - let mut harness = |_emulator: &mut Emulator<_, _, _, _, _>, + let mut harness = |_emulator: &mut Emulator<_, _, _, _, _, _, _>, _state: &mut _, input: &BytesInput| { let target = input.target_bytes(); diff --git a/libafl_targets/src/windows_asan.rs b/libafl_targets/src/windows_asan.rs index 4f97431444..5cfe3a4365 100644 --- a/libafl_targets/src/windows_asan.rs +++ b/libafl_targets/src/windows_asan.rs @@ -30,20 +30,20 @@ extern "C" { /// /// # Safety /// Calls the unsafe `__sanitizer_set_death_callback` symbol, but should be safe to call otherwise. -pub unsafe fn setup_asan_callback(_executor: &E, _event_mgr: &EM, _fuzzer: &Z) +pub unsafe fn setup_asan_callback(_executor: &E, _event_mgr: &EM, _fuzzer: &Z) where - E: Executor::Input, S, Z> + HasObservers, - E::Observers: ObserversTuple<::Input, S>, + E: Executor + HasObservers, + E::Observers: ObserversTuple, EM: EventFirer + EventRestarter, - OF: Feedback::Input, E::Observers, S>, + OF: Feedback, S: HasExecutions + HasSolutions + HasCurrentTestcase + HasCorpus - + UsesInput::Input>, - S::Solutions: Corpus::Input>, + + UsesInput, + S::Solutions: Corpus, Z: HasObjective, - ::Input: Input + Clone, + I: Input + Clone, { - __sanitizer_set_death_callback(Some(asan_death_handler::)); + __sanitizer_set_death_callback(Some(asan_death_handler::)); }