TransferFeedback for determining if a testcase was from another node (#1906)

* impl TransferFeedback

* whoops, fix build

* fix doc

* fix build for tcp manager

* fix fr
This commit is contained in:
Addison Crump 2024-03-04 15:33:46 +01:00 committed by GitHub
parent 035c01b4a1
commit f3c37db2b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 108 additions and 6 deletions

View File

@ -28,6 +28,7 @@ use crate::{
EventManagerId, EventProcessor, EventRestarter, HasEventManagerId, LogSeverity, EventManagerId, EventProcessor, EventRestarter, HasEventManagerId, LogSeverity,
}, },
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},
feedbacks::transferred::TransferringMetadata,
fuzzer::{EvaluatorObservers, ExecutionProcessor}, fuzzer::{EvaluatorObservers, ExecutionProcessor},
inputs::{Input, UsesInput}, inputs::{Input, UsesInput},
observers::ObserversTuple, observers::ObserversTuple,
@ -663,6 +664,9 @@ where
} => { } => {
log::info!("Received new Testcase from {client_id:?} ({client_config:?}, forward {forward_id:?})"); log::info!("Received new Testcase from {client_id:?} ({client_config:?}, forward {forward_id:?})");
if let Ok(meta) = state.metadata_mut::<TransferringMetadata>() {
meta.set_transferring(true);
}
let res = let res =
if client_config.match_with(&self.configuration()) && observers_buf.is_some() { if client_config.match_with(&self.configuration()) && observers_buf.is_some() {
let observers: E::Observers = let observers: E::Observers =
@ -692,6 +696,10 @@ where
false, false,
)? )?
}; };
if let Ok(meta) = state.metadata_mut::<TransferringMetadata>() {
meta.set_transferring(false);
}
if let Some(item) = res.1 { if let Some(item) = res.1 {
if res.1.is_some() { if res.1.is_some() {
self.inner.fire( self.inner.fire(

View File

@ -46,6 +46,7 @@ use crate::{
EventProcessor, EventRestarter, HasCustomBufHandlers, HasEventManagerId, ProgressReporter, EventProcessor, EventRestarter, HasCustomBufHandlers, HasEventManagerId, ProgressReporter,
}, },
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},
feedbacks::transferred::TransferringMetadata,
fuzzer::{EvaluatorObservers, ExecutionProcessor}, fuzzer::{EvaluatorObservers, ExecutionProcessor},
inputs::{Input, InputConverter, UsesInput}, inputs::{Input, InputConverter, UsesInput},
monitors::Monitor, monitors::Monitor,
@ -590,6 +591,9 @@ where
} => { } => {
log::info!("Received new Testcase from {client_id:?} ({client_config:?}, forward {forward_id:?})"); log::info!("Received new Testcase from {client_id:?} ({client_config:?}, forward {forward_id:?})");
if let Ok(meta) = state.metadata_mut::<TransferringMetadata>() {
meta.set_transferring(true);
}
let res = if client_config.match_with(&self.configuration) let res = if client_config.match_with(&self.configuration)
&& observers_buf.is_some() && observers_buf.is_some()
{ {
@ -615,6 +619,9 @@ where
state, executor, self, input, false, state, executor, self, input, false,
)? )?
}; };
if let Ok(meta) = state.metadata_mut::<TransferringMetadata>() {
meta.set_transferring(false);
}
if let Some(item) = res.1 { if let Some(item) = res.1 {
log::info!("Added received Testcase as item #{item}"); log::info!("Added received Testcase as item #{item}");
} }
@ -1451,7 +1458,7 @@ where
impl<IC, ICB, DI, S, SP> LlmpEventConverter<IC, ICB, DI, S, SP> impl<IC, ICB, DI, S, SP> LlmpEventConverter<IC, ICB, DI, S, SP>
where where
S: UsesInput + HasExecutions, S: UsesInput + HasExecutions + HasMetadata,
SP: ShMemProvider + 'static, SP: ShMemProvider + 'static,
IC: InputConverter<From = S::Input, To = DI>, IC: InputConverter<From = S::Input, To = DI>,
ICB: InputConverter<From = DI, To = S::Input>, ICB: InputConverter<From = DI, To = S::Input>,
@ -1568,6 +1575,9 @@ where
return Ok(()); return Ok(());
}; };
if let Ok(meta) = state.metadata_mut::<TransferringMetadata>() {
meta.set_transferring(true);
}
let res = fuzzer.evaluate_input_with_observers::<E, EM>( let res = fuzzer.evaluate_input_with_observers::<E, EM>(
state, state,
executor, executor,
@ -1575,6 +1585,10 @@ where
converter.convert(input)?, converter.convert(input)?,
false, false,
)?; )?;
if let Ok(meta) = state.metadata_mut::<TransferringMetadata>() {
meta.set_transferring(false);
}
if let Some(item) = res.1 { if let Some(item) = res.1 {
log::info!("Added received Testcase as item #{item}"); log::info!("Added received Testcase as item #{item}");
} }

View File

@ -44,6 +44,7 @@ use crate::{
EventProcessor, EventRestarter, HasCustomBufHandlers, HasEventManagerId, ProgressReporter, EventProcessor, EventRestarter, HasCustomBufHandlers, HasEventManagerId, ProgressReporter,
}, },
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},
feedbacks::transferred::TransferringMetadata,
fuzzer::{EvaluatorObservers, ExecutionProcessor}, fuzzer::{EvaluatorObservers, ExecutionProcessor},
inputs::{Input, UsesInput}, inputs::{Input, UsesInput},
monitors::Monitor, monitors::Monitor,
@ -457,7 +458,7 @@ where
impl<S> TcpEventManager<S> impl<S> TcpEventManager<S>
where where
S: State + HasExecutions, S: State + HasExecutions + HasMetadata,
{ {
/// Create a manager from a raw TCP client specifying the client id /// Create a manager from a raw TCP client specifying the client id
pub fn existing<A: ToSocketAddrs>( pub fn existing<A: ToSocketAddrs>(
@ -559,6 +560,9 @@ where
} => { } => {
log::info!("Received new Testcase from {client_id:?} ({client_config:?}, forward {forward_id:?})"); log::info!("Received new Testcase from {client_id:?} ({client_config:?}, forward {forward_id:?})");
if let Ok(meta) = state.metadata_mut::<TransferringMetadata>() {
meta.set_transferring(true);
}
let _res = if client_config.match_with(&self.configuration) let _res = if client_config.match_with(&self.configuration)
&& observers_buf.is_some() && observers_buf.is_some()
{ {
@ -578,6 +582,9 @@ where
state, executor, self, input, false, state, executor, self, input, false,
)? )?
}; };
if let Ok(meta) = state.metadata_mut::<TransferringMetadata>() {
meta.set_transferring(false);
}
if let Some(item) = _res.1 { if let Some(item) = _res.1 {
log::info!("Added received Testcase as item #{item}"); log::info!("Added received Testcase as item #{item}");
} }
@ -681,7 +688,7 @@ where
impl<E, S, Z> EventProcessor<E, Z> for TcpEventManager<S> impl<E, S, Z> EventProcessor<E, Z> for TcpEventManager<S>
where where
S: State + HasExecutions, S: State + HasExecutions + HasMetadata,
E: HasObservers<State = S> + Executor<Self, Z>, E: HasObservers<State = S> + Executor<Self, Z>,
for<'a> E::Observers: Deserialize<'a>, for<'a> E::Observers: Deserialize<'a>,
Z: EvaluatorObservers<E::Observers, State = S> + ExecutionProcessor<E::Observers, State = S>, Z: EvaluatorObservers<E::Observers, State = S> + ExecutionProcessor<E::Observers, State = S>,
@ -874,7 +881,7 @@ impl<E, S, SP, Z> EventProcessor<E, Z> for TcpRestartingEventManager<S, SP>
where where
E: HasObservers<State = S> + Executor<TcpEventManager<S>, Z>, E: HasObservers<State = S> + Executor<TcpEventManager<S>, Z>,
for<'a> E::Observers: Deserialize<'a>, for<'a> E::Observers: Deserialize<'a>,
S: State + HasExecutions, S: State + HasExecutions + HasMetadata,
SP: ShMemProvider + 'static, SP: ShMemProvider + 'static,
Z: EvaluatorObservers<E::Observers, State = S> + ExecutionProcessor<E::Observers>, //CE: CustomEvent<I>, Z: EvaluatorObservers<E::Observers, State = S> + ExecutionProcessor<E::Observers>, //CE: CustomEvent<I>,
{ {
@ -978,7 +985,7 @@ pub fn setup_restarting_mgr_tcp<MT, S>(
) -> Result<(Option<S>, TcpRestartingEventManager<S, StdShMemProvider>), Error> ) -> Result<(Option<S>, TcpRestartingEventManager<S, StdShMemProvider>), Error>
where where
MT: Monitor + Clone, MT: Monitor + Clone,
S: State + HasExecutions, S: State + HasExecutions + HasMetadata,
{ {
TcpRestartingMgr::builder() TcpRestartingMgr::builder()
.shmem_provider(StdShMemProvider::new()?) .shmem_provider(StdShMemProvider::new()?)
@ -1039,7 +1046,7 @@ where
impl<MT, S, SP> TcpRestartingMgr<MT, S, SP> impl<MT, S, SP> TcpRestartingMgr<MT, S, SP>
where where
SP: ShMemProvider, SP: ShMemProvider,
S: State + HasExecutions, S: State + HasExecutions + HasMetadata,
MT: Monitor + Clone, MT: Monitor + Clone,
{ {
/// Internal function, returns true when shuttdown is requested by a `SIGINT` signal /// Internal function, returns true when shuttdown is requested by a `SIGINT` signal

View File

@ -23,6 +23,8 @@ pub use new_hash_feedback::NewHashFeedbackMetadata;
#[cfg(feature = "nautilus")] #[cfg(feature = "nautilus")]
pub mod nautilus; pub mod nautilus;
pub mod transferred;
use alloc::string::{String, ToString}; use alloc::string::{String, ToString};
use core::{ use core::{
fmt::{self, Debug, Formatter}, fmt::{self, Debug, Formatter},

View File

@ -0,0 +1,71 @@
//! Feedbacks and associated metadata for detecting whether a given testcase was transferred from
//! another node.
use libafl_bolts::{impl_serdeany, Error, Named};
use serde::{Deserialize, Serialize};
use crate::{
events::EventFirer,
executors::ExitKind,
feedbacks::Feedback,
observers::ObserversTuple,
state::{HasMetadata, State},
};
/// Constant name of the [`TransferringMetadata`].
pub const TRANSFERRED_FEEDBACK_NAME: &str = "transferred_feedback_internal";
/// Metadata which denotes whether we are currently transferring an input. Implementors of
/// multi-node communication systems (like [`crate::events::LlmpEventManager`]) should wrap any
/// [`crate::EvaluatorObservers::evaluate_input_with_observers`] or
/// [`crate::ExecutionProcessor::process_execution`] calls with setting this metadata to true/false
/// before and after.
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub struct TransferringMetadata {
transferring: bool,
}
impl_serdeany!(TransferringMetadata);
impl TransferringMetadata {
/// Indicate to the metadata that we are currently transferring data.
pub fn set_transferring(&mut self, transferring: bool) {
self.transferring = transferring;
}
}
/// Simple feedback which may be used to test whether the testcase was transferred from another node
/// in a multi-node fuzzing arrangement.
#[derive(Copy, Clone, Debug)]
pub struct TransferredFeedback;
impl Named for TransferredFeedback {
fn name(&self) -> &str {
TRANSFERRED_FEEDBACK_NAME
}
}
impl<S> Feedback<S> for TransferredFeedback
where
S: HasMetadata + State,
{
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
state.add_metadata(TransferringMetadata { transferring: true });
Ok(())
}
fn is_interesting<EM, OT>(
&mut self,
state: &mut S,
_manager: &mut EM,
_input: &S::Input,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S>,
{
Ok(state.metadata::<TransferringMetadata>()?.transferring)
}
}