From 5605f233fc794a52d2010cfe5d2b725e72f15b2d Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 17 Nov 2021 18:32:26 +0100 Subject: [PATCH] InProcessHandlers (#387) * InProcessHandlers * clippy --- libafl/src/executors/inprocess.rs | 290 +++++++++++++++++------------- 1 file changed, 164 insertions(+), 126 deletions(-) diff --git a/libafl/src/executors/inprocess.rs b/libafl/src/executors/inprocess.rs index a70c46daec..93598948a3 100644 --- a/libafl/src/executors/inprocess.rs +++ b/libafl/src/executors/inprocess.rs @@ -53,10 +53,8 @@ where harness_fn: &'a mut H, /// The observers, observing each run observers: OT, - /// On crash C function pointer - crash_handler: *const c_void, - /// On timeout C function pointer - timeout_handler: *const c_void, + // Crash and timeout hah + handlers: InProcessHandlers, phantom: PhantomData<(I, S)>, } @@ -69,59 +67,15 @@ where #[inline] fn run_target( &mut self, - _fuzzer: &mut Z, - _state: &mut S, - _mgr: &mut EM, + fuzzer: &mut Z, + state: &mut S, + mgr: &mut EM, input: &I, ) -> Result { - #[cfg(unix)] - unsafe { - let data = &mut GLOBAL_STATE; - write_volatile( - &mut data.current_input_ptr, - input as *const _ as *const c_void, - ); - write_volatile(&mut data.executor_ptr, self as *const _ as *const c_void); - data.crash_handler = self.crash_handler; - data.timeout_handler = self.timeout_handler; - // Direct raw pointers access /aliasing is pretty undefined behavior. - // Since the state and event may have moved in memory, refresh them right before the signal may happen - write_volatile(&mut data.state_ptr, _state as *mut _ as *mut c_void); - write_volatile(&mut data.event_mgr_ptr, _mgr as *mut _ as *mut c_void); - write_volatile(&mut data.fuzzer_ptr, _fuzzer as *mut _ as *mut c_void); - compiler_fence(Ordering::SeqCst); - } - #[cfg(all(windows, feature = "std"))] - unsafe { - let data = &mut GLOBAL_STATE; - write_volatile( - &mut data.current_input_ptr, - input as *const _ as *const c_void, - ); - write_volatile(&mut data.executor_ptr, self as *const _ as *const c_void); - data.crash_handler = self.crash_handler; - data.timeout_handler = self.timeout_handler; - // Direct raw pointers access /aliasing is pretty undefined behavior. - // Since the state and event may have moved in memory, refresh them right before the signal may happen - write_volatile(&mut data.state_ptr, _state as *mut _ as *mut c_void); - write_volatile(&mut data.event_mgr_ptr, _mgr as *mut _ as *mut c_void); - write_volatile(&mut data.fuzzer_ptr, _fuzzer as *mut _ as *mut c_void); - compiler_fence(Ordering::SeqCst); - } - + self.handlers + .pre_run_target(self, fuzzer, state, mgr, input); let ret = (self.harness_fn)(input); - - #[cfg(unix)] - unsafe { - write_volatile(&mut GLOBAL_STATE.current_input_ptr, ptr::null()); - compiler_fence(Ordering::SeqCst); - } - #[cfg(all(windows, feature = "std"))] - unsafe { - write_volatile(&mut GLOBAL_STATE.current_input_ptr, ptr::null()); - compiler_fence(Ordering::SeqCst); - } - + self.handlers.post_run_target(); Ok(ret) } } @@ -169,77 +123,11 @@ where S: HasSolutions + HasClientPerfMonitor, Z: HasObjective, { - #[cfg(unix)] - unsafe { - let data = &mut GLOBAL_STATE; - setup_signal_handler(data)?; - compiler_fence(Ordering::SeqCst); - - Ok(Self { - harness_fn, - observers, - crash_handler: unix_signal_handler::inproc_crash_handler::< - Self, - EM, - I, - OC, - OF, - OT, - S, - Z, - > as *const _, - timeout_handler: unix_signal_handler::inproc_timeout_handler::< - Self, - EM, - I, - OC, - OF, - OT, - S, - Z, - > as *const _, - phantom: PhantomData, - }) - } - #[cfg(all(windows, feature = "std"))] - unsafe { - let data = &mut GLOBAL_STATE; - setup_exception_handler(data)?; - compiler_fence(Ordering::SeqCst); - - Ok(Self { - harness_fn, - observers, - crash_handler: windows_exception_handler::inproc_crash_handler::< - Self, - EM, - I, - OC, - OF, - OT, - S, - Z, - > as *const _, - timeout_handler: windows_exception_handler::inproc_timeout_handler::< - Self, - EM, - I, - OC, - OF, - OT, - S, - Z, - > as *const c_void, - // timeout_handler: ptr::null(), - phantom: PhantomData, - }) - } - #[cfg(not(any(unix, all(windows, feature = "std"))))] + let handlers = InProcessHandlers::new::()?; Ok(Self { harness_fn, observers, - crash_handler: ptr::null(), - timeout_handler: ptr::null(), + handlers, phantom: PhantomData, }) } @@ -257,6 +145,157 @@ where } } +#[derive(Debug)] +pub struct InProcessHandlers { + /// On crash C function pointer + crash_handler: *const c_void, + /// On timeout C function pointer + timeout_handler: *const c_void, +} + +impl InProcessHandlers { + pub fn pre_run_target( + &self, + executor: &E, + fuzzer: &mut Z, + state: &mut S, + mgr: &mut EM, + input: &I, + ) { + #[cfg(unix)] + unsafe { + let data = &mut GLOBAL_STATE; + write_volatile( + &mut data.current_input_ptr, + input as *const _ as *const c_void, + ); + write_volatile( + &mut data.executor_ptr, + executor as *const _ as *const c_void, + ); + data.crash_handler = self.crash_handler; + data.timeout_handler = self.timeout_handler; + // Direct raw pointers access /aliasing is pretty undefined behavior. + // Since the state and event may have moved in memory, refresh them right before the signal may happen + write_volatile(&mut data.state_ptr, state as *mut _ as *mut c_void); + write_volatile(&mut data.event_mgr_ptr, mgr as *mut _ as *mut c_void); + write_volatile(&mut data.fuzzer_ptr, fuzzer as *mut _ as *mut c_void); + compiler_fence(Ordering::SeqCst); + } + #[cfg(all(windows, feature = "std"))] + unsafe { + let data = &mut GLOBAL_STATE; + write_volatile( + &mut data.current_input_ptr, + input as *const _ as *const c_void, + ); + write_volatile( + &mut data.executor_ptr, + executor as *const _ as *const c_void, + ); + data.crash_handler = self.crash_handler; + data.timeout_handler = self.timeout_handler; + // Direct raw pointers access /aliasing is pretty undefined behavior. + // Since the state and event may have moved in memory, refresh them right before the signal may happen + write_volatile(&mut data.state_ptr, state as *mut _ as *mut c_void); + write_volatile(&mut data.event_mgr_ptr, mgr as *mut _ as *mut c_void); + write_volatile(&mut data.fuzzer_ptr, fuzzer as *mut _ as *mut c_void); + compiler_fence(Ordering::SeqCst); + } + } + + #[allow(clippy::unused_self)] + pub fn post_run_target(&self) { + #[cfg(unix)] + unsafe { + write_volatile(&mut GLOBAL_STATE.current_input_ptr, ptr::null()); + compiler_fence(Ordering::SeqCst); + } + #[cfg(all(windows, feature = "std"))] + unsafe { + write_volatile(&mut GLOBAL_STATE.current_input_ptr, ptr::null()); + compiler_fence(Ordering::SeqCst); + } + } + + #[must_use] + pub fn new() -> Result + where + I: Input, + E: HasObservers, + OT: ObserversTuple, + EM: EventFirer + EventRestarter, + OC: Corpus, + OF: Feedback, + S: HasSolutions + HasClientPerfMonitor, + Z: HasObjective, + { + #[cfg(unix)] + unsafe { + let data = &mut GLOBAL_STATE; + setup_signal_handler(data)?; + compiler_fence(Ordering::SeqCst); + + Ok(Self { + crash_handler: unix_signal_handler::inproc_crash_handler:: + as *const _, + timeout_handler: unix_signal_handler::inproc_timeout_handler::< + E, + EM, + I, + OC, + OF, + OT, + S, + Z, + > as *const _, + }) + } + #[cfg(all(windows, feature = "std"))] + unsafe { + let data = &mut GLOBAL_STATE; + setup_exception_handler(data)?; + compiler_fence(Ordering::SeqCst); + + Ok(Self { + crash_handler: windows_exception_handler::inproc_crash_handler::< + E, + EM, + I, + OC, + OF, + OT, + S, + Z, + > as *const _, + timeout_handler: windows_exception_handler::inproc_timeout_handler::< + E, + EM, + I, + OC, + OF, + OT, + S, + Z, + > as *const c_void, + }) + } + #[cfg(not(any(unix, all(windows, feature = "std"))))] + Ok(Self { + crash_handler: ptr::null(), + timeout_handler: ptr::null(), + }) + } + + #[must_use] + pub fn nop() -> Self { + Self { + crash_handler: ptr::null(), + timeout_handler: ptr::null(), + } + } +} + pub struct InProcessExecutorHandlerData { pub state_ptr: *mut c_void, pub event_mgr_ptr: *mut c_void, @@ -965,7 +1004,7 @@ where #[cfg(test)] mod tests { - use core::{marker::PhantomData, ptr}; + use core::marker::PhantomData; #[cfg(all(feature = "std", feature = "fork", unix))] use crate::{ @@ -974,7 +1013,7 @@ mod tests { }; use crate::{ bolts::tuples::tuple_list, - executors::{Executor, ExitKind, InProcessExecutor}, + executors::{inprocess::InProcessHandlers, Executor, ExitKind, InProcessExecutor}, inputs::NopInput, }; @@ -985,8 +1024,7 @@ mod tests { let mut in_process_executor = InProcessExecutor::<_, NopInput, (), ()> { harness_fn: &mut harness, observers: tuple_list!(), - crash_handler: ptr::null(), - timeout_handler: ptr::null(), + handlers: InProcessHandlers::nop(), phantom: PhantomData, }; let input = NopInput {};