From 9e9425c622934fc9390a67e7ba7c60fb1a11c57a Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 9 Jun 2021 12:15:08 +0200 Subject: [PATCH] introduce ShadowExecutor --- libafl/src/executors/mod.rs | 3 + libafl/src/executors/shadow.rs | 178 +++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 libafl/src/executors/shadow.rs diff --git a/libafl/src/executors/mod.rs b/libafl/src/executors/mod.rs index 25bcaf3c89..4dfa0d4cdc 100644 --- a/libafl/src/executors/mod.rs +++ b/libafl/src/executors/mod.rs @@ -13,6 +13,9 @@ pub use forkserver::{Forkserver, ForkserverExecutor, OutFile, TimeoutForkserverE pub mod combined; pub use combined::CombinedExecutor; +pub mod shadow; +pub use shadow::{HasShadowObserverHooks, ShadowExecutor}; + use crate::{ bolts::serdeany::SerdeAny, inputs::{HasTargetBytes, Input}, diff --git a/libafl/src/executors/shadow.rs b/libafl/src/executors/shadow.rs new file mode 100644 index 0000000000..99441fcf59 --- /dev/null +++ b/libafl/src/executors/shadow.rs @@ -0,0 +1,178 @@ +//! A `ShadowExecutor` wraps an executor to have shadow observer that will not be considered by the manager + +use crate::{ + executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks}, + inputs::Input, + observers::ObserversTuple, + Error, +}; + +pub trait HasShadowObserverHooks { + /// Run the pre exec hook for all the shadow [`crate::observers::Observer`]`s` + fn pre_exec_shadow_observers( + &mut self, + fuzzer: &mut Z, + state: &mut S, + mgr: &mut EM, + input: &I, + ) -> Result<(), Error>; + + /// Run the post exec hook for all the shadow [`crate::observers::Observer`]`s` + fn post_exec_shadow_observers( + &mut self, + fuzzer: &mut Z, + state: &mut S, + mgr: &mut EM, + input: &I, + ) -> Result<(), Error>; +} + +/// A [`ShadowExecutor`] wraps a primary executor, forwarding its methods, and a secondary one +pub struct ShadowExecutor { + executor: E, + shadow_observers: SOT, + // Enable the execution of the shadow observers hooks with the regular observers hooks + shadow_hooks: bool, +} + +impl ShadowExecutor +where + SOT: ObserversTuple, +{ + /// Create a new `ShadowExecutor`, wrapping the given `executor`. + pub fn new(executor: E, shadow_observers: SOT) -> Self { + Self { + executor, + shadow_observers, + shadow_hooks: false, + } + } + + /// Create a new `ShadowExecutor`, wrapping the given `executor`. + pub fn with_shadow_hooks( + executor: E, + shadow_observers: SOT, + shadow_hooks: bool, + ) -> Self { + Self { + executor, + shadow_observers, + shadow_hooks, + } + } + + #[inline] + pub fn shadow_observers(&self) -> &SOT { + &self.shadow_observers + } + + #[inline] + pub fn shadow_observers_mut(&mut self) -> &mut SOT { + &mut self.shadow_observers + } +} + +impl HasShadowObserverHooks for ShadowExecutor +where + I: Input, + SOT: ObserversTuple + HasExecHooksTuple, +{ + #[inline] + fn pre_exec_shadow_observers( + &mut self, + fuzzer: &mut Z, + state: &mut S, + mgr: &mut EM, + input: &I, + ) -> Result<(), Error> { + self.shadow_observers + .pre_exec_all(fuzzer, state, mgr, input) + } + + #[inline] + fn post_exec_shadow_observers( + &mut self, + fuzzer: &mut Z, + state: &mut S, + mgr: &mut EM, + input: &I, + ) -> Result<(), Error> { + self.shadow_observers + .post_exec_all(fuzzer, state, mgr, input) + } +} + +impl Executor for ShadowExecutor +where + E: Executor, + I: Input, + SOT: ObserversTuple, +{ + fn run_target( + &mut self, + fuzzer: &mut Z, + state: &mut S, + mgr: &mut EM, + input: &I, + ) -> Result { + self.executor.run_target(fuzzer, state, mgr, input) + } +} + +impl HasObservers for ShadowExecutor +where + E: HasObservers, + OT: ObserversTuple, + SOT: ObserversTuple, +{ + #[inline] + fn observers(&self) -> &OT { + self.executor.observers() + } + + #[inline] + fn observers_mut(&mut self) -> &mut OT { + self.executor.observers_mut() + } +} + +impl HasObserversHooks for ShadowExecutor +where + E: HasObservers, + I: Input, + OT: ObserversTuple + HasExecHooksTuple, + SOT: ObserversTuple + HasExecHooksTuple, +{ + /// Run the pre exec hook for all [`crate::observers::Observer`]`s` linked to this [`Executor`]. + #[inline] + fn pre_exec_observers( + &mut self, + fuzzer: &mut Z, + state: &mut S, + mgr: &mut EM, + input: &I, + ) -> Result<(), Error> { + if self.shadow_hooks { + self.shadow_observers + .pre_exec_all(fuzzer, state, mgr, input)?; + } + self.observers_mut().pre_exec_all(fuzzer, state, mgr, input) + } + + /// Run the post exec hook for all the [`crate::observers::Observer`]`s` linked to this [`Executor`]. + #[inline] + fn post_exec_observers( + &mut self, + fuzzer: &mut Z, + state: &mut S, + mgr: &mut EM, + input: &I, + ) -> Result<(), Error> { + if self.shadow_hooks { + self.shadow_observers + .post_exec_all(fuzzer, state, mgr, input)?; + } + self.observers_mut() + .post_exec_all(fuzzer, state, mgr, input) + } +}