Unify qemu executor (#2483)
* Remove stateless qemu executor * All harnesses take a reference to an emulator as parameter now * harness takes an emulator as first parameter, and input as second parameter (opposite of previous definition) * bump libafl qemu dependencies to the latest version
This commit is contained in:
parent
00806b177d
commit
13ba32ed2a
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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",
|
||||
] }
|
||||
|
@ -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,14 +127,8 @@ 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
|
||||
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,20 +66,14 @@ 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
|
||||
@ -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,
|
||||
|
@ -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<OT, S, ES> = StatefulGenericInProcessExecutor<
|
||||
dyn FnMut(&<S as UsesInput>::Input, &mut ES) -> ExitKind,
|
||||
Box<dyn FnMut(&<S as UsesInput>::Input, &mut ES) -> ExitKind>,
|
||||
dyn FnMut(&mut ES, &<S as UsesInput>::Input) -> ExitKind,
|
||||
Box<dyn FnMut(&mut ES, &<S as UsesInput>::Input) -> ExitKind>,
|
||||
(),
|
||||
OT,
|
||||
S,
|
||||
@ -46,7 +46,7 @@ pub type OwnedInProcessExecutor<OT, S, ES> = StatefulGenericInProcessExecutor<
|
||||
#[allow(dead_code)]
|
||||
pub struct StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S>,
|
||||
@ -63,7 +63,7 @@ where
|
||||
|
||||
impl<H, HB, HT, OT, S, ES> Debug for StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S> + Debug,
|
||||
@ -79,7 +79,7 @@ where
|
||||
|
||||
impl<H, HB, HT, OT, S, ES> UsesState for StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S>,
|
||||
@ -90,7 +90,7 @@ where
|
||||
|
||||
impl<H, HB, HT, OT, S, ES> UsesObservers for StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S>,
|
||||
@ -103,7 +103,7 @@ impl<EM, H, HB, HT, OT, S, Z, ES> Executor<EM, Z>
|
||||
for StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
EM: UsesState<State = S>,
|
||||
H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S>,
|
||||
@ -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<H, HB, HT, OT, S, ES> HasObservers for StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S>,
|
||||
@ -154,7 +154,7 @@ where
|
||||
|
||||
impl<'a, H, OT, S, ES> StatefulInProcessExecutor<'a, H, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&<S as UsesInput>::Input, &mut ES) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut ES, &<S as UsesInput>::Input) -> ExitKind + ?Sized,
|
||||
OT: ObserversTuple<S>,
|
||||
S: HasExecutions + HasSolutions + HasCorpus + State,
|
||||
{
|
||||
@ -265,7 +265,7 @@ where
|
||||
|
||||
impl<H, HB, HT, OT, S, ES> StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S>,
|
||||
@ -284,7 +284,7 @@ where
|
||||
|
||||
impl<H, HB, HT, OT, S, ES> StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&S::Input, &mut ES) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut ES, &S::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S>,
|
||||
@ -414,7 +414,7 @@ where
|
||||
impl<H, HB, HT, OT, S, ES> HasInProcessHooks<S>
|
||||
for StatefulGenericInProcessExecutor<H, HB, HT, OT, S, ES>
|
||||
where
|
||||
H: FnMut(&<S as UsesInput>::Input, &mut ES) -> ExitKind + ?Sized,
|
||||
H: FnMut(&mut ES, &<S as UsesInput>::Input) -> ExitKind + ?Sized,
|
||||
HB: BorrowMut<H>,
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S>,
|
||||
|
@ -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"
|
||||
|
@ -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")
|
||||
|
@ -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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
S: Unpin + State + HasExecutions,
|
||||
{
|
||||
emulator: &'a mut Emulator<CM, EH, ET, S>,
|
||||
#[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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
H: FnMut(&mut Emulator<CM, EH, ET, S>, &S::Input) -> ExitKind,
|
||||
S: Unpin + State + HasExecutions,
|
||||
OT: ObserversTuple<S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
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<EH, ET, S> + Debug,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S: Unpin + State + HasExecutions + Debug,
|
||||
OT: ObserversTuple<S> + Debug,
|
||||
ET: EmulatorModuleTuple<S> + 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<CM, EH, ET, S>>,
|
||||
}
|
||||
|
||||
#[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::<ucontext_t>(*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::<siginfo_t>(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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
H: FnMut(&mut Emulator<CM, EH, ET, S>, &S::Input) -> ExitKind,
|
||||
S: Unpin + State + HasExecutions,
|
||||
OT: ObserversTuple<S> + Debug,
|
||||
ET: EmulatorModuleTuple<S> + Debug,
|
||||
S: Unpin + State + HasExecutions + HasCorpus + HasSolutions,
|
||||
{
|
||||
#[cfg(emulation_mode = "systemmode")]
|
||||
pub fn new<E, EM, OF, OT, Z>(emulator: &'a mut Emulator<CM, EH, ET, S>) -> Result<Self, Error>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasInProcessHooks<S> + HasObservers,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<S>,
|
||||
OT: ObserversTuple<S>,
|
||||
Z: HasObjective<Objective = OF, State = S>,
|
||||
{
|
||||
Ok(QemuExecutorState { emulator })
|
||||
}
|
||||
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
pub fn new<E, EM, OF, OT, Z>(emulator: &'a mut Emulator<CM, EH, ET, S>) -> Result<Self, Error>
|
||||
where
|
||||
E: Executor<EM, Z, State = S> + HasInProcessHooks<S> + HasObservers,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<S>,
|
||||
OT: ObserversTuple<S>,
|
||||
Z: HasObjective<Objective = OF, State = S> + ExecutionProcessor + HasScheduler,
|
||||
{
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
{
|
||||
let handler = |emulator_modules: &mut EmulatorModules<ET, S>, host_sig| {
|
||||
eprintln!("Crashed with signal {host_sig}");
|
||||
unsafe {
|
||||
libafl::executors::inprocess::generic_inproc_crash_handler::<E, EM, OF, Z>();
|
||||
}
|
||||
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<CM, EH, ET, S> {
|
||||
self.emulator
|
||||
}
|
||||
|
||||
pub fn emulator_mut(&mut self) -> &mut Emulator<CM, EH, ET, S> {
|
||||
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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
H: FnMut(&mut Emulator<CM, EH, ET, S>, &S::Input) -> ExitKind,
|
||||
S: Unpin + State + HasExecutions,
|
||||
OT: ObserversTuple<S>,
|
||||
ET: EmulatorModuleTuple<S> + Debug,
|
||||
{
|
||||
pub fn new<EM, OF, Z>(
|
||||
emulator: &'a mut Emulator<CM, EH, ET, S>,
|
||||
emulator: Emulator<CM, EH, ET, S>,
|
||||
harness_fn: &'a mut H,
|
||||
observers: OT,
|
||||
fuzzer: &mut Z,
|
||||
@ -215,31 +142,51 @@ where
|
||||
S: Unpin + State + HasExecutions + HasCorpus + HasSolutions,
|
||||
Z: HasObjective<Objective = OF, State = S> + 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::<InProcessExecutor<'a, H, OT, S>, 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<CM, EH, ET, S>>,
|
||||
EM,
|
||||
OF,
|
||||
Z,
|
||||
ET,
|
||||
S,
|
||||
> as *const c_void;
|
||||
|
||||
let handler = |emulator_modules: &mut EmulatorModules<ET, S>, host_sig| {
|
||||
eprintln!("Crashed with signal {host_sig}");
|
||||
unsafe {
|
||||
libafl::executors::inprocess::generic_inproc_crash_handler::<Self, EM, OF, Z>();
|
||||
}
|
||||
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::<InProcessExecutor<'a, H, OT, S>, EM, OF, Z>
|
||||
as *const c_void;
|
||||
inner.inprocess_hooks_mut().timeout_handler = inproc_qemu_timeout_handler::<
|
||||
StatefulInProcessExecutor<'a, H, OT, S, Emulator<CM, EH, ET, S>>,
|
||||
EM,
|
||||
OF,
|
||||
Z,
|
||||
> as *const c_void;
|
||||
}
|
||||
|
||||
let state =
|
||||
QemuExecutorState::new::<InProcessExecutor<'a, H, OT, S>, 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<CM, EH, ET, S>> {
|
||||
&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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
S: Unpin + State + HasExecutions,
|
||||
{
|
||||
fn pre_exec<E, EM, OF, Z>(&mut self, input: &E::Input)
|
||||
where
|
||||
E: Executor<EM, Z, State = S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<S>,
|
||||
Z: HasObjective<Objective = OF, State = S>,
|
||||
{
|
||||
self.emulator.first_exec_all();
|
||||
|
||||
self.emulator.pre_exec_all(input);
|
||||
}
|
||||
|
||||
fn post_exec<E, EM, OT, OF, Z>(
|
||||
pub fn inner_mut(
|
||||
&mut self,
|
||||
input: &E::Input,
|
||||
observers: &mut OT,
|
||||
exit_kind: &mut ExitKind,
|
||||
) where
|
||||
E: Executor<EM, Z, State = S> + HasObservers,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OT: ObserversTuple<S>,
|
||||
OF: Feedback<S>,
|
||||
Z: HasObjective<Objective = OF, State = S>,
|
||||
{
|
||||
self.emulator.post_exec_all(input, observers, exit_kind);
|
||||
) -> &mut StatefulInProcessExecutor<'a, H, OT, S, Emulator<CM, EH, ET, S>> {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,7 +209,7 @@ where
|
||||
CM: CommandManager<EH, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
H: FnMut(&mut Emulator<CM, EH, ET, S>, &S::Input) -> ExitKind,
|
||||
S: Unpin + State + HasExecutions + HasCorpus + HasSolutions,
|
||||
OT: ObserversTuple<S>,
|
||||
OF: Feedback<S>,
|
||||
@ -309,13 +223,18 @@ where
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
self.state.pre_exec::<Self, EM, OF, Z>(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, EM, OT, OF, Z>(
|
||||
|
||||
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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
H: FnMut(&mut Emulator<CM, EH, ET, S>, &S::Input) -> ExitKind,
|
||||
OT: ObserversTuple<S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
H: FnMut(&mut Emulator<CM, EH, ET, S>, &S::Input) -> ExitKind,
|
||||
OT: ObserversTuple<S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
H: FnMut(&mut Emulator<CM, EH, ET, S>, &S::Input) -> ExitKind,
|
||||
S: Unpin + State + HasExecutions,
|
||||
OT: ObserversTuple<S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
@ -378,7 +297,7 @@ where
|
||||
Z: UsesState<State = S>,
|
||||
{
|
||||
inner: InProcessForkExecutor<'a, H, OT, S, SP, EM, Z>,
|
||||
state: QemuExecutorState<'a, CM, EH, ET, S>,
|
||||
emulator: Emulator<CM, EH, ET, S>,
|
||||
}
|
||||
|
||||
#[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<Objective = OF, State = S>,
|
||||
{
|
||||
pub fn new(
|
||||
emulator: &'a mut Emulator<CM, EH, ET, S>,
|
||||
emulator: Emulator<CM, EH, ET, S>,
|
||||
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<CM, EH, ET, S> {
|
||||
self.state.emulator
|
||||
&self.emulator
|
||||
}
|
||||
|
||||
pub fn emulator_mut(&mut self) -> &Emulator<CM, EH, ET, S> {
|
||||
&mut self.emulator
|
||||
}
|
||||
}
|
||||
|
@ -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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind,
|
||||
S: Unpin + State + HasExecutions,
|
||||
OT: ObserversTuple<S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
{
|
||||
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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind,
|
||||
S: Unpin + State + HasExecutions,
|
||||
OT: ObserversTuple<S> + Debug,
|
||||
ET: EmulatorModuleTuple<S> + 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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind,
|
||||
S: Unpin + State + HasExecutions,
|
||||
OT: ObserversTuple<S>,
|
||||
ET: EmulatorModuleTuple<S> + Debug,
|
||||
{
|
||||
pub fn new<EM, OF, Z>(
|
||||
emulator: &'a mut Emulator<CM, EH, ET, S>,
|
||||
harness_fn: &'a mut H,
|
||||
observers: OT,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut S,
|
||||
event_mgr: &mut EM,
|
||||
timeout: Duration,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
OF: Feedback<S>,
|
||||
S: Unpin + State + HasExecutions + HasCorpus + HasSolutions,
|
||||
Z: HasObjective<Objective = OF, State = S> + 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<EM, Z>
|
||||
for StatefulQemuExecutor<'a, CM, EH, H, OT, ET, S>
|
||||
where
|
||||
CM: CommandManager<EH, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
EM: EventFirer<State = S> + EventRestarter<State = S>,
|
||||
H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind,
|
||||
S: Unpin + State + HasExecutions + HasCorpus + HasSolutions,
|
||||
OT: ObserversTuple<S>,
|
||||
OF: Feedback<S>,
|
||||
ET: EmulatorModuleTuple<S> + Debug,
|
||||
Z: HasObjective<Objective = OF, State = S>,
|
||||
{
|
||||
fn run_target(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
state: &mut Self::State,
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
self.inner
|
||||
.exposed_executor_state_mut()
|
||||
.pre_exec::<Self, EM, OF, Z>(input);
|
||||
let mut exit_kind = self.inner.run_target(fuzzer, state, mgr, input)?;
|
||||
self.inner
|
||||
.exposed_executor_state
|
||||
.post_exec::<Self, EM, OT, OF, Z>(
|
||||
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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind,
|
||||
OT: ObserversTuple<S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind,
|
||||
OT: ObserversTuple<S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
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, ET, S>,
|
||||
EH: EmulatorExitHandler<ET, S>,
|
||||
H: FnMut(&S::Input, &mut QemuExecutorState<'a, CM, EH, ET, S>) -> ExitKind,
|
||||
S: Unpin + State + HasExecutions,
|
||||
OT: ObserversTuple<S>,
|
||||
ET: EmulatorModuleTuple<S>,
|
||||
{
|
||||
#[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()
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user