From 226a20e6cf5e3110c0b79002c8d567c7ab7a4756 Mon Sep 17 00:00:00 2001 From: "Dongjia \"toka\" Zhang" Date: Tue, 11 Mar 2025 14:37:19 +0100 Subject: [PATCH] Fix usage of TracingStage (#3062) * real fix * more * debug * fix * fixer * mmmm * mm * mm * mm * fix * fix atheris * ? --- .../frida_executable_libpng/src/fuzzer.rs | 2 +- .../binary_only/frida_libpng/src/fuzzer.rs | 2 +- .../frida_windows_gdiplus/src/fuzzer.rs | 2 +- .../fuzzbench_fork_qemu/src/fuzzer.rs | 2 +- .../binary_only/fuzzbench_qemu/src/fuzzer.rs | 2 +- .../binary_only/qemu_launcher/src/instance.rs | 2 +- .../full_system/nyx_launcher/src/instance.rs | 2 +- .../qemu_linux_kernel/src/fuzzer.rs | 2 +- .../qemu_linux_process/src/fuzzer.rs | 2 +- .../fuzz_anything/libafl_atheris/src/lib.rs | 13 +- fuzzers/inprocess/fuzzbench/src/lib.rs | 20 +-- fuzzers/inprocess/fuzzbench_ctx/src/lib.rs | 29 +--- fuzzers/inprocess/fuzzbench_text/src/lib.rs | 30 +--- .../inprocess/libfuzzer_stb_image/src/main.rs | 2 +- .../fuzzer/src/main.rs | 2 +- libafl/src/stages/mod.rs | 5 +- libafl/src/stages/shadow.rs | 139 ++++++++++++++++++ libafl/src/stages/tracing.rs | 108 +------------- libafl_libfuzzer/runtime/src/lib.rs | 15 +- libafl_sugar/src/inmemory.rs | 2 +- libafl_sugar/src/qemu.rs | 2 +- 21 files changed, 186 insertions(+), 199 deletions(-) create mode 100644 libafl/src/stages/shadow.rs diff --git a/fuzzers/binary_only/frida_executable_libpng/src/fuzzer.rs b/fuzzers/binary_only/frida_executable_libpng/src/fuzzer.rs index 44d28b3b42..53c6d64c7a 100644 --- a/fuzzers/binary_only/frida_executable_libpng/src/fuzzer.rs +++ b/fuzzers/binary_only/frida_executable_libpng/src/fuzzer.rs @@ -370,7 +370,7 @@ unsafe fn fuzz( let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); - let tracing = ShadowTracingStage::new(&mut executor); + let tracing = ShadowTracingStage::new(); // Setup a randomic Input2State stage let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!( diff --git a/fuzzers/binary_only/frida_libpng/src/fuzzer.rs b/fuzzers/binary_only/frida_libpng/src/fuzzer.rs index 6ea6f9cd33..b6165fe75c 100644 --- a/fuzzers/binary_only/frida_libpng/src/fuzzer.rs +++ b/fuzzers/binary_only/frida_libpng/src/fuzzer.rs @@ -218,7 +218,7 @@ fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); - let tracing = ShadowTracingStage::new(&mut executor); + let tracing = ShadowTracingStage::new(); // Setup a randomic Input2State stage let i2s = diff --git a/fuzzers/binary_only/frida_windows_gdiplus/src/fuzzer.rs b/fuzzers/binary_only/frida_windows_gdiplus/src/fuzzer.rs index 4739b88827..b88c2004c8 100644 --- a/fuzzers/binary_only/frida_windows_gdiplus/src/fuzzer.rs +++ b/fuzzers/binary_only/frida_windows_gdiplus/src/fuzzer.rs @@ -344,7 +344,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> { let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); - let tracing = ShadowTracingStage::new(&mut executor); + let tracing = ShadowTracingStage::new(); // Setup a randomic Input2State stage let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!( diff --git a/fuzzers/binary_only/fuzzbench_fork_qemu/src/fuzzer.rs b/fuzzers/binary_only/fuzzbench_fork_qemu/src/fuzzer.rs index cd82d72b0d..c98e3259cd 100644 --- a/fuzzers/binary_only/fuzzbench_fork_qemu/src/fuzzer.rs +++ b/fuzzers/binary_only/fuzzbench_fork_qemu/src/fuzzer.rs @@ -391,7 +391,7 @@ fn fuzz( println!("We imported {} inputs from disk.", state.corpus().count()); } - let tracing = ShadowTracingStage::new(&mut executor); + let tracing = ShadowTracingStage::new(); // The order of the stages matter! let mut stages = tuple_list!(calibration, tracing, i2s, power); diff --git a/fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs b/fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs index f3a29a2765..d4b7acb74f 100644 --- a/fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs +++ b/fuzzers/binary_only/fuzzbench_qemu/src/fuzzer.rs @@ -403,7 +403,7 @@ fn fuzz( println!("We imported {} input(s) from disk.", state.corpus().count()); } - let tracing = ShadowTracingStage::new(&mut executor); + let tracing = ShadowTracingStage::new(); // The order of the stages matter! let mut stages = tuple_list!(calibration, tracing, i2s, power); diff --git a/fuzzers/binary_only/qemu_launcher/src/instance.rs b/fuzzers/binary_only/qemu_launcher/src/instance.rs index 6ec9d28ad5..0409eb3d7d 100644 --- a/fuzzers/binary_only/qemu_launcher/src/instance.rs +++ b/fuzzers/binary_only/qemu_launcher/src/instance.rs @@ -316,7 +316,7 @@ impl Instance<'_, M> { let mut shadow_executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); - let tracing = ShadowTracingStage::new(&mut shadow_executor); + let tracing = ShadowTracingStage::new(); // Setup a randomic Input2State stage let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!( diff --git a/fuzzers/full_system/nyx_launcher/src/instance.rs b/fuzzers/full_system/nyx_launcher/src/instance.rs index 568297844b..a2d1fcd055 100644 --- a/fuzzers/full_system/nyx_launcher/src/instance.rs +++ b/fuzzers/full_system/nyx_launcher/src/instance.rs @@ -192,7 +192,7 @@ impl Instance<'_, M> { I2SRandReplace::new() ))); - let tracing = ShadowTracingStage::new(&mut executor); + let tracing = ShadowTracingStage::new(); // Setup a MOPT mutator let mutator = StdMOptMutator::new( diff --git a/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs b/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs index 704346da90..9e07067ddf 100644 --- a/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs +++ b/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs @@ -232,7 +232,7 @@ pub fn fuzz() { ))); // Setup an havoc mutator with a mutational stage - let tracing = ShadowTracingStage::new(&mut executor); + let tracing = ShadowTracingStage::new(); let mutator = StdScheduledMutator::new(havoc_mutations()); let mut stages = tuple_list!(tracing, i2s, StdMutationalStage::new(mutator),); diff --git a/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs b/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs index badb02d59c..0e4626782e 100644 --- a/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs +++ b/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs @@ -240,7 +240,7 @@ pub fn fuzz() { ))); // Setup an havoc mutator with a mutational stage - let tracing = ShadowTracingStage::new(&mut executor); + let tracing = ShadowTracingStage::new(); let mutator = StdScheduledMutator::new(havoc_mutations()); let mut stages = tuple_list!(tracing, i2s, StdMutationalStage::new(mutator),); diff --git a/fuzzers/fuzz_anything/libafl_atheris/src/lib.rs b/fuzzers/fuzz_anything/libafl_atheris/src/lib.rs index 0d00e2778e..f8b000ddd2 100644 --- a/fuzzers/fuzz_anything/libafl_atheris/src/lib.rs +++ b/fuzzers/fuzz_anything/libafl_atheris/src/lib.rs @@ -14,7 +14,7 @@ use clap::{Arg, ArgAction, Command}; use libafl::{ corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, - executors::{inprocess::InProcessExecutor, ExitKind}, + executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor}, feedback_or, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, @@ -28,7 +28,7 @@ use libafl::{ }, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, - stages::{StdMutationalStage, TracingStage}, + stages::{ShadowTracingStage, StdMutationalStage, TracingStage}, state::{HasCorpus, StdState}, Error, HasMetadata, }; @@ -216,14 +216,9 @@ pub extern "C" fn LLVMFuzzerRunDriver( ExitKind::Ok }; + let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); // Setup a tracing stage in which we log comparisons - let tracing = TracingStage::new(InProcessExecutor::new( - &mut harness, - tuple_list!(cmplog_observer), - &mut fuzzer, - &mut state, - &mut mgr, - )?); + let tracing = ShadowTracingStage::new(); // Setup a randomic Input2State stage let i2s = diff --git a/fuzzers/inprocess/fuzzbench/src/lib.rs b/fuzzers/inprocess/fuzzbench/src/lib.rs index f95e933d81..49f94465b8 100644 --- a/fuzzers/inprocess/fuzzbench/src/lib.rs +++ b/fuzzers/inprocess/fuzzbench/src/lib.rs @@ -19,7 +19,7 @@ use libafl::{ Error, HasMetadata, corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus}, events::SimpleRestartingEventManager, - executors::{ExitKind, inprocess::InProcessExecutor}, + executors::{ExitKind, ShadowExecutor, inprocess::InProcessExecutor}, feedback_or, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, fuzzer::{Fuzzer, StdFuzzer}, @@ -34,7 +34,7 @@ use libafl::{ IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, powersched::PowerSchedule, }, stages::{ - StdMutationalStage, TracingStage, calibrate::CalibrationStage, + ShadowTracingStage, StdMutationalStage, calibrate::CalibrationStage, power::StdPowerMutationalStage, }, state::{HasCorpus, StdState}, @@ -331,8 +331,6 @@ fn fuzz( ExitKind::Ok }; - let mut tracing_harness = harness; - // Create the executor for an in-process function with one observer for edge coverage and one for the execution time let mut executor = InProcessExecutor::with_timeout( &mut harness, @@ -343,18 +341,10 @@ fn fuzz( timeout, )?; + let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); + // Setup a tracing stage in which we log comparisons - let tracing = TracingStage::new( - InProcessExecutor::with_timeout( - &mut tracing_harness, - tuple_list!(cmplog_observer), - &mut fuzzer, - &mut state, - &mut mgr, - timeout * 10, - )?, - // Give it more time! - ); + let tracing = ShadowTracingStage::new(); // The order of the stages matter! let mut stages = tuple_list!(calibration, tracing, i2s, power); diff --git a/fuzzers/inprocess/fuzzbench_ctx/src/lib.rs b/fuzzers/inprocess/fuzzbench_ctx/src/lib.rs index 02c5f0e339..bb9b961bfd 100644 --- a/fuzzers/inprocess/fuzzbench_ctx/src/lib.rs +++ b/fuzzers/inprocess/fuzzbench_ctx/src/lib.rs @@ -18,10 +18,7 @@ use clap::{Arg, Command}; use libafl::{ corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus}, events::SimpleRestartingEventManager, - executors::{ - inprocess::{HookableInProcessExecutor, InProcessExecutor}, - ExitKind, - }, + executors::{inprocess::HookableInProcessExecutor, ExitKind, ShadowExecutor}, feedback_or, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, fuzzer::{Fuzzer, StdFuzzer}, @@ -36,8 +33,8 @@ use libafl::{ powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, }, stages::{ - calibrate::CalibrationStage, power::StdPowerMutationalStage, StdMutationalStage, - TracingStage, + calibrate::CalibrationStage, power::StdPowerMutationalStage, ShadowTracingStage, + StdMutationalStage, }, state::{HasCorpus, StdState}, Error, HasMetadata, @@ -343,24 +340,10 @@ fn fuzz( ExitKind::Ok }; - let mut tracing_harness = harness; let ctx_hook = CtxHook::new(); - // Setup a tracing stage in which we log comparisons - let tracing = TracingStage::new( - InProcessExecutor::with_timeout( - &mut tracing_harness, - tuple_list!(cmplog_observer), - &mut fuzzer, - &mut state, - &mut mgr, - timeout * 10, - )?, - // Give it more time! - ); - // Create the executor for an in-process function with one observer for edge coverage and one for the execution time - let mut executor = HookableInProcessExecutor::with_timeout_generic( + let executor = HookableInProcessExecutor::with_timeout_generic( tuple_list!(ctx_hook), &mut harness, tuple_list!(edges_observer, time_observer), @@ -370,6 +353,10 @@ fn fuzz( timeout, )?; + let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); + // Setup a tracing stage in which we log comparisons + let tracing = ShadowTracingStage::new(); + // The order of the stages matter! let mut stages = tuple_list!(calibration, tracing, i2s, power); diff --git a/fuzzers/inprocess/fuzzbench_text/src/lib.rs b/fuzzers/inprocess/fuzzbench_text/src/lib.rs index 82dd8400da..afbe5a6d87 100644 --- a/fuzzers/inprocess/fuzzbench_text/src/lib.rs +++ b/fuzzers/inprocess/fuzzbench_text/src/lib.rs @@ -19,7 +19,7 @@ use content_inspector::inspect; use libafl::{ corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus}, events::SimpleRestartingEventManager, - executors::{inprocess::InProcessExecutor, ExitKind}, + executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor}, feedback_or, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, fuzzer::{Fuzzer, StdFuzzer}, @@ -40,7 +40,7 @@ use libafl::{ }, stages::{ calibrate::CalibrationStage, power::StdPowerMutationalStage, GeneralizationStage, - StdMutationalStage, TracingStage, + ShadowTracingStage, StdMutationalStage, }, state::{HasCorpus, StdState}, Error, HasMetadata, @@ -400,8 +400,6 @@ fn fuzz_binary( ExitKind::Ok }; - let mut tracing_harness = harness; - // Create the executor for an in-process function with one observer for edge coverage and one for the execution time let mut executor = InProcessExecutor::with_timeout( &mut harness, @@ -413,14 +411,9 @@ fn fuzz_binary( )?; // Setup a tracing stage in which we log comparisons - let tracing = TracingStage::new(InProcessExecutor::with_timeout( - &mut tracing_harness, - tuple_list!(cmplog_observer), - &mut fuzzer, - &mut state, - &mut mgr, - timeout * 10, - )?); + let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); + + let tracing = ShadowTracingStage::new(); // The order of the stages matter! let mut stages = tuple_list!(calibration, tracing, i2s, power); @@ -632,8 +625,6 @@ fn fuzz_text( ExitKind::Ok }; - let mut tracing_harness = harness; - let generalization = GeneralizationStage::new(&edges_observer); // Create the executor for an in-process function with one observer for edge coverage and one for the execution time @@ -646,15 +637,8 @@ fn fuzz_text( timeout, )?; // Setup a tracing stage in which we log comparisons - let tracing = TracingStage::new(InProcessExecutor::with_timeout( - &mut tracing_harness, - tuple_list!(cmplog_observer), - &mut fuzzer, - &mut state, - &mut mgr, - // Give it more time! - timeout * 10, - )?); + let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); + let tracing = ShadowTracingStage::new(); // The order of the stages matter! let mut stages = tuple_list!(generalization, calibration, tracing, i2s, power, grimoire); diff --git a/fuzzers/inprocess/libfuzzer_stb_image/src/main.rs b/fuzzers/inprocess/libfuzzer_stb_image/src/main.rs index 77e7e06f1d..a6c938b8ed 100644 --- a/fuzzers/inprocess/libfuzzer_stb_image/src/main.rs +++ b/fuzzers/inprocess/libfuzzer_stb_image/src/main.rs @@ -152,7 +152,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re } // Setup a tracing stage in which we log comparisons - let tracing = ShadowTracingStage::new(&mut executor); + let tracing = ShadowTracingStage::new(); // Setup a randomic Input2State stage let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); diff --git a/fuzzers/structure_aware/libfuzzer_stb_image_concolic/fuzzer/src/main.rs b/fuzzers/structure_aware/libfuzzer_stb_image_concolic/fuzzer/src/main.rs index f7703e40a9..71cd19251b 100644 --- a/fuzzers/structure_aware/libfuzzer_stb_image_concolic/fuzzer/src/main.rs +++ b/fuzzers/structure_aware/libfuzzer_stb_image_concolic/fuzzer/src/main.rs @@ -190,7 +190,7 @@ fn fuzz( } // Setup a tracing stage in which we log comparisons - let tracing = ShadowTracingStage::new(&mut executor); + let tracing = ShadowTracingStage::new(); // Setup a randomic Input2State stage let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); diff --git a/libafl/src/stages/mod.rs b/libafl/src/stages/mod.rs index 77320e898a..dbddebc8d5 100644 --- a/libafl/src/stages/mod.rs +++ b/libafl/src/stages/mod.rs @@ -37,7 +37,7 @@ pub use sync::*; #[cfg(feature = "std")] pub use time_tracker::TimeTrackingStageWrapper; pub use tmin::{ObserverEqualityFactory, ObserverEqualityFeedback, StdTMinMutationalStage}; -pub use tracing::{ShadowTracingStage, TracingStage}; +pub use tracing::TracingStage; pub use tuneable::*; use tuple_list::NonEmptyTuple; #[cfg(feature = "unicode")] @@ -57,6 +57,9 @@ pub mod mutational; pub mod push; pub mod tmin; +pub mod shadow; +pub use shadow::*; + pub mod replay; pub use replay::*; diff --git a/libafl/src/stages/shadow.rs b/libafl/src/stages/shadow.rs new file mode 100644 index 0000000000..07641258a5 --- /dev/null +++ b/libafl/src/stages/shadow.rs @@ -0,0 +1,139 @@ +//! A stage that runs the shadow executor using also the shadow observers. Unlike tracing stage, this +//! stage *CAN* be used with inprocess executor. + +use alloc::{ + borrow::{Cow, ToOwned}, + string::ToString, +}; +use core::{fmt::Debug, marker::PhantomData}; + +use libafl_bolts::Named; + +#[cfg(feature = "introspection")] +use crate::monitors::stats::PerfFeature; +use crate::{ + Error, HasNamedMetadata, + corpus::HasCurrentCorpusId, + executors::{Executor, HasObservers, ShadowExecutor}, + mark_feature_time, + observers::ObserversTuple, + stages::{Restartable, RetryCountRestartHelper, Stage}, + start_timer, + state::{HasCorpus, HasCurrentTestcase, HasExecutions, MaybeHasClientPerfMonitor}, +}; + +/// A stage that runs the shadow executor using also the shadow observers +#[derive(Clone, Debug)] +pub struct ShadowTracingStage { + name: Cow<'static, str>, + phantom: PhantomData<(E, EM, I, SOT, S, Z)>, +} + +impl Default for ShadowTracingStage +where + E: Executor + HasObservers, + S: HasExecutions + HasCorpus, + SOT: ObserversTuple, +{ + fn default() -> Self { + Self::new() + } +} + +/// The counter for giving this stage unique id +static mut SHADOW_TRACING_STAGE_ID: usize = 0; +/// Name for shadow tracing stage +pub static SHADOW_TRACING_STAGE_NAME: &str = "shadow"; + +impl Named for ShadowTracingStage { + fn name(&self) -> &Cow<'static, str> { + &self.name + } +} + +impl Stage, EM, S, Z> + for ShadowTracingStage +where + E: Executor + HasObservers, + E::Observers: ObserversTuple, + SOT: ObserversTuple, + S: HasExecutions + + HasCorpus + + HasNamedMetadata + + Debug + + HasCurrentTestcase + + HasCurrentCorpusId + + MaybeHasClientPerfMonitor, +{ + #[inline] + fn perform( + &mut self, + fuzzer: &mut Z, + executor: &mut ShadowExecutor, + state: &mut S, + manager: &mut EM, + ) -> Result<(), Error> { + start_timer!(state); + let input = state.current_input_cloned()?; + + mark_feature_time!(state, PerfFeature::GetInputFromCorpus); + + start_timer!(state); + executor + .shadow_observers_mut() + .pre_exec_all(state, &input)?; + executor.observers_mut().pre_exec_all(state, &input)?; + mark_feature_time!(state, PerfFeature::PreExecObservers); + + start_timer!(state); + let exit_kind = executor.run_target(fuzzer, state, manager, &input)?; + mark_feature_time!(state, PerfFeature::TargetExecution); + + start_timer!(state); + executor + .shadow_observers_mut() + .post_exec_all(state, &input, &exit_kind)?; + executor + .observers_mut() + .post_exec_all(state, &input, &exit_kind)?; + mark_feature_time!(state, PerfFeature::PostExecObservers); + + Ok(()) + } +} + +impl Restartable for ShadowTracingStage +where + S: HasNamedMetadata + HasCurrentCorpusId, +{ + fn should_restart(&mut self, state: &mut S) -> Result { + RetryCountRestartHelper::no_retry(state, &self.name) + } + + fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> { + RetryCountRestartHelper::clear_progress(state, &self.name) + } +} + +impl ShadowTracingStage +where + E: Executor + HasObservers, + S: HasExecutions + HasCorpus, + SOT: ObserversTuple, +{ + /// Creates a new default stage + pub fn new() -> Self { + // unsafe but impossible that you create two threads both instantiating this instance + let stage_id = unsafe { + let ret = SHADOW_TRACING_STAGE_ID; + SHADOW_TRACING_STAGE_ID += 1; + ret + }; + Self { + name: Cow::Owned( + SHADOW_TRACING_STAGE_NAME.to_owned() + ":" + stage_id.to_string().as_str(), + ), + phantom: PhantomData, + } + } +} diff --git a/libafl/src/stages/tracing.rs b/libafl/src/stages/tracing.rs index 457b69c0dc..ca199e09cb 100644 --- a/libafl/src/stages/tracing.rs +++ b/libafl/src/stages/tracing.rs @@ -13,7 +13,7 @@ use crate::monitors::stats::PerfFeature; use crate::{ Error, HasNamedMetadata, corpus::HasCurrentCorpusId, - executors::{Executor, HasObservers, ShadowExecutor}, + executors::{Executor, HasObservers}, inputs::Input, mark_feature_time, observers::ObserversTuple, @@ -23,6 +23,7 @@ use crate::{ }; /// A stage that runs a tracer executor +/// This should *NOT* be used with inprocess executor #[derive(Clone, Debug)] pub struct TracingStage { name: Cow<'static, str>, @@ -146,108 +147,3 @@ impl TracingStage { &mut self.tracer_executor } } - -/// A stage that runs the shadow executor using also the shadow observers -#[derive(Clone, Debug)] -pub struct ShadowTracingStage { - name: Cow<'static, str>, - phantom: PhantomData<(E, EM, I, SOT, S, Z)>, -} - -/// The counter for giving this stage unique id -static mut SHADOW_TRACING_STAGE_ID: usize = 0; -/// Name for shadow tracing stage -pub static SHADOW_TRACING_STAGE_NAME: &str = "shadow"; - -impl Named for ShadowTracingStage { - fn name(&self) -> &Cow<'static, str> { - &self.name - } -} - -impl Stage, EM, S, Z> - for ShadowTracingStage -where - E: Executor + HasObservers, - E::Observers: ObserversTuple, - SOT: ObserversTuple, - S: HasExecutions - + HasCorpus - + HasNamedMetadata - + Debug - + HasCurrentTestcase - + HasCurrentCorpusId - + MaybeHasClientPerfMonitor, -{ - #[inline] - fn perform( - &mut self, - fuzzer: &mut Z, - executor: &mut ShadowExecutor, - state: &mut S, - manager: &mut EM, - ) -> Result<(), Error> { - start_timer!(state); - let input = state.current_input_cloned()?; - - mark_feature_time!(state, PerfFeature::GetInputFromCorpus); - - start_timer!(state); - executor - .shadow_observers_mut() - .pre_exec_all(state, &input)?; - executor.observers_mut().pre_exec_all(state, &input)?; - mark_feature_time!(state, PerfFeature::PreExecObservers); - - start_timer!(state); - let exit_kind = executor.run_target(fuzzer, state, manager, &input)?; - mark_feature_time!(state, PerfFeature::TargetExecution); - - start_timer!(state); - executor - .shadow_observers_mut() - .post_exec_all(state, &input, &exit_kind)?; - executor - .observers_mut() - .post_exec_all(state, &input, &exit_kind)?; - mark_feature_time!(state, PerfFeature::PostExecObservers); - - Ok(()) - } -} - -impl Restartable for ShadowTracingStage -where - S: HasNamedMetadata + HasCurrentCorpusId, -{ - fn should_restart(&mut self, state: &mut S) -> Result { - RetryCountRestartHelper::no_retry(state, &self.name) - } - - fn clear_progress(&mut self, state: &mut S) -> Result<(), Error> { - RetryCountRestartHelper::clear_progress(state, &self.name) - } -} - -impl ShadowTracingStage -where - E: Executor + HasObservers, - S: HasExecutions + HasCorpus, - SOT: ObserversTuple, -{ - /// Creates a new default stage - pub fn new(_executor: &mut ShadowExecutor) -> Self { - // unsafe but impossible that you create two threads both instantiating this instance - let stage_id = unsafe { - let ret = SHADOW_TRACING_STAGE_ID; - SHADOW_TRACING_STAGE_ID += 1; - ret - }; - Self { - name: Cow::Owned( - SHADOW_TRACING_STAGE_NAME.to_owned() + ":" + stage_id.to_string().as_str(), - ), - phantom: PhantomData, - } - } -} diff --git a/libafl_libfuzzer/runtime/src/lib.rs b/libafl_libfuzzer/runtime/src/lib.rs index ce54468dac..da826008ae 100644 --- a/libafl_libfuzzer/runtime/src/lib.rs +++ b/libafl_libfuzzer/runtime/src/lib.rs @@ -148,7 +148,7 @@ macro_rules! fuzz_with { }; use libafl::{ corpus::Corpus, - executors::{ExitKind, InProcessExecutor}, + executors::{ExitKind, InProcessExecutor, ShadowExecutor}, feedback_and_fast, feedback_not, feedback_or, feedback_or_fast, feedbacks::{ConstFeedback, CrashFeedback, MaxMapFeedback, NewHashFeedback, TimeFeedback, TimeoutFeedback}, generators::RandBytesGenerator, @@ -166,7 +166,7 @@ macro_rules! fuzz_with { }, stages::{ CalibrationStage, GeneralizationStage, IfStage, StdMutationalStage, - StdPowerMutationalStage, UnicodeIdentificationStage, TracingStage, + StdPowerMutationalStage, UnicodeIdentificationStage, ShadowTracingStage, }, state::{HasCorpus, StdState}, StdFuzzer, @@ -438,8 +438,6 @@ macro_rules! fuzz_with { } }; - let mut tracing_harness = harness; - let add_extra_observer = $extra_obsv; let observers = add_extra_observer( tuple_list!(edges_observer, size_edges_observer, time_observer, backtrace_observer, oom_observer), @@ -488,14 +486,9 @@ macro_rules! fuzz_with { } } + let mut executor = ShadowExecutor::new(executor, tuple_list!(cmplog_observer)); // Setup a tracing stage in which we log comparisons - let tracing = IfStage::new(|_, _, _, _| Ok(!$options.skip_tracing()), (TracingStage::new(InProcessExecutor::new( - &mut tracing_harness, - tuple_list!(cmplog_observer), - &mut fuzzer, - &mut state, - &mut mgr, - )?), ())); + let tracing = IfStage::new(|_, _, _, _| Ok(!$options.skip_tracing()), (ShadowTracingStage::new(), ())); // The order of the stages matter! let mut stages = tuple_list!( diff --git a/libafl_sugar/src/inmemory.rs b/libafl_sugar/src/inmemory.rs index 42ff0900fa..d16800eb61 100644 --- a/libafl_sugar/src/inmemory.rs +++ b/libafl_sugar/src/inmemory.rs @@ -261,7 +261,7 @@ where } // Setup a tracing stage in which we log comparisons - let tracing = ShadowTracingStage::new(&mut executor); + let tracing = ShadowTracingStage::new(); // Setup a randomic Input2State stage let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!( diff --git a/libafl_sugar/src/qemu.rs b/libafl_sugar/src/qemu.rs index 19295e0ffc..ac94749698 100644 --- a/libafl_sugar/src/qemu.rs +++ b/libafl_sugar/src/qemu.rs @@ -299,7 +299,7 @@ where } // Setup a tracing stage in which we log comparisons - let tracing = ShadowTracingStage::new(&mut executor); + let tracing = ShadowTracingStage::new(); // Setup a randomic Input2State stage let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(