diff --git a/libafl/src/events/launcher.rs b/libafl/src/events/launcher.rs index a29ef5307b..3012123953 100644 --- a/libafl/src/events/launcher.rs +++ b/libafl/src/events/launcher.rs @@ -495,6 +495,9 @@ where monitor: MT, /// The configuration configuration: EventConfig, + /// Consider this testcase as interesting always if true + #[builder(default = false)] + always_interesting: bool, /// The 'main' function to run for each client forked. This probably shouldn't return #[builder(default, setter(strip_option))] run_client: Option, @@ -684,6 +687,7 @@ where // Fuzzer client. keeps retrying the connection to broker till the broker starts let builder = RestartingMgr::<(), MT, S, SP>::builder() + .always_interesting(self.always_interesting) .shmem_provider(self.shmem_provider.clone()) .broker_port(self.broker_port) .kind(ManagerKind::Client { diff --git a/libafl/src/events/llmp/mgr.rs b/libafl/src/events/llmp/mgr.rs index 58deecd018..3dc8082082 100644 --- a/libafl/src/events/llmp/mgr.rs +++ b/libafl/src/events/llmp/mgr.rs @@ -43,7 +43,7 @@ use crate::{ ProgressReporter, }, executors::{Executor, HasObservers}, - fuzzer::{EvaluatorObservers, ExecutionProcessor}, + fuzzer::{Evaluator, EvaluatorObservers, ExecutionProcessor}, inputs::{NopInput, UsesInput}, observers::ObserversTuple, state::{HasExecutions, HasLastReportTime, NopState, State, UsesState}, @@ -59,6 +59,8 @@ where { /// We only send 1 testcase for every `throttle` second pub(crate) throttle: Option, + /// Treat the incoming testcase as interesting always without evaluating them + always_interesting: bool, /// We sent last message at `last_sent` last_sent: Duration, hooks: EMH, @@ -98,6 +100,7 @@ impl LlmpEventManager<(), NopState, NopShMemProvider> { pub struct LlmpEventManagerBuilder { throttle: Option, hooks: EMH, + always_interesting: bool, } impl Default for LlmpEventManagerBuilder<()> { @@ -113,6 +116,7 @@ impl LlmpEventManagerBuilder<()> { Self { throttle: None, hooks: (), + always_interesting: false, } } @@ -121,6 +125,17 @@ impl LlmpEventManagerBuilder<()> { LlmpEventManagerBuilder { throttle: self.throttle, hooks, + always_interesting: self.always_interesting, + } + } + + /// Set `always_interesting` + #[must_use] + pub fn always_interesting(self, always_interesting: bool) -> LlmpEventManagerBuilder<()> { + LlmpEventManagerBuilder { + throttle: self.throttle, + hooks: self.hooks, + always_interesting, } } } @@ -149,6 +164,7 @@ impl LlmpEventManagerBuilder { throttle: self.throttle, last_sent: Duration::from_secs(0), hooks: self.hooks, + always_interesting: self.always_interesting, llmp, #[cfg(feature = "llmp_compression")] compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD), @@ -178,6 +194,7 @@ impl LlmpEventManagerBuilder { throttle: self.throttle, last_sent: Duration::from_secs(0), hooks: self.hooks, + always_interesting: self.always_interesting, llmp, #[cfg(feature = "llmp_compression")] compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD), @@ -208,6 +225,7 @@ impl LlmpEventManagerBuilder { throttle: self.throttle, last_sent: Duration::from_secs(0), hooks: self.hooks, + always_interesting: self.always_interesting, llmp, #[cfg(feature = "llmp_compression")] compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD), @@ -242,6 +260,7 @@ impl LlmpEventManagerBuilder { throttle: self.throttle, last_sent: Duration::from_secs(0), hooks: self.hooks, + always_interesting: self.always_interesting, llmp, #[cfg(feature = "llmp_compression")] compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD), @@ -270,6 +289,7 @@ impl LlmpEventManagerBuilder { throttle: self.throttle, last_sent: Duration::from_secs(0), hooks: self.hooks, + always_interesting: self.always_interesting, llmp, #[cfg(feature = "llmp_compression")] compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD), @@ -302,6 +322,7 @@ impl LlmpEventManagerBuilder { throttle: self.throttle, last_sent: Duration::from_secs(0), hooks: self.hooks, + always_interesting: self.always_interesting, llmp, #[cfg(feature = "llmp_compression")] compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD), @@ -329,6 +350,7 @@ impl LlmpEventManagerBuilder { throttle: self.throttle, last_sent: Duration::from_secs(0), hooks: self.hooks, + always_interesting: self.always_interesting, llmp, #[cfg(feature = "llmp_compression")] compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD), @@ -360,6 +382,7 @@ impl LlmpEventManagerBuilder { throttle: self.throttle, last_sent: Duration::from_secs(0), hooks: self.hooks, + always_interesting: self.always_interesting, llmp, #[cfg(feature = "llmp_compression")] compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD), @@ -506,7 +529,9 @@ where where E: Executor + HasObservers, for<'a> E::Observers: Deserialize<'a>, - Z: ExecutionProcessor + EvaluatorObservers, + Z: ExecutionProcessor + + EvaluatorObservers + + Evaluator, { if !self.hooks.pre_exec_all(state, client_id, &event)? { return Ok(()); @@ -524,33 +549,40 @@ where } => { log::info!("Received new Testcase from {client_id:?} ({client_config:?}, forward {forward_id:?})"); - let res = if client_config.match_with(&self.configuration) - && observers_buf.is_some() - { - #[cfg(feature = "adaptive_serialization")] - let start = current_time(); - let observers: E::Observers = - postcard::from_bytes(observers_buf.as_ref().unwrap())?; - #[cfg(feature = "adaptive_serialization")] - { - self.deserialization_time = current_time() - start; - } - #[cfg(feature = "scalability_introspection")] - { - state.scalability_monitor_mut().testcase_with_observers += 1; - } - fuzzer.execute_and_process(state, self, input, &observers, &exit_kind, false)? - } else { - #[cfg(feature = "scalability_introspection")] - { - state.scalability_monitor_mut().testcase_without_observers += 1; - } - fuzzer.evaluate_input_with_observers::( - state, executor, self, input, false, - )? - }; - if let Some(item) = res.1 { + if self.always_interesting { + let item = fuzzer.add_input(state, executor, self, input)?; log::info!("Added received Testcase as item #{item}"); + } else { + let res = if client_config.match_with(&self.configuration) + && observers_buf.is_some() + { + #[cfg(feature = "adaptive_serialization")] + let start = current_time(); + let observers: E::Observers = + postcard::from_bytes(observers_buf.as_ref().unwrap())?; + #[cfg(feature = "adaptive_serialization")] + { + self.deserialization_time = current_time() - start; + } + #[cfg(feature = "scalability_introspection")] + { + state.scalability_monitor_mut().testcase_with_observers += 1; + } + fuzzer.execute_and_process( + state, self, input, &observers, &exit_kind, false, + )? + } else { + #[cfg(feature = "scalability_introspection")] + { + state.scalability_monitor_mut().testcase_without_observers += 1; + } + fuzzer.evaluate_input_with_observers::( + state, executor, self, input, false, + )? + }; + if let Some(item) = res.1 { + log::info!("Added received Testcase as item #{item}"); + } } } Event::CustomBuf { tag, buf } => { @@ -686,7 +718,9 @@ where SP: ShMemProvider, E: HasObservers + Executor, for<'a> E::Observers: Deserialize<'a>, - Z: EvaluatorObservers + ExecutionProcessor, + Z: ExecutionProcessor + + EvaluatorObservers + + Evaluator, { fn process( &mut self, @@ -732,7 +766,9 @@ where EMH: EventManagerHooksTuple, S: State + HasExecutions + HasMetadata + HasLastReportTime, SP: ShMemProvider, - Z: EvaluatorObservers + ExecutionProcessor, + Z: ExecutionProcessor + + EvaluatorObservers + + Evaluator, { } diff --git a/libafl/src/events/llmp/restarting.rs b/libafl/src/events/llmp/restarting.rs index 0abe3ec087..52f5cbdb56 100644 --- a/libafl/src/events/llmp/restarting.rs +++ b/libafl/src/events/llmp/restarting.rs @@ -48,7 +48,7 @@ use crate::{ LlmpEventManager, LlmpShouldSaveState, ProgressReporter, }, executors::{Executor, HasObservers}, - fuzzer::{EvaluatorObservers, ExecutionProcessor}, + fuzzer::{Evaluator, EvaluatorObservers, ExecutionProcessor}, inputs::UsesInput, monitors::Monitor, observers::ObserversTuple, @@ -219,7 +219,9 @@ where EMH: EventManagerHooksTuple, S: State + HasExecutions + HasMetadata, SP: ShMemProvider + 'static, - Z: EvaluatorObservers + ExecutionProcessor, //CE: CustomEvent, + Z: ExecutionProcessor + + EvaluatorObservers + + Evaluator>, { fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result { let res = self.llmp_mgr.process(fuzzer, state, executor)?; @@ -236,7 +238,9 @@ where EMH: EventManagerHooksTuple, S: State + HasExecutions + HasMetadata + HasLastReportTime, SP: ShMemProvider + 'static, - Z: EvaluatorObservers + ExecutionProcessor, //CE: CustomEvent, + Z: ExecutionProcessor + + EvaluatorObservers + + Evaluator>, { } @@ -402,6 +406,9 @@ where /// The shared memory provider to use for the broker or client spawned by the restarting /// manager. shmem_provider: SP, + #[builder(default = false)] + /// Consider this testcase as interesting always if true + always_interesting: bool, /// The configuration configuration: EventConfig, /// The monitor to use @@ -487,10 +494,12 @@ where LlmpConnection::IsClient { client } => { #[cfg(not(feature = "adaptive_serialization"))] let mgr: LlmpEventManager = LlmpEventManager::builder() + .always_interesting(self.always_interesting) .hooks(self.hooks) .build_from_client(client, self.configuration)?; #[cfg(feature = "adaptive_serialization")] let mgr: LlmpEventManager = LlmpEventManager::builder() + .always_interesting(self.always_interesting) .hooks(self.hooks) .build_from_client( client, @@ -515,6 +524,7 @@ where // We are a client #[cfg(not(feature = "adaptive_serialization"))] let mgr = LlmpEventManager::builder() + .always_interesting(self.always_interesting) .hooks(self.hooks) .build_on_port( self.shmem_provider.clone(), @@ -523,6 +533,7 @@ where )?; #[cfg(feature = "adaptive_serialization")] let mgr = LlmpEventManager::builder() + .always_interesting(self.always_interesting) .hooks(self.hooks) .build_on_port( self.shmem_provider.clone(),