diff --git a/fuzzers/fuzzbench/fuzzbench_fork_qemu/src/fuzzer.rs b/fuzzers/fuzzbench/fuzzbench_fork_qemu/src/fuzzer.rs index 3b44b674ec..306831d84e 100644 --- a/fuzzers/fuzzbench/fuzzbench_fork_qemu/src/fuzzer.rs +++ b/fuzzers/fuzzbench/fuzzbench_fork_qemu/src/fuzzer.rs @@ -156,7 +156,7 @@ fn fuzz( CmpLogChildModule::default(), ); - let mut emulator = Emulator::new( + let emulator = Emulator::new( args.as_slice(), env.as_slice(), emulator_modules, @@ -356,7 +356,7 @@ fn fuzz( }; let executor = QemuForkExecutor::new( - &mut emulator, + emulator, &mut harness, tuple_list!(edges_observer, time_observer), &mut fuzzer, diff --git a/fuzzers/fuzzbench/fuzzbench_qemu/src/fuzzer.rs b/fuzzers/fuzzbench/fuzzbench_qemu/src/fuzzer.rs index 6c65a08592..659610b4dd 100644 --- a/fuzzers/fuzzbench/fuzzbench_qemu/src/fuzzer.rs +++ b/fuzzers/fuzzbench/fuzzbench_qemu/src/fuzzer.rs @@ -329,7 +329,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 = |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(); @@ -366,12 +366,12 @@ fn fuzz( //QemuSnapshotHelper::new() ); - let mut emulator = + let emulator = Emulator::new_with_qemu(qemu, modules, NopEmulatorExitHandler, NopCommandManager)?; // Create the executor for an in-process function with one observer for edge coverage and one for the execution time let executor = QemuExecutor::new( - &mut emulator, + emulator, &mut harness, tuple_list!(edges_observer, time_observer), &mut fuzzer, diff --git a/fuzzers/qemu/qemu_cmin/src/fuzzer.rs b/fuzzers/qemu/qemu_cmin/src/fuzzer.rs index b4b5201062..4bf1ebec46 100644 --- a/fuzzers/qemu/qemu_cmin/src/fuzzer.rs +++ b/fuzzers/qemu/qemu_cmin/src/fuzzer.rs @@ -223,11 +223,11 @@ pub fn fuzz() -> Result<(), Error> { let modules = tuple_list!(EdgeCoverageChildModule::default(),); - let mut emulator = + let emulator = Emulator::new_with_qemu(qemu, modules, NopEmulatorExitHandler, NopCommandManager)?; let mut executor = QemuForkExecutor::new( - &mut emulator, + emulator, &mut harness, tuple_list!(edges_observer), &mut fuzzer, diff --git a/fuzzers/qemu/qemu_coverage/src/fuzzer.rs b/fuzzers/qemu/qemu_coverage/src/fuzzer.rs index 78d2577347..dac399fff2 100644 --- a/fuzzers/qemu/qemu_coverage/src/fuzzer.rs +++ b/fuzzers/qemu/qemu_coverage/src/fuzzer.rs @@ -178,7 +178,7 @@ pub fn fuzz() { } }; - let mut harness = |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(); @@ -241,7 +241,7 @@ pub fn fuzz() { false, )); - let mut emulator = Emulator::new_with_qemu( + let emulator = Emulator::new_with_qemu( qemu, emulator_modules, NopEmulatorExitHandler, @@ -250,7 +250,7 @@ pub fn fuzz() { .unwrap(); let mut executor = QemuExecutor::new( - &mut emulator, + emulator, &mut harness, (), &mut fuzzer, diff --git a/fuzzers/qemu/qemu_launcher/src/instance.rs b/fuzzers/qemu/qemu_launcher/src/instance.rs index 12ba81c432..867b42b784 100644 --- a/fuzzers/qemu/qemu_launcher/src/instance.rs +++ b/fuzzers/qemu/qemu_launcher/src/instance.rs @@ -149,12 +149,13 @@ impl<'a, M: Monitor> Instance<'a, M> { state.add_metadata(tokens); let harness = Harness::new(self.qemu)?; - let mut harness = |input: &BytesInput| harness.run(input); + let mut harness = + |_emulator: &mut Emulator<_, _, _, _>, input: &BytesInput| harness.run(input); // A fuzzer with feedbacks and a corpus scheduler let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); - let mut emulator = Emulator::new_with_qemu( + let emulator = Emulator::new_with_qemu( *self.qemu, modules, NopEmulatorExitHandler, @@ -165,7 +166,7 @@ impl<'a, M: Monitor> Instance<'a, M> { if self.options.is_cmplog_core(self.core_id) { // Create a QEMU in-process executor let executor = QemuExecutor::new( - &mut emulator, + emulator, &mut harness, observers, &mut fuzzer, @@ -203,7 +204,7 @@ impl<'a, M: Monitor> Instance<'a, M> { } else { // Create a QEMU in-process executor let mut executor = QemuExecutor::new( - &mut emulator, + emulator, &mut harness, observers, &mut fuzzer, diff --git a/fuzzers/qemu/qemu_systemmode/Cargo.toml b/fuzzers/qemu/qemu_systemmode/Cargo.toml index 5219dce31c..58c0b7248b 100644 --- a/fuzzers/qemu/qemu_systemmode/Cargo.toml +++ b/fuzzers/qemu/qemu_systemmode/Cargo.toml @@ -25,9 +25,9 @@ lto = "fat" codegen-units = 1 [dependencies] -libafl = { path = "../../../libafl/" } -libafl_bolts = { path = "../../../libafl_bolts/" } -libafl_qemu = { path = "../../../libafl_qemu/", features = [ +libafl = { path = "../../../libafl" } +libafl_bolts = { path = "../../../libafl_bolts" } +libafl_qemu = { path = "../../../libafl_qemu", features = [ "arm", "systemmode", ] } diff --git a/fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs b/fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs index 74c09f950c..b0eee27c2a 100644 --- a/fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs +++ b/fuzzers/qemu/qemu_systemmode/src/fuzzer_breakpoint.rs @@ -32,7 +32,7 @@ use libafl_qemu::{ command::{EndCommand, StartCommand, StdCommandManager}, elf::EasyElf, emu::Emulator, - executor::{stateful::StatefulQemuExecutor, QemuExecutorState}, + executor::QemuExecutor, modules::edges::{ edges_map_mut_ptr, EdgeCoverageModule, EDGES_MAP_SIZE_IN_USE, MAX_EDGES_FOUND, }, @@ -103,7 +103,7 @@ pub fn fuzz() { let modules = tuple_list!(EdgeCoverageModule::default()); // Create emulator - let mut emu = Emulator::new(&args, &env, modules, emu_exit_handler, cmd_manager).unwrap(); + let emu = Emulator::new(&args, &env, modules, emu_exit_handler, cmd_manager).unwrap(); // Set breakpoints of interest with corresponding commands. emu.add_breakpoint( @@ -127,15 +127,9 @@ pub fn fuzz() { println!("Devices = {:?}", devices); // The wrapped harness function, calling out to the LLVM-style harness - let mut harness = - |input: &BytesInput, qemu_executor_state: &mut QemuExecutorState<_, _, _, _>| unsafe { - qemu_executor_state - .emulator_mut() - .run(input) - .unwrap() - .try_into() - .unwrap() - }; + let mut harness = |emulator: &mut Emulator<_, _, _, _>, input: &BytesInput| unsafe { + emulator.run(input).unwrap().try_into().unwrap() + }; // Create an observation channel using the coverage map let edges_observer = unsafe { @@ -197,8 +191,8 @@ pub fn fuzz() { ); // Create a QEMU in-process executor - let mut executor = StatefulQemuExecutor::new( - &mut emu, + let mut executor = QemuExecutor::new( + emu, &mut harness, tuple_list!(edges_observer, time_observer), &mut fuzzer, diff --git a/fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs b/fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs index 441cc5e1e6..14ddd0c5c1 100644 --- a/fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs +++ b/fuzzers/qemu/qemu_systemmode/src/fuzzer_classic.rs @@ -32,7 +32,7 @@ use libafl_bolts::{ use libafl_qemu::{ command::NopCommandManager, elf::EasyElf, - executor::{stateful::StatefulQemuExecutor, QemuExecutorState}, + executor::QemuExecutor, modules::edges::{ edges_map_mut_ptr, EdgeCoverageModule, EDGES_MAP_SIZE_IN_USE, MAX_EDGES_FOUND, }, @@ -93,7 +93,7 @@ pub fn fuzz() { let emulator_modules = tuple_list!(EdgeCoverageModule::default()); - let mut emulator = Emulator::new( + let emulator = Emulator::new( args.as_slice(), env.as_slice(), emulator_modules, @@ -129,8 +129,7 @@ pub fn fuzz() { let snap = qemu.create_fast_snapshot(true); // The wrapped harness function, calling out to the LLVM-style harness - let mut harness = |input: &BytesInput, state: &mut QemuExecutorState<_, _, _, _>| { - let emulator = state.emulator_mut(); + let mut harness = |emulator: &mut Emulator<_, _, _, _>, input: &BytesInput| { let target = input.target_bytes(); let mut buf = target.as_slice(); let len = buf.len(); @@ -229,8 +228,8 @@ pub fn fuzz() { let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); // Create a QEMU in-process executor - let mut executor = StatefulQemuExecutor::new( - &mut emulator, + let mut executor = QemuExecutor::new( + emulator, &mut harness, tuple_list!(edges_observer, time_observer), &mut fuzzer, diff --git a/fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs b/fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs index ca60a95c0f..29e1b6358d 100644 --- a/fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs +++ b/fuzzers/qemu/qemu_systemmode/src/fuzzer_sync_exit.rs @@ -29,7 +29,7 @@ use libafl_bolts::{ use libafl_qemu::{ command::StdCommandManager, emu::Emulator, - executor::{stateful::StatefulQemuExecutor, QemuExecutorState}, + executor::QemuExecutor, modules::edges::{ edges_map_mut_ptr, EdgeCoverageModule, EDGES_MAP_SIZE_IN_USE, MAX_EDGES_FOUND, }, @@ -66,21 +66,15 @@ pub fn fuzz() { // Choose modules to use let modules = tuple_list!(EdgeCoverageModule::default()); - let mut emu = Emulator::new(&args, &env, modules, emu_exit_handler, cmd_manager).unwrap(); // Create the emulator + let emu = Emulator::new(&args, &env, modules, emu_exit_handler, cmd_manager).unwrap(); // Create the emulator let devices = emu.list_devices(); println!("Devices = {:?}", devices); // The wrapped harness function, calling out to the LLVM-style harness - let mut harness = - |input: &BytesInput, qemu_executor_state: &mut QemuExecutorState<_, _, _, _>| unsafe { - qemu_executor_state - .emulator_mut() - .run(input) - .unwrap() - .try_into() - .unwrap() - }; + let mut harness = |emulator: &mut Emulator<_, _, _, _>, input: &BytesInput| unsafe { + emulator.run(input).unwrap().try_into().unwrap() + }; // Create an observation channel using the coverage map let edges_observer = unsafe { @@ -142,8 +136,8 @@ pub fn fuzz() { ); // Create a QEMU in-process executor - let mut executor = StatefulQemuExecutor::new( - &mut emu, + let mut executor = QemuExecutor::new( + emu, &mut harness, tuple_list!(edges_observer, time_observer), &mut fuzzer, diff --git a/libafl/src/executors/inprocess/stateful.rs b/libafl/src/executors/inprocess/stateful.rs index 9c1579f0a3..a94d3192aa 100644 --- a/libafl/src/executors/inprocess/stateful.rs +++ b/libafl/src/executors/inprocess/stateful.rs @@ -33,8 +33,8 @@ pub type StatefulInProcessExecutor<'a, H, OT, S, ES> = /// 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(&::Input, &mut ES) -> ExitKind, - Box::Input, &mut ES) -> ExitKind>, + dyn FnMut(&mut ES, &::Input) -> ExitKind, + Box::Input) -> ExitKind>, (), OT, S, @@ -46,7 +46,7 @@ pub type OwnedInProcessExecutor = StatefulGenericInProcessExecutor< #[allow(dead_code)] pub struct StatefulGenericInProcessExecutor where - H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized, + H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, HB: BorrowMut, HT: ExecutorHooksTuple, OT: ObserversTuple, @@ -63,7 +63,7 @@ where impl Debug for StatefulGenericInProcessExecutor where - H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized, + H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, HB: BorrowMut, HT: ExecutorHooksTuple, OT: ObserversTuple + Debug, @@ -79,7 +79,7 @@ where impl UsesState for StatefulGenericInProcessExecutor where - H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized, + H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, HB: BorrowMut, HT: ExecutorHooksTuple, OT: ObserversTuple, @@ -90,7 +90,7 @@ where impl UsesObservers for StatefulGenericInProcessExecutor where - H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized, + H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, HB: BorrowMut, HT: ExecutorHooksTuple, OT: ObserversTuple, @@ -103,7 +103,7 @@ impl Executor for StatefulGenericInProcessExecutor where EM: UsesState, - H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized, + H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, HB: BorrowMut, HT: ExecutorHooksTuple, OT: ObserversTuple, @@ -125,7 +125,7 @@ where } self.inner.hooks.pre_exec_all(state, input); - let ret = self.harness_fn.borrow_mut()(input, &mut self.exposed_executor_state); + let ret = self.harness_fn.borrow_mut()(&mut self.exposed_executor_state, input); self.inner.hooks.post_exec_all(state, input); self.inner.leave_target(fuzzer, state, mgr, input); @@ -135,7 +135,7 @@ where impl HasObservers for StatefulGenericInProcessExecutor where - H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized, + H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, HB: BorrowMut, HT: ExecutorHooksTuple, OT: ObserversTuple, @@ -154,7 +154,7 @@ where impl<'a, H, OT, S, ES> StatefulInProcessExecutor<'a, H, OT, S, ES> where - H: FnMut(&::Input, &mut ES) -> ExitKind + ?Sized, + H: FnMut(&mut ES, &::Input) -> ExitKind + ?Sized, OT: ObserversTuple, S: HasExecutions + HasSolutions + HasCorpus + State, { @@ -265,7 +265,7 @@ where impl StatefulGenericInProcessExecutor where - H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized, + H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, HB: BorrowMut, HT: ExecutorHooksTuple, OT: ObserversTuple, @@ -284,7 +284,7 @@ where impl StatefulGenericInProcessExecutor where - H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized, + H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized, HB: BorrowMut, HT: ExecutorHooksTuple, OT: ObserversTuple, @@ -414,7 +414,7 @@ where impl HasInProcessHooks for StatefulGenericInProcessExecutor where - H: FnMut(&::Input, &mut ES) -> ExitKind + ?Sized, + H: FnMut(&mut ES, &::Input) -> ExitKind + ?Sized, HB: BorrowMut, HT: ExecutorHooksTuple, OT: ObserversTuple, diff --git a/libafl_qemu/Cargo.toml b/libafl_qemu/Cargo.toml index 5081a25a63..de5351a8ad 100644 --- a/libafl_qemu/Cargo.toml +++ b/libafl_qemu/Cargo.toml @@ -110,14 +110,14 @@ goblin = "0.8" libc = "0.2" strum = "0.26" strum_macros = "0.26" -syscall-numbers = "3.0" +syscall-numbers = "4.0" meminterval = "0.4" thread_local = "1.1.4" capstone = "0.12.0" rangemap = "1.3" log = "0.4" object = "0.36" -addr2line = "0.23" +addr2line = "0.24" typed-arena = "2.0" paste = "1" enum-map = "2.7" diff --git a/libafl_qemu/libafl_qemu_build/src/bindings.rs b/libafl_qemu/libafl_qemu_build/src/bindings.rs index 6929d5fc64..0b8f954291 100644 --- a/libafl_qemu/libafl_qemu_build/src/bindings.rs +++ b/libafl_qemu/libafl_qemu_build/src/bindings.rs @@ -58,6 +58,7 @@ const WRAPPER_HEADER: &str = r#" #include "hw/core/sysemu-cpu-ops.h" #include "exec/address-spaces.h" #include "sysemu/tcg.h" +#include "sysemu/runstate.h" #include "sysemu/replay.h" #include "libafl/syx-snapshot/device-save.h" @@ -148,6 +149,7 @@ pub fn generate( .allowlist_type("libafl_mapinfo") .allowlist_type("IntervalTreeRoot") .allowlist_function("qemu_user_init") + .allowlist_function("qemu_system_debug_request") .allowlist_function("target_mmap") .allowlist_function("target_mprotect") .allowlist_function("target_munmap") diff --git a/libafl_qemu/src/executor/mod.rs b/libafl_qemu/src/executor.rs similarity index 71% rename from libafl_qemu/src/executor/mod.rs rename to libafl_qemu/src/executor.rs index 3150235ada..d97772dcc3 100644 --- a/libafl_qemu/src/executor/mod.rs +++ b/libafl_qemu/src/executor.rs @@ -1,11 +1,11 @@ //! A `QEMU`-based executor for binary-only instrumentation in `LibAFL` -#[cfg(emulation_mode = "usermode")] -use core::ptr; use core::{ ffi::c_void, fmt::{self, Debug, Formatter}, time::Duration, }; +#[cfg(emulation_mode = "usermode")] +use std::ptr; #[cfg(feature = "fork")] use libafl::{ @@ -15,7 +15,7 @@ use libafl::{ events::{EventFirer, EventRestarter}, executors::{ hooks::inprocess::InProcessExecutorHandlerData, - inprocess::{HasInProcessHooks, InProcessExecutor}, + inprocess::{stateful::StatefulInProcessExecutor, HasInProcessHooks}, Executor, ExitKind, HasObservers, }, feedbacks::Feedback, @@ -30,58 +30,29 @@ use libafl_bolts::{ os::unix_signals::{siginfo_t, ucontext_t, Signal}, tuples::RefIndexable, }; +#[cfg(emulation_mode = "systemmode")] +use libafl_qemu_sys::qemu_system_debug_request; #[cfg(emulation_mode = "usermode")] -use crate::emu::EmulatorModules; +use crate::EmulatorModules; use crate::{command::CommandManager, modules::EmulatorModuleTuple, Emulator, EmulatorExitHandler}; -/// A version of `QemuExecutor` with a state accessible from the harness. -pub mod stateful; - -pub struct QemuExecutorState<'a, CM, EH, ET, S> -where - CM: CommandManager, - EH: EmulatorExitHandler, - ET: EmulatorModuleTuple, - S: Unpin + State + HasExecutions, -{ - emulator: &'a mut Emulator, +#[cfg(emulation_mode = "usermode")] +extern "C" { + // Original QEMU user signal handler + fn libafl_qemu_handle_crash(signal: i32, info: *mut siginfo_t, puc: *mut c_void); } pub struct QemuExecutor<'a, CM, EH, H, OT, ET, S> where CM: CommandManager, EH: EmulatorExitHandler, - H: FnMut(&S::Input) -> ExitKind, + H: FnMut(&mut Emulator, &S::Input) -> ExitKind, + S: Unpin + State + HasExecutions, OT: ObserversTuple, ET: EmulatorModuleTuple, - S: Unpin + State + HasExecutions, { - inner: InProcessExecutor<'a, H, OT, S>, - state: QemuExecutorState<'a, CM, EH, ET, S>, -} - -impl<'a, CM, EH, H, OT, ET, S> Debug for QemuExecutor<'a, CM, EH, H, OT, ET, S> -where - CM: CommandManager + Debug, - EH: EmulatorExitHandler, - H: FnMut(&S::Input) -> ExitKind, - S: Unpin + State + HasExecutions + Debug, - OT: ObserversTuple + Debug, - ET: EmulatorModuleTuple + Debug, -{ - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("QemuExecutor") - .field("emulator", &self.state.emulator) - .field("inner", &self.inner) - .finish() - } -} - -#[cfg(emulation_mode = "usermode")] -extern "C" { - // Original QEMU user signal handler - fn libafl_qemu_handle_crash(signal: i32, info: *mut siginfo_t, puc: *mut c_void); + inner: StatefulInProcessExecutor<'a, H, OT, S, Emulator>, } #[cfg(emulation_mode = "usermode")] @@ -103,17 +74,12 @@ pub unsafe fn inproc_qemu_crash_handler<'a, E, EM, OF, Z, ET, S>( Some(v) => ptr::from_mut::(*v) as *mut c_void, None => ptr::null_mut(), }; - libafl_qemu_handle_crash(signal as i32, info, puc); + libafl_qemu_handle_crash(signal as i32, std::ptr::from_mut::(info), puc); } #[cfg(emulation_mode = "systemmode")] pub(crate) static mut BREAK_ON_TMOUT: bool = false; -#[cfg(emulation_mode = "systemmode")] -extern "C" { - fn qemu_system_debug_request(); -} - #[cfg(emulation_mode = "systemmode")] pub unsafe fn inproc_qemu_timeout_handler<'a, E, EM, OF, Z>( signal: Signal, @@ -136,58 +102,19 @@ pub unsafe fn inproc_qemu_timeout_handler<'a, E, EM, OF, Z>( } } -impl<'a, CM, EH, ET, S> QemuExecutorState<'a, CM, EH, ET, S> +impl<'a, CM, EH, H, OT, ET, S> Debug for QemuExecutor<'a, CM, EH, H, OT, ET, S> where CM: CommandManager, EH: EmulatorExitHandler, + H: FnMut(&mut Emulator, &S::Input) -> ExitKind, + S: Unpin + State + HasExecutions, + OT: ObserversTuple + Debug, ET: EmulatorModuleTuple + Debug, - S: Unpin + State + HasExecutions + HasCorpus + HasSolutions, { - #[cfg(emulation_mode = "systemmode")] - pub fn new(emulator: &'a mut Emulator) -> Result - where - E: Executor + HasInProcessHooks + HasObservers, - EM: EventFirer + EventRestarter, - OF: Feedback, - OT: ObserversTuple, - Z: HasObjective, - { - Ok(QemuExecutorState { emulator }) - } - - #[cfg(emulation_mode = "usermode")] - pub fn new(emulator: &'a mut Emulator) -> Result - where - E: Executor + HasInProcessHooks + HasObservers, - EM: EventFirer + EventRestarter, - OF: Feedback, - OT: ObserversTuple, - Z: HasObjective + ExecutionProcessor + HasScheduler, - { - #[cfg(emulation_mode = "usermode")] - { - let handler = |emulator_modules: &mut EmulatorModules, host_sig| { - eprintln!("Crashed with signal {host_sig}"); - unsafe { - libafl::executors::inprocess::generic_inproc_crash_handler::(); - } - if let Some(cpu) = emulator_modules.qemu().current_cpu() { - eprint!("Context:\n{}", cpu.display_context()); - } - }; - - emulator.modules_mut().crash_closure(Box::new(handler)); - } - Ok(QemuExecutorState { emulator }) - } - - #[must_use] - pub fn emulator(&self) -> &Emulator { - self.emulator - } - - pub fn emulator_mut(&mut self) -> &mut Emulator { - self.emulator + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct("QemuExecutor") + .field("inner", &self.inner) + .finish() } } @@ -195,13 +122,13 @@ impl<'a, CM, EH, H, OT, ET, S> QemuExecutor<'a, CM, EH, H, OT, ET, S> where CM: CommandManager, EH: EmulatorExitHandler, - H: FnMut(&S::Input) -> ExitKind, + H: FnMut(&mut Emulator, &S::Input) -> ExitKind, S: Unpin + State + HasExecutions, OT: ObserversTuple, ET: EmulatorModuleTuple + Debug, { pub fn new( - emulator: &'a mut Emulator, + emulator: Emulator, harness_fn: &'a mut H, observers: OT, fuzzer: &mut Z, @@ -215,31 +142,51 @@ where S: Unpin + State + HasExecutions + HasCorpus + HasSolutions, Z: HasObjective + HasScheduler + ExecutionProcessor, { - let mut inner = InProcessExecutor::with_timeout( - harness_fn, observers, fuzzer, state, event_mgr, timeout, + let mut inner = StatefulInProcessExecutor::with_timeout( + harness_fn, emulator, observers, fuzzer, state, event_mgr, timeout, )?; #[cfg(emulation_mode = "usermode")] { - inner.inprocess_hooks_mut().crash_handler = - inproc_qemu_crash_handler::, EM, OF, Z, ET, S> - as *const c_void; + inner.inprocess_hooks_mut().crash_handler = inproc_qemu_crash_handler::< + StatefulInProcessExecutor<'a, H, OT, S, Emulator>, + EM, + OF, + Z, + ET, + S, + > as *const c_void; + + let handler = |emulator_modules: &mut EmulatorModules, host_sig| { + eprintln!("Crashed with signal {host_sig}"); + unsafe { + libafl::executors::inprocess::generic_inproc_crash_handler::(); + } + if let Some(cpu) = emulator_modules.qemu().current_cpu() { + eprint!("Context:\n{}", cpu.display_context()); + } + }; + + inner + .exposed_executor_state_mut() + .modules_mut() + .crash_closure(Box::new(handler)); } #[cfg(emulation_mode = "systemmode")] { - inner.inprocess_hooks_mut().timeout_handler = - inproc_qemu_timeout_handler::, EM, OF, Z> - as *const c_void; + inner.inprocess_hooks_mut().timeout_handler = inproc_qemu_timeout_handler::< + StatefulInProcessExecutor<'a, H, OT, S, Emulator>, + EM, + OF, + Z, + > as *const c_void; } - let state = - QemuExecutorState::new::, EM, OF, OT, Z>(emulator)?; - - Ok(Self { inner, state }) + Ok(Self { inner }) } - pub fn inner(&self) -> &InProcessExecutor<'a, H, OT, S> { + pub fn inner(&self) -> &StatefulInProcessExecutor<'a, H, OT, S, Emulator> { &self.inner } @@ -250,43 +197,10 @@ where } } - pub fn inner_mut(&mut self) -> &mut InProcessExecutor<'a, H, OT, S> { - &mut self.inner - } -} - -impl<'a, CM, EH, ET, S> QemuExecutorState<'a, CM, EH, ET, S> -where - CM: CommandManager, - EH: EmulatorExitHandler, - ET: EmulatorModuleTuple, - S: Unpin + State + HasExecutions, -{ - fn pre_exec(&mut self, input: &E::Input) - where - E: Executor, - EM: EventFirer + EventRestarter, - OF: Feedback, - Z: HasObjective, - { - self.emulator.first_exec_all(); - - self.emulator.pre_exec_all(input); - } - - fn post_exec( + pub fn inner_mut( &mut self, - input: &E::Input, - observers: &mut OT, - exit_kind: &mut ExitKind, - ) where - E: Executor + HasObservers, - EM: EventFirer + EventRestarter, - OT: ObserversTuple, - OF: Feedback, - Z: HasObjective, - { - self.emulator.post_exec_all(input, observers, exit_kind); + ) -> &mut StatefulInProcessExecutor<'a, H, OT, S, Emulator> { + &mut self.inner } } @@ -295,7 +209,7 @@ where CM: CommandManager, EH: EmulatorExitHandler, EM: EventFirer + EventRestarter, - H: FnMut(&S::Input) -> ExitKind, + H: FnMut(&mut Emulator, &S::Input) -> ExitKind, S: Unpin + State + HasExecutions + HasCorpus + HasSolutions, OT: ObserversTuple, OF: Feedback, @@ -309,13 +223,18 @@ where mgr: &mut EM, input: &Self::Input, ) -> Result { - self.state.pre_exec::(input); + self.inner.exposed_executor_state_mut().first_exec_all(); + + self.inner.exposed_executor_state_mut().pre_exec_all(input); + let mut exit_kind = self.inner.run_target(fuzzer, state, mgr, input)?; - self.state.post_exec::( + + self.inner.exposed_executor_state.post_exec_all( input, - &mut *self.inner.observers_mut(), + &mut *self.inner.inner.observers_mut(), &mut exit_kind, ); + Ok(exit_kind) } } @@ -324,7 +243,7 @@ impl<'a, CM, EH, H, OT, ET, S> UsesState for QemuExecutor<'a, CM, EH, H, OT, ET, where CM: CommandManager, EH: EmulatorExitHandler, - H: FnMut(&S::Input) -> ExitKind, + H: FnMut(&mut Emulator, &S::Input) -> ExitKind, OT: ObserversTuple, ET: EmulatorModuleTuple, S: Unpin + State + HasExecutions, @@ -336,7 +255,7 @@ impl<'a, CM, EH, H, OT, ET, S> UsesObservers for QemuExecutor<'a, CM, EH, H, OT, where CM: CommandManager, EH: EmulatorExitHandler, - H: FnMut(&S::Input) -> ExitKind, + H: FnMut(&mut Emulator, &S::Input) -> ExitKind, OT: ObserversTuple, ET: EmulatorModuleTuple, S: Unpin + State + HasExecutions, @@ -348,7 +267,7 @@ impl<'a, CM, EH, H, OT, ET, S> HasObservers for QemuExecutor<'a, CM, EH, H, OT, where CM: CommandManager, EH: EmulatorExitHandler, - H: FnMut(&S::Input) -> ExitKind, + H: FnMut(&mut Emulator, &S::Input) -> ExitKind, S: Unpin + State + HasExecutions, OT: ObserversTuple, ET: EmulatorModuleTuple, @@ -378,7 +297,7 @@ where Z: UsesState, { inner: InProcessForkExecutor<'a, H, OT, S, SP, EM, Z>, - state: QemuExecutorState<'a, CM, EH, ET, S>, + emulator: Emulator, } #[cfg(feature = "fork")] @@ -397,8 +316,8 @@ where { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QemuForkExecutor") - .field("emulator", &self.state.emulator) .field("inner", &self.inner) + .field("emulator", &self.emulator) .finish() } } @@ -419,7 +338,7 @@ where Z: HasObjective, { pub fn new( - emulator: &'a mut Emulator, + emulator: Emulator, harness_fn: &'a mut H, observers: OT, fuzzer: &mut Z, @@ -440,7 +359,7 @@ where timeout, shmem_provider, )?, - state: QemuExecutorState { emulator }, + emulator, }) } @@ -453,7 +372,11 @@ where } pub fn emulator(&self) -> &Emulator { - self.state.emulator + &self.emulator + } + + pub fn emulator_mut(&mut self) -> &Emulator { + &mut self.emulator } } diff --git a/libafl_qemu/src/executor/stateful.rs b/libafl_qemu/src/executor/stateful.rs deleted file mode 100644 index b257e9d8d9..0000000000 --- a/libafl_qemu/src/executor/stateful.rs +++ /dev/null @@ -1,217 +0,0 @@ -//! A `QEMU`-based executor for binary-only instrumentation in `LibAFL` -use core::{ - ffi::c_void, - fmt::{self, Debug, Formatter}, - time::Duration, -}; - -use libafl::{ - events::{EventFirer, EventRestarter}, - executors::{ - inprocess::{stateful::StatefulInProcessExecutor, HasInProcessHooks}, - Executor, ExitKind, HasObservers, - }, - feedbacks::Feedback, - fuzzer::HasObjective, - observers::{ObserversTuple, UsesObservers}, - state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState}, - Error, ExecutionProcessor, HasScheduler, -}; -use libafl_bolts::tuples::RefIndexable; - -#[cfg(emulation_mode = "usermode")] -use crate::executor::inproc_qemu_crash_handler; -#[cfg(emulation_mode = "systemmode")] -use crate::executor::{inproc_qemu_timeout_handler, BREAK_ON_TMOUT}; -use crate::{ - command::CommandManager, executor::QemuExecutorState, modules::EmulatorModuleTuple, Emulator, - EmulatorExitHandler, -}; - -pub struct StatefulQemuExecutor<'a, CM, EH, H, OT, ET, S> -where - CM: CommandManager, - EH: EmulatorExitHandler, - H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind, - S: Unpin + State + HasExecutions, - OT: ObserversTuple, - ET: EmulatorModuleTuple, -{ - inner: StatefulInProcessExecutor<'a, H, OT, S, QemuExecutorState<'a, CM, EH, ET, S>>, -} - -impl<'a, CM, EH, H, OT, ET, S> Debug for StatefulQemuExecutor<'a, CM, EH, H, OT, ET, S> -where - CM: CommandManager, - EH: EmulatorExitHandler, - H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind, - S: Unpin + State + HasExecutions, - OT: ObserversTuple + Debug, - ET: EmulatorModuleTuple + Debug, -{ - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - f.debug_struct("StatefulQemuExecutor") - .field("inner", &self.inner) - .finish() - } -} - -impl<'a, CM, EH, H, OT, ET, S> StatefulQemuExecutor<'a, CM, EH, H, OT, ET, S> -where - CM: CommandManager, - EH: EmulatorExitHandler, - H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind, - S: Unpin + State + HasExecutions, - OT: ObserversTuple, - ET: EmulatorModuleTuple + Debug, -{ - pub fn new( - emulator: &'a mut Emulator, - harness_fn: &'a mut H, - observers: OT, - fuzzer: &mut Z, - state: &mut S, - event_mgr: &mut EM, - timeout: Duration, - ) -> Result - where - EM: EventFirer + EventRestarter, - OF: Feedback, - S: Unpin + State + HasExecutions + HasCorpus + HasSolutions, - Z: HasObjective + HasScheduler + ExecutionProcessor, - { - let qemu_state = QemuExecutorState::new::< - StatefulInProcessExecutor<'a, H, OT, S, QemuExecutorState<'a, CM, EH, ET, S>>, - EM, - OF, - OT, - Z, - >(emulator)?; - - let mut inner = StatefulInProcessExecutor::with_timeout( - harness_fn, qemu_state, observers, fuzzer, state, event_mgr, timeout, - )?; - - #[cfg(emulation_mode = "usermode")] - { - inner.inprocess_hooks_mut().crash_handler = inproc_qemu_crash_handler::< - StatefulInProcessExecutor<'a, H, OT, S, QemuExecutorState<'a, CM, EH, ET, S>>, - EM, - OF, - Z, - ET, - S, - > as *const c_void; - } - - #[cfg(emulation_mode = "systemmode")] - { - inner.inprocess_hooks_mut().timeout_handler = inproc_qemu_timeout_handler::< - StatefulInProcessExecutor<'a, H, OT, S, QemuExecutorState<'a, CM, EH, ET, S>>, - EM, - OF, - Z, - > as *const c_void; - } - - Ok(Self { inner }) - } - - pub fn inner( - &self, - ) -> &StatefulInProcessExecutor<'a, H, OT, S, QemuExecutorState<'a, CM, EH, ET, S>> { - &self.inner - } - - #[cfg(emulation_mode = "systemmode")] - pub fn break_on_timeout(&mut self) { - unsafe { - BREAK_ON_TMOUT = true; - } - } - - pub fn inner_mut( - &mut self, - ) -> &mut StatefulInProcessExecutor<'a, H, OT, S, QemuExecutorState<'a, CM, EH, ET, S>> { - &mut self.inner - } -} - -impl<'a, CM, EH, EM, H, OT, OF, ET, S, Z> Executor - for StatefulQemuExecutor<'a, CM, EH, H, OT, ET, S> -where - CM: CommandManager, - EH: EmulatorExitHandler, - EM: EventFirer + EventRestarter, - H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind, - S: Unpin + State + HasExecutions + HasCorpus + HasSolutions, - OT: ObserversTuple, - OF: Feedback, - ET: EmulatorModuleTuple + Debug, - Z: HasObjective, -{ - fn run_target( - &mut self, - fuzzer: &mut Z, - state: &mut Self::State, - mgr: &mut EM, - input: &Self::Input, - ) -> Result { - self.inner - .exposed_executor_state_mut() - .pre_exec::(input); - let mut exit_kind = self.inner.run_target(fuzzer, state, mgr, input)?; - self.inner - .exposed_executor_state - .post_exec::( - input, - &mut *self.inner.inner.observers_mut(), - &mut exit_kind, - ); - Ok(exit_kind) - } -} - -impl<'a, CM, EH, H, OT, ET, S> UsesState for StatefulQemuExecutor<'a, CM, EH, H, OT, ET, S> -where - CM: CommandManager, - EH: EmulatorExitHandler, - H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind, - OT: ObserversTuple, - ET: EmulatorModuleTuple, - S: Unpin + State + HasExecutions, -{ - type State = S; -} - -impl<'a, CM, EH, H, OT, ET, S> UsesObservers for StatefulQemuExecutor<'a, CM, EH, H, OT, ET, S> -where - CM: CommandManager, - EH: EmulatorExitHandler, - H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind, - OT: ObserversTuple, - ET: EmulatorModuleTuple, - S: Unpin + State + HasExecutions, -{ - type Observers = OT; -} - -impl<'a, CM, EH, H, OT, ET, S> HasObservers for StatefulQemuExecutor<'a, CM, EH, H, OT, ET, S> -where - CM: CommandManager, - EH: EmulatorExitHandler, - H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind, - S: Unpin + State + HasExecutions, - OT: ObserversTuple, - ET: EmulatorModuleTuple, -{ - #[inline] - fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> { - self.inner.observers() - } - - #[inline] - fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> { - self.inner.observers_mut() - } -} diff --git a/libafl_sugar/src/qemu.rs b/libafl_sugar/src/qemu.rs index 203f5208fe..eed5c152b2 100644 --- a/libafl_sugar/src/qemu.rs +++ b/libafl_sugar/src/qemu.rs @@ -218,13 +218,6 @@ where let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); // The wrapped harness function, calling out to the LLVM-style harness - let mut harness = |input: &BytesInput| { - let target = input.target_bytes(); - let buf = target.as_slice(); - harness_bytes(buf); - ExitKind::Ok - }; - if self.use_cmplog.unwrap_or(false) { let modules = { #[cfg(not(any(feature = "mips", feature = "hexagon")))] @@ -237,7 +230,14 @@ where } }; - let mut emulator = Emulator::new_with_qemu( + let mut harness = |_emulator: &mut Emulator<_, _, _, _>, input: &BytesInput| { + let target = input.target_bytes(); + let buf = target.as_slice(); + harness_bytes(buf); + ExitKind::Ok + }; + + let emulator = Emulator::new_with_qemu( qemu, modules, NopEmulatorExitHandler, @@ -245,7 +245,7 @@ where )?; let executor = QemuExecutor::new( - &mut emulator, + emulator, &mut harness, tuple_list!(edges_observer, time_observer), &mut fuzzer, @@ -347,7 +347,14 @@ where } else { let tools = tuple_list!(EdgeCoverageModule::default()); - let mut emulator = Emulator::new_with_qemu( + let mut harness = |_emulator: &mut Emulator<_, _, _, _>, input: &BytesInput| { + let target = input.target_bytes(); + let buf = target.as_slice(); + harness_bytes(buf); + ExitKind::Ok + }; + + let emulator = Emulator::new_with_qemu( qemu, tools, NopEmulatorExitHandler, @@ -355,7 +362,7 @@ where )?; let mut executor = QemuExecutor::new( - &mut emulator, + emulator, &mut harness, tuple_list!(edges_observer, time_observer), &mut fuzzer,