inmem fix v1

This commit is contained in:
Dominik Maier 2021-01-14 20:40:41 +01:00
parent 0fe2c49a17
commit c9174ecb38
6 changed files with 133 additions and 49 deletions

View File

@ -214,13 +214,20 @@ where
} }
/// Runs the input and triggers observers and feedback /// Runs the input and triggers observers and feedback
pub fn evaluate_input<E, OT>(&mut self, input: &I, executor: &mut E) -> Result<u32, AflError> pub fn evaluate_input<C, E, EM, OT>(
&mut self,
input: &I,
executor: &mut E,
corpus: &C,
event_mgr: &mut EM,
) -> Result<u32, AflError>
where where
E: Executor<I> + HasObservers<OT>, E: Executor<I> + HasObservers<OT>,
OT: ObserversTuple, OT: ObserversTuple,
{ {
executor.pre_exec_observers()?; executor.pre_exec_observers()?;
executor.run_target(&input)?;
executor.run_target(&input, &self, &corpus, &mut event_mgr)?;
self.set_executions(self.executions() + 1); self.set_executions(self.executions() + 1);
executor.post_exec_observers()?; executor.post_exec_observers()?;

View File

@ -1,5 +1,6 @@
use alloc::boxed::Box; use alloc::boxed::Box;
use core::{ffi::c_void, ptr}; use core::{ffi::c_void, ptr};
use os_signals::set_oncrash_ptrs;
use crate::{ use crate::{
corpus::Corpus, corpus::Corpus,
@ -18,14 +19,10 @@ use crate::{
#[cfg(unix)] #[cfg(unix)]
use unix_signals as os_signals; use unix_signals as os_signals;
use self::os_signals::reset_oncrash_ptrs;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use self::os_signals::setup_crash_handlers; 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 /// The inmem executor harness
type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind; type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind;
type OnCrashFunction<I, C, EM, FT, R> = dyn FnMut(ExitKind, &I, &State<I, R, FT>, &C, &mut EM); type OnCrashFunction<I, C, EM, FT, R> = dyn FnMut(ExitKind, &I, &State<I, R, FT>, &C, &mut EM);
@ -60,16 +57,28 @@ where
R: Rand, R: Rand,
{ {
#[inline] #[inline]
fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError> { fn run_target(
let bytes = input.target_bytes(); &mut self,
input: &I,
state: State<I, R, FT>,
corpus: &C,
event_mgr: &EM,
) -> Result<ExitKind, AflError> {
#[cfg(unix)]
unsafe { unsafe {
CURRENT_ON_CRASH_FN = &mut self.on_crash_fn as *mut _ as *mut c_void; set_oncrash_ptrs::<EM, C, OT, FT, I, R>(
CURRENT_INPUT_PTR = input as *const _ as *const c_void; state,
corpus,
event_mgr,
input,
&mut self.on_crash_fn,
);
} }
let bytes = input.target_bytes();
let ret = (self.harness_fn)(self, bytes.as_slice()); let ret = (self.harness_fn)(self, bytes.as_slice());
#[cfg(unix)]
unsafe { unsafe {
CURRENT_ON_CRASH_FN = ptr::null_mut(); reset_oncrash_ptrs::<EM, C, OT, FT, I, R>();
CURRENT_INPUT_PTR = ptr::null();
} }
Ok(ret) Ok(ret)
} }
@ -137,7 +146,7 @@ where
) -> Self { ) -> Self {
#[cfg(feature = "std")] #[cfg(feature = "std")]
unsafe { unsafe {
setup_crash_handlers::<EM, C, OT, FT, I, R>(_state, _corpus, _event_mgr); setup_crash_handlers::<EM, C, OT, FT, I, R>();
} }
Self { Self {
@ -149,6 +158,25 @@ where
} }
} }
/*
unsafe fn tidy_up_on_exit<EM>(mgr: &EM)
where
EM: EventManager<I>,
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(feature = "std")]
#[cfg(unix)] #[cfg(unix)]
pub mod unix_signals { pub mod unix_signals {
@ -172,7 +200,7 @@ pub mod unix_signals {
corpus::Corpus, corpus::Corpus,
engines::State, engines::State,
events::EventManager, events::EventManager,
executors::inmemory::{ExitKind, OnCrashFunction, CURRENT_INPUT_PTR, CURRENT_ON_CRASH_FN}, executors::inmemory::{ExitKind, OnCrashFunction},
feedbacks::FeedbacksTuple, feedbacks::FeedbacksTuple,
inputs::Input, inputs::Input,
observers::ObserversTuple, 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, /// 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, /// we should (tm) be okay with raw pointers here,
static mut CORPUS_PTR: *const 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 state_ptr: *const c_void = ptr::null_mut();
static mut EVENT_MANAGER_PTR: *mut 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<EM, C, OT, FT, I, R>( pub unsafe extern "C" fn libaflrs_executor_inmem_handle_crash<EM, C, OT, FT, I, R>(
_sig: c_int, _sig: c_int,
@ -197,12 +229,13 @@ pub mod unix_signals {
I: Input, I: Input,
R: Rand, R: Rand,
{ {
if CURRENT_INPUT_PTR == ptr::null() { if current_input_ptr == ptr::null() {
println!( println!(
"We died accessing addr {}, but are not in client... Exiting.", "We died accessing addr {}, but are not in client... Exiting.",
info.si_addr() as usize info.si_addr() as usize
); );
return; return;
//exit(1);
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -210,15 +243,13 @@ pub mod unix_signals {
#[cfg(feature = "std")] #[cfg(feature = "std")]
let _ = stdout().flush(); let _ = stdout().flush();
let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap(); let input = (current_input_ptr as *const I).as_ref().unwrap();
let corpus = (CORPUS_PTR as *const C).as_ref().unwrap(); let corpus = (corpus_ptr as *const C).as_ref().unwrap();
let state = (EVENT_MANAGER_PTR as *const State<I, R, FT>) let state = (event_mgr_ptr as *const State<I, R, FT>).as_ref().unwrap();
.as_ref() let manager = (event_mgr_ptr as *mut EM).as_mut().unwrap();
.unwrap();
let manager = (EVENT_MANAGER_PTR as *mut EM).as_mut().unwrap();
if !CURRENT_ON_CRASH_FN.is_null() { if !on_crash_fn_ptr.is_null() {
(*(CURRENT_ON_CRASH_FN as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))( (*(on_crash_fn_ptr as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))(
ExitKind::Crash, ExitKind::Crash,
input, input,
state, state,
@ -243,20 +274,18 @@ pub mod unix_signals {
R: Rand, R: Rand,
{ {
dbg!("TIMEOUT/SIGUSR2 received"); 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"); dbg!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing. Exiting");
return; return;
} }
let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap(); let input = (current_input_ptr as *const I).as_ref().unwrap();
let corpus = (CORPUS_PTR as *const C).as_ref().unwrap(); let corpus = (corpus_ptr as *const C).as_ref().unwrap();
let state = (EVENT_MANAGER_PTR as *const State<I, R, FT>) let state = (event_mgr_ptr as *const State<I, R, FT>).as_ref().unwrap();
.as_ref() let manager = (event_mgr_ptr as *mut EM).as_mut().unwrap();
.unwrap();
let manager = (EVENT_MANAGER_PTR as *mut EM).as_mut().unwrap();
if !CURRENT_ON_CRASH_FN.is_null() { if !on_crash_fn_ptr.is_null() {
(*(CURRENT_ON_CRASH_FN as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))( (*(on_crash_fn_ptr as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))(
ExitKind::Timeout, ExitKind::Timeout,
input, input,
state, state,
@ -283,11 +312,13 @@ pub mod unix_signals {
process::abort(); process::abort();
} }
// TODO clearly state that manager should be static (maybe put the 'static lifetime?) #[inline]
pub unsafe fn setup_crash_handlers<EM, C, OT, FT, I, R>( pub unsafe fn set_oncrash_ptrs<EM, C, OT, FT, I, R>(
state: &State<I, R, FT>, state: &State<I, R, FT>,
corpus: &C, corpus: &C,
manager: &mut EM, event_mgr: &mut EM,
input: I,
on_crash_handler: &mut Box<OnCrashFunction<I, C, EM, FT, R>>,
) where ) where
EM: EventManager<I>, EM: EventManager<I>,
C: Corpus<I, R>, C: Corpus<I, R>,
@ -296,10 +327,32 @@ pub mod unix_signals {
I: Input, I: Input,
R: Rand, R: Rand,
{ {
CORPUS_PTR = corpus as *const _ as *const c_void; current_input_ptr = input as *const _ as *const c_void;
STATE_PTR = state as *const _ as *const c_void; corpus_ptr = corpus as *const _ as *const c_void;
EVENT_MANAGER_PTR = manager as *mut _ as *mut 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<EM, C, OT, FT, I, R>() {
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<EM, C, OT, FT, I, R>()
where
EM: EventManager<I>,
C: Corpus<I, R>,
OT: ObserversTuple,
FT: FeedbacksTuple<I>,
I: Input,
R: Rand,
{
let mut sa: sigaction = mem::zeroed(); let mut sa: sigaction = mem::zeroed();
libc::sigemptyset(&mut sa.sa_mask as *mut libc::sigset_t); libc::sigemptyset(&mut sa.sa_mask as *mut libc::sigset_t);
sa.sa_flags = SA_NODEFER | SA_SIGINFO; sa.sa_flags = SA_NODEFER | SA_SIGINFO;

View File

@ -6,6 +6,7 @@ pub mod runtime;
use core::marker::PhantomData; use core::marker::PhantomData;
use crate::{ use crate::{
engines::State,
inputs::{HasTargetBytes, Input}, inputs::{HasTargetBytes, Input},
observers::ObserversTuple, observers::ObserversTuple,
tuples::{MatchNameAndType, MatchType, Named, TupleList}, tuples::{MatchNameAndType, MatchType, Named, TupleList},
@ -74,7 +75,13 @@ where
I: Input, I: Input,
{ {
/// Instruct the target about the input and run /// Instruct the target about the input and run
fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError>; fn run_target<R, FT, C, EM>(
&mut self,
input: &I,
state: &State<I, R, FT>,
corpus: &C,
event_mgr: &EM,
) -> Result<ExitKind, AflError>;
} }
pub trait ExecutorsTuple<I>: MatchType + MatchNameAndType pub trait ExecutorsTuple<I>: MatchType + MatchNameAndType

View File

@ -208,7 +208,6 @@ where
9 => mutation_byteinteresting, 9 => mutation_byteinteresting,
10 => mutation_wordinteresting, 10 => mutation_wordinteresting,
11 => mutation_dwordinteresting,*/ 11 => mutation_dwordinteresting,*/
_ => mutation_splice, _ => mutation_splice,
}; };
mutation(self, rand, corpus, input)?; mutation(self, rand, corpus, input)?;

View File

@ -35,14 +35,25 @@ where
SH: ShMem, SH: ShMem,
ST: Stats, ST: Stats,
{ {
let mgr_bytes = postcard::to_allocvec(&mgr.describe()?)?; println!("state ptr: {:x}", state as *const _ as u64);
let state_bytes = postcard::to_allocvec(&state)?; println!("state execs: {}", state.executions());
let corpus_bytes = postcard::to_allocvec(&corpus)?; println!("More fun");
Ok(postcard::to_allocvec(&( 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, state_bytes,
corpus_bytes, corpus_bytes,
mgr_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(...)` /// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)`

View File

@ -149,12 +149,17 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
sender.to_env(ENV_FUZZER_SENDER)?; sender.to_env(ENV_FUZZER_SENDER)?;
receiver.to_env(ENV_FUZZER_RECEIVER)?; receiver.to_env(ENV_FUZZER_RECEIVER)?;
let mut ctr = 0;
loop { loop {
dbg!("Spawning next client"); dbg!("Spawning next client");
Command::new(env::current_exe()?) Command::new(env::current_exe()?)
.current_dir(env::current_dir()?) .current_dir(env::current_dir()?)
.args(env::args()) .args(env::args())
.status()?; .status()?;
ctr += 1;
if ctr == 10 {
return Ok(());
}
} }
} }
} }
@ -219,7 +224,9 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
.expect(&format!("Error sending crash event for input {:?}", input)), .expect(&format!("Error sending crash event for input {:?}", input)),
_ => (), _ => (),
} }
println!("foo");
let state_corpus_serialized = serialize_state_corpus_mgr(state, corpus, mgr).unwrap(); 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(); sender.send_buf(0x1, &state_corpus_serialized).unwrap();
}), }),
&state, &state,