diff --git a/fuzzers/binary_only/qemu_launcher/src/fuzzer.rs b/fuzzers/binary_only/qemu_launcher/src/fuzzer.rs index ac25c2102b..45cbff3c70 100644 --- a/fuzzers/binary_only/qemu_launcher/src/fuzzer.rs +++ b/fuzzers/binary_only/qemu_launcher/src/fuzzer.rs @@ -6,18 +6,19 @@ use std::{ use clap::Parser; #[cfg(feature = "simplemgr")] -use libafl::events::{ClientDescription, SimpleEventManager}; +use libafl::events::SimpleEventManager; #[cfg(not(feature = "simplemgr"))] use libafl::events::{EventConfig, Launcher, MonitorTypedEventManager}; use libafl::{ + events::{ClientDescription, LlmpEventManagerBuilder}, monitors::{tui::TuiMonitor, Monitor, MultiMonitor}, Error, }; -#[cfg(feature = "simplemgr")] -use libafl_bolts::core_affinity::CoreId; -use libafl_bolts::current_time; #[cfg(not(feature = "simplemgr"))] use libafl_bolts::shmem::{ShMemProvider, StdShMemProvider}; +use libafl_bolts::{core_affinity::CoreId, current_time}; +#[cfg(not(feature = "simplemgr"))] +use libafl_bolts::{llmp::LlmpBroker, staterestore::StateRestorer, tuples::tuple_list}; #[cfg(unix)] use { nix::unistd::dup, @@ -83,7 +84,7 @@ impl Fuzzer { { // The shared memory allocator #[cfg(not(feature = "simplemgr"))] - let shmem_provider = StdShMemProvider::new()?; + let mut shmem_provider = StdShMemProvider::new()?; /* If we are running in verbose, don't provide a replacement stdout, otherwise, use /dev/null */ #[cfg(not(feature = "simplemgr"))] let stdout = if self.options.verbose { @@ -94,12 +95,43 @@ impl Fuzzer { let client = Client::new(&self.options); + #[cfg(not(feature = "simplemgr"))] + if self.options.rerun_input.is_some() { + // If we want to rerun a single input but we use a restarting mgr, we'll have to create a fake restarting mgr that doesn't actually restart. + // It's not pretty but better than recompiling with simplemgr. + + // Just a random number, let's hope it's free :) + let broker_port = 13120; + let _fake_broker = LlmpBroker::create_attach_to_tcp( + shmem_provider.clone(), + tuple_list!(), + broker_port, + ) + .unwrap(); + + // To rerun an input, instead of using a launcher, we create dummy parameters and run the client directly. + // NOTE: This is a hack for debugging that that will only work for non-crashing inputs. + return client.run( + None, + MonitorTypedEventManager::<_, M>::new( + LlmpEventManagerBuilder::builder() + .build_on_port( + shmem_provider.clone(), + broker_port, + EventConfig::AlwaysUnique, + None, + Some(StateRestorer::new( + shmem_provider.new_shmem(0x1000).unwrap(), + )), + ) + .unwrap(), + ), + ClientDescription::new(0, 0, CoreId(0)), + ); + } + #[cfg(feature = "simplemgr")] if self.options.rerun_input.is_some() { - // only for simplemgr - // DON'T USE LLMP HERE!! - // it doesn't work like that - return client.run( None, SimpleEventManager::new(monitor), diff --git a/fuzzers/binary_only/qemu_launcher/src/instance.rs b/fuzzers/binary_only/qemu_launcher/src/instance.rs index 245afc3b91..5d7981dc3b 100644 --- a/fuzzers/binary_only/qemu_launcher/src/instance.rs +++ b/fuzzers/binary_only/qemu_launcher/src/instance.rs @@ -378,15 +378,15 @@ impl Instance<'_, M> { executor: &mut QemuExecutor<'a, C, CM, ED, EM, (SnapshotModule, ET), H, I, OT, S, SM, Z>, qemu: Qemu, ) where - I: Input + Unpin, ET: EmulatorModuleTuple, - S: HasCorpus + HasCurrentCorpusId + HasSolutions + HasExecutions + Unpin, H: for<'e, 's, 'i> FnMut( &'e mut Emulator, &'s mut S, &'i I, ) -> ExitKind, + I: Input + Unpin, OT: ObserversTuple, + S: HasCorpus + HasCurrentCorpusId + HasSolutions + HasExecutions + Unpin, { executor .inner_mut() @@ -406,15 +406,15 @@ impl Instance<'_, M> { >, qemu: Qemu, ) where - I: Input + Unpin, ET: EmulatorModuleTuple, - S: HasCorpus + HasCurrentCorpusId + HasSolutions + HasExecutions + Unpin, H: for<'e, 's, 'i> FnMut( &'e mut Emulator, &'s mut S, &'i I, ) -> ExitKind, + I: Input + Unpin, OT: ObserversTuple, + S: HasCorpus + HasCurrentCorpusId + HasSolutions + HasExecutions + Unpin, SOT: ObserversTuple, { executor @@ -427,7 +427,7 @@ impl Instance<'_, M> { .reset(qemu); } - fn fuzz( + fn fuzz( &mut self, state: &mut ClientState, fuzzer: &mut Z, @@ -437,10 +437,10 @@ impl Instance<'_, M> { stages: &mut ST, ) -> Result<(), Error> where - Z: Fuzzer, BytesInput, ClientState, ST> - + Evaluator, BytesInput, ClientState>, ST: StagesTuple, ClientState, Z>, RSM: Fn(&mut E, Qemu), + Z: Fuzzer, BytesInput, ClientState, ST> + + Evaluator, BytesInput, ClientState>, { if state.must_load_initial_inputs() { let corpus_dirs = [self.options.input_dir()];