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
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
E: Executor<I> + HasObservers<OT>,
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()?;

View File

@ -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<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);
@ -60,16 +57,28 @@ where
R: Rand,
{
#[inline]
fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError> {
let bytes = input.target_bytes();
fn run_target(
&mut self,
input: &I,
state: State<I, R, FT>,
corpus: &C,
event_mgr: &EM,
) -> Result<ExitKind, AflError> {
#[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::<EM, C, OT, FT, I, R>(
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::<EM, C, OT, FT, I, R>();
}
Ok(ret)
}
@ -137,7 +146,7 @@ where
) -> Self {
#[cfg(feature = "std")]
unsafe {
setup_crash_handlers::<EM, C, OT, FT, I, R>(_state, _corpus, _event_mgr);
setup_crash_handlers::<EM, C, OT, FT, I, R>();
}
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(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<EM, C, OT, FT, I, R>(
_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<I, R, FT>)
.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<I, R, FT>).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<OnCrashFunction<I, C, EM, FT, R>>))(
if !on_crash_fn_ptr.is_null() {
(*(on_crash_fn_ptr as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))(
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<I, R, FT>)
.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<I, R, FT>).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<OnCrashFunction<I, C, EM, FT, R>>))(
if !on_crash_fn_ptr.is_null() {
(*(on_crash_fn_ptr as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))(
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<EM, C, OT, FT, I, R>(
#[inline]
pub unsafe fn set_oncrash_ptrs<EM, C, OT, FT, I, R>(
state: &State<I, R, FT>,
corpus: &C,
manager: &mut EM,
event_mgr: &mut EM,
input: I,
on_crash_handler: &mut Box<OnCrashFunction<I, C, EM, FT, R>>,
) where
EM: EventManager<I>,
C: Corpus<I, R>,
@ -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<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();
libc::sigemptyset(&mut sa.sa_mask as *mut libc::sigset_t);
sa.sa_flags = SA_NODEFER | SA_SIGINFO;

View File

@ -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<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

View File

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

View File

@ -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(...)`

View File

@ -149,12 +149,17 @@ fn fuzz(input: Option<Vec<PathBuf>>, 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<Vec<PathBuf>>, 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,