From c9174ecb38e2146ac79cb8f320dc3b885645cd1a Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 14 Jan 2021 20:40:41 +0100 Subject: [PATCH] inmem fix v1 --- afl/src/engines/mod.rs | 11 ++- afl/src/executors/inmemory.rs | 133 +++++++++++++++++++--------- afl/src/executors/mod.rs | 9 +- afl/src/mutators/scheduled.rs | 1 - afl/src/utils.rs | 21 +++-- fuzzers/libfuzzer_libpng/src/mod.rs | 7 ++ 6 files changed, 133 insertions(+), 49 deletions(-) diff --git a/afl/src/engines/mod.rs b/afl/src/engines/mod.rs index ff9cc651f2..1d350ac179 100644 --- a/afl/src/engines/mod.rs +++ b/afl/src/engines/mod.rs @@ -214,13 +214,20 @@ where } /// Runs the input and triggers observers and feedback - pub fn evaluate_input(&mut self, input: &I, executor: &mut E) -> Result + pub fn evaluate_input( + &mut self, + input: &I, + executor: &mut E, + corpus: &C, + event_mgr: &mut EM, + ) -> Result where E: Executor + HasObservers, OT: ObserversTuple, { executor.pre_exec_observers()?; - executor.run_target(&input)?; + + executor.run_target(&input, &self, &corpus, &mut event_mgr)?; self.set_executions(self.executions() + 1); executor.post_exec_observers()?; diff --git a/afl/src/executors/inmemory.rs b/afl/src/executors/inmemory.rs index bf343f07af..6389619bc4 100644 --- a/afl/src/executors/inmemory.rs +++ b/afl/src/executors/inmemory.rs @@ -1,5 +1,6 @@ use alloc::boxed::Box; use core::{ffi::c_void, ptr}; +use os_signals::set_oncrash_ptrs; use crate::{ corpus::Corpus, @@ -18,14 +19,10 @@ use crate::{ #[cfg(unix)] use unix_signals as os_signals; +use self::os_signals::reset_oncrash_ptrs; #[cfg(feature = "std")] use self::os_signals::setup_crash_handlers; -/// The (unsafe) pointer to the current inmem input, for the current run. -/// This is neede for certain non-rust side effects, as well as unix signal handling. -static mut CURRENT_INPUT_PTR: *const c_void = ptr::null(); -static mut CURRENT_ON_CRASH_FN: *mut c_void = ptr::null_mut(); - /// The inmem executor harness type HarnessFunction = fn(&dyn Executor, &[u8]) -> ExitKind; type OnCrashFunction = dyn FnMut(ExitKind, &I, &State, &C, &mut EM); @@ -60,16 +57,28 @@ where R: Rand, { #[inline] - fn run_target(&mut self, input: &I) -> Result { - let bytes = input.target_bytes(); + fn run_target( + &mut self, + input: &I, + state: State, + corpus: &C, + event_mgr: &EM, + ) -> Result { + #[cfg(unix)] unsafe { - CURRENT_ON_CRASH_FN = &mut self.on_crash_fn as *mut _ as *mut c_void; - CURRENT_INPUT_PTR = input as *const _ as *const c_void; + set_oncrash_ptrs::( + state, + corpus, + event_mgr, + input, + &mut self.on_crash_fn, + ); } + let bytes = input.target_bytes(); let ret = (self.harness_fn)(self, bytes.as_slice()); + #[cfg(unix)] unsafe { - CURRENT_ON_CRASH_FN = ptr::null_mut(); - CURRENT_INPUT_PTR = ptr::null(); + reset_oncrash_ptrs::(); } Ok(ret) } @@ -137,7 +146,7 @@ where ) -> Self { #[cfg(feature = "std")] unsafe { - setup_crash_handlers::(_state, _corpus, _event_mgr); + setup_crash_handlers::(); } Self { @@ -149,6 +158,25 @@ where } } +/* +unsafe fn tidy_up_on_exit(mgr: &EM) +where +EM: EventManager, +I: Input, +{ + + match manager.llmp { + IsClient { client } => { + let map = client.out_maps.last().unwrap(); + /// wait until we can drop the message safely. + map.await_save_to_unmap_blocking(); + /// Make sure all pages are unmapped. + drop(manager); + } + _ => (), + } +}*/ + #[cfg(feature = "std")] #[cfg(unix)] pub mod unix_signals { @@ -172,7 +200,7 @@ pub mod unix_signals { corpus::Corpus, engines::State, events::EventManager, - executors::inmemory::{ExitKind, OnCrashFunction, CURRENT_INPUT_PTR, CURRENT_ON_CRASH_FN}, + executors::inmemory::{ExitKind, OnCrashFunction}, feedbacks::FeedbacksTuple, inputs::Input, observers::ObserversTuple, @@ -181,9 +209,13 @@ pub mod unix_signals { /// Pointers to values only needed on crash. As the program will not continue after a crash, /// we should (tm) be okay with raw pointers here, - static mut CORPUS_PTR: *const c_void = ptr::null_mut(); - static mut STATE_PTR: *const c_void = ptr::null_mut(); - static mut EVENT_MANAGER_PTR: *mut c_void = ptr::null_mut(); + static mut corpus_ptr: *const c_void = ptr::null_mut(); + static mut state_ptr: *const c_void = ptr::null_mut(); + static mut event_mgr_ptr: *mut c_void = ptr::null_mut(); + /// The (unsafe) pointer to the current inmem input, for the current run. + /// This is neede for certain non-rust side effects, as well as unix signal handling. + static mut current_input_ptr: *const c_void = ptr::null(); + static mut on_crash_fn_ptr: *mut c_void = ptr::null_mut(); pub unsafe extern "C" fn libaflrs_executor_inmem_handle_crash( _sig: c_int, @@ -197,12 +229,13 @@ pub mod unix_signals { I: Input, R: Rand, { - if CURRENT_INPUT_PTR == ptr::null() { + if current_input_ptr == ptr::null() { println!( "We died accessing addr {}, but are not in client... Exiting.", info.si_addr() as usize ); return; + //exit(1); } #[cfg(feature = "std")] @@ -210,15 +243,13 @@ pub mod unix_signals { #[cfg(feature = "std")] let _ = stdout().flush(); - let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap(); - let corpus = (CORPUS_PTR as *const C).as_ref().unwrap(); - let state = (EVENT_MANAGER_PTR as *const State) - .as_ref() - .unwrap(); - let manager = (EVENT_MANAGER_PTR as *mut EM).as_mut().unwrap(); + let input = (current_input_ptr as *const I).as_ref().unwrap(); + let corpus = (corpus_ptr as *const C).as_ref().unwrap(); + let state = (event_mgr_ptr as *const State).as_ref().unwrap(); + let manager = (event_mgr_ptr as *mut EM).as_mut().unwrap(); - if !CURRENT_ON_CRASH_FN.is_null() { - (*(CURRENT_ON_CRASH_FN as *mut Box>))( + if !on_crash_fn_ptr.is_null() { + (*(on_crash_fn_ptr as *mut Box>))( ExitKind::Crash, input, state, @@ -243,20 +274,18 @@ pub mod unix_signals { R: Rand, { dbg!("TIMEOUT/SIGUSR2 received"); - if CURRENT_INPUT_PTR.is_null() { + if current_input_ptr.is_null() { dbg!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing. Exiting"); return; } - let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap(); - let corpus = (CORPUS_PTR as *const C).as_ref().unwrap(); - let state = (EVENT_MANAGER_PTR as *const State) - .as_ref() - .unwrap(); - let manager = (EVENT_MANAGER_PTR as *mut EM).as_mut().unwrap(); + let input = (current_input_ptr as *const I).as_ref().unwrap(); + let corpus = (corpus_ptr as *const C).as_ref().unwrap(); + let state = (event_mgr_ptr as *const State).as_ref().unwrap(); + let manager = (event_mgr_ptr as *mut EM).as_mut().unwrap(); - if !CURRENT_ON_CRASH_FN.is_null() { - (*(CURRENT_ON_CRASH_FN as *mut Box>))( + if !on_crash_fn_ptr.is_null() { + (*(on_crash_fn_ptr as *mut Box>))( ExitKind::Timeout, input, state, @@ -283,11 +312,13 @@ pub mod unix_signals { process::abort(); } - // TODO clearly state that manager should be static (maybe put the 'static lifetime?) - pub unsafe fn setup_crash_handlers( + #[inline] + pub unsafe fn set_oncrash_ptrs( state: &State, corpus: &C, - manager: &mut EM, + event_mgr: &mut EM, + input: I, + on_crash_handler: &mut Box>, ) where EM: EventManager, C: Corpus, @@ -296,10 +327,32 @@ pub mod unix_signals { I: Input, R: Rand, { - CORPUS_PTR = corpus as *const _ as *const c_void; - STATE_PTR = state as *const _ as *const c_void; - EVENT_MANAGER_PTR = manager as *mut _ as *mut c_void; + current_input_ptr = input as *const _ as *const c_void; + corpus_ptr = corpus as *const _ as *const c_void; + state_ptr = state as *const _ as *const c_void; + event_mgr_ptr = event_mgr as *mut _ as *mut c_void; + on_crash_fn_ptr = on_crash_handler as *mut _ as *mut c_void; + } + #[inline] + pub unsafe fn reset_oncrash_ptrs() { + current_input_ptr = ptr::null(); + corpus_ptr = ptr::null(); + state_ptr = ptr::null(); + event_mgr_ptr = ptr::null_mut(); + on_crash_fn_ptr = ptr::null_mut(); + } + + // TODO clearly state that manager should be static (maybe put the 'static lifetime?) + pub unsafe fn setup_crash_handlers() + where + EM: EventManager, + C: Corpus, + OT: ObserversTuple, + FT: FeedbacksTuple, + I: Input, + R: Rand, + { let mut sa: sigaction = mem::zeroed(); libc::sigemptyset(&mut sa.sa_mask as *mut libc::sigset_t); sa.sa_flags = SA_NODEFER | SA_SIGINFO; diff --git a/afl/src/executors/mod.rs b/afl/src/executors/mod.rs index 6863f6f9f1..cef91a313c 100644 --- a/afl/src/executors/mod.rs +++ b/afl/src/executors/mod.rs @@ -6,6 +6,7 @@ pub mod runtime; use core::marker::PhantomData; use crate::{ + engines::State, inputs::{HasTargetBytes, Input}, observers::ObserversTuple, tuples::{MatchNameAndType, MatchType, Named, TupleList}, @@ -74,7 +75,13 @@ where I: Input, { /// Instruct the target about the input and run - fn run_target(&mut self, input: &I) -> Result; + fn run_target( + &mut self, + input: &I, + state: &State, + corpus: &C, + event_mgr: &EM, + ) -> Result; } pub trait ExecutorsTuple: MatchType + MatchNameAndType diff --git a/afl/src/mutators/scheduled.rs b/afl/src/mutators/scheduled.rs index 01c7e7edaf..787adc8fba 100644 --- a/afl/src/mutators/scheduled.rs +++ b/afl/src/mutators/scheduled.rs @@ -208,7 +208,6 @@ where 9 => mutation_byteinteresting, 10 => mutation_wordinteresting, 11 => mutation_dwordinteresting,*/ - _ => mutation_splice, }; mutation(self, rand, corpus, input)?; diff --git a/afl/src/utils.rs b/afl/src/utils.rs index 8b38da47a7..35d5d09fda 100644 --- a/afl/src/utils.rs +++ b/afl/src/utils.rs @@ -35,14 +35,25 @@ where SH: ShMem, ST: Stats, { - let mgr_bytes = postcard::to_allocvec(&mgr.describe()?)?; - let state_bytes = postcard::to_allocvec(&state)?; - let corpus_bytes = postcard::to_allocvec(&corpus)?; - Ok(postcard::to_allocvec(&( + println!("state ptr: {:x}", state as *const _ as u64); + println!("state execs: {}", state.executions()); + println!("More fun"); + let ret_slice = postcard::to_allocvec(&(&state, &corpus, &mgr.describe()?))?; + println!("done: {:?}", ret_slice); + //let corpus_bytes = serde_json::to_string(&corpus).unwrap(); + + //println!("fun"); + //let state_bytes = serde_json::to_string(&state).unwrap(); + //println!("fun & games"); + /*match serde_json::to_string(&( state_bytes, corpus_bytes, mgr_bytes, - ))?) + )) { + Ok(val) => Ok(val.as_bytes().to_vec()), + Err(e) => panic!("couldn't do things"), + }*/ + Ok(ret_slice) } /// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)` diff --git a/fuzzers/libfuzzer_libpng/src/mod.rs b/fuzzers/libfuzzer_libpng/src/mod.rs index 7ac87f3a20..c7f24abf0e 100644 --- a/fuzzers/libfuzzer_libpng/src/mod.rs +++ b/fuzzers/libfuzzer_libpng/src/mod.rs @@ -149,12 +149,17 @@ fn fuzz(input: Option>, broker_port: u16) -> Result<(), AflError> { sender.to_env(ENV_FUZZER_SENDER)?; receiver.to_env(ENV_FUZZER_RECEIVER)?; + let mut ctr = 0; loop { dbg!("Spawning next client"); Command::new(env::current_exe()?) .current_dir(env::current_dir()?) .args(env::args()) .status()?; + ctr += 1; + if ctr == 10 { + return Ok(()); + } } } } @@ -219,7 +224,9 @@ fn fuzz(input: Option>, broker_port: u16) -> Result<(), AflError> { .expect(&format!("Error sending crash event for input {:?}", input)), _ => (), } + println!("foo"); let state_corpus_serialized = serialize_state_corpus_mgr(state, corpus, mgr).unwrap(); + println!("bar: {:?}", &state_corpus_serialized); sender.send_buf(0x1, &state_corpus_serialized).unwrap(); }), &state,