This commit is contained in:
Dominik Maier 2021-01-05 14:22:12 +01:00
parent cf7c9cd571
commit 1581993a3f
2 changed files with 24 additions and 33 deletions

View File

@ -28,7 +28,7 @@ static mut EVENT_MANAGER_PTR: *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> = fn(ExitKind, &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);
/// The inmem executor simply calls a target function, then returns afterwards. /// The inmem executor simply calls a target function, then returns afterwards.
pub struct InMemoryExecutor<I, OT, C, E, EM, FT, R> pub struct InMemoryExecutor<I, OT, C, E, EM, FT, R>
@ -44,11 +44,11 @@ where
/// The name of this executor instance, to address it from other components /// The name of this executor instance, to address it from other components
name: &'static str, name: &'static str,
/// The harness function, being executed for each fuzzing loop execution /// The harness function, being executed for each fuzzing loop execution
harness: HarnessFunction<I>, harness_fn: HarnessFunction<I>,
/// The observers, observing each run /// The observers, observing each run
observers: OT, observers: OT,
/// A special function being called right before the process crashes. It may save state to restore fuzzing after respawn. /// A special function being called right before the process crashes. It may save state to restore fuzzing after respawn.
on_crash_fn: OnCrashFunction<I, C, EM, FT, R>, on_crash_fn: Box<OnCrashFunction<I, C, EM, FT, R>>,
phantom: PhantomData<E> phantom: PhantomData<E>
} }
@ -70,7 +70,7 @@ where
CURRENT_ON_CRASH_FN = &mut self.on_crash_fn as *mut _ as *mut c_void; 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; CURRENT_INPUT_PTR = input as *const _ as *const c_void;
} }
let ret = (self.harness)(self, bytes.as_slice()); let ret = (self.harness_fn)(self, bytes.as_slice());
unsafe { unsafe {
CURRENT_ON_CRASH_FN = ptr::null_mut(); CURRENT_ON_CRASH_FN = ptr::null_mut();
CURRENT_INPUT_PTR = ptr::null(); CURRENT_INPUT_PTR = ptr::null();
@ -137,7 +137,8 @@ where
name: &'static str, name: &'static str,
harness_fn: HarnessFunction<I>, harness_fn: HarnessFunction<I>,
observers: OT, observers: OT,
on_crash_fn: OnCrashFunction<I, C, EM, FT, R>, on_crash_fn: Box<OnCrashFunction<I, C, EM, FT, R>>,
_event_mgr: &EM,
) -> Self ) -> Self
{ {
/*#[cfg(feature = "std")] /*#[cfg(feature = "std")]
@ -149,7 +150,7 @@ where
}*/ }*/
Self { Self {
harness: harness_fn, harness_fn,
on_crash_fn, on_crash_fn,
observers, observers,
name, name,
@ -160,36 +161,26 @@ where
/// Serialize the current state and corpus during an executiont to bytes. /// Serialize the current state and corpus during an executiont to bytes.
/// This method is needed when the fuzzer run crashes and has to restart. /// This method is needed when the fuzzer run crashes and has to restart.
pub unsafe fn serialize_state_corpus<C, FT, I, OT, R>() -> Result<Vec<u8>, AflError> pub fn serialize_state_corpus<C, FT, I, OT, R>(state: &State<I, R, FT>, corpus: &C) -> Result<Vec<u8>, AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
I: Input, I: Input,
OT: ObserversTuple,
R: Rand, R: Rand,
{ {
if STATE_PTR.is_null() || CORPUS_PTR.is_null() {
return Err(AflError::IllegalState(
"State or corpus is not currently set and cannot be serialized in in-mem-executor"
.to_string(),
));
}
let state: &State<I, R, FT> = (STATE_PTR as *const State<I, R, FT>).as_ref().unwrap();
let corpus = (CORPUS_PTR as *mut C).as_ref().unwrap();
let state_bytes = postcard::to_allocvec(&state)?; let state_bytes = postcard::to_allocvec(&state)?;
let corpus_bytes = postcard::to_allocvec(&corpus)?; let corpus_bytes = postcard::to_allocvec(&corpus)?;
Ok(postcard::to_allocvec(&(state_bytes, corpus_bytes))?) Ok(postcard::to_allocvec(&(state_bytes, corpus_bytes))?)
} }
/// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)` /// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)`
pub fn deserialize_state_corpus<C, FT, I, OT, R>( pub fn deserialize_state_corpus<C, FT, I, R>(
state_corpus_serialized: &[u8], state_corpus_serialized: &[u8],
) -> Result<(State<I, R, FT>, C), AflError> ) -> Result<(State<I, R, FT>, C), AflError>
where where
C: Corpus<I, R>, C: Corpus<I, R>,
FT: FeedbacksTuple<I>, FT: FeedbacksTuple<I>,
I: Input, I: Input,
OT: ObserversTuple,
R: Rand, R: Rand,
{ {
let tuple: (Vec<u8>, Vec<u8>) = postcard::from_bytes(&state_corpus_serialized)?; let tuple: (Vec<u8>, Vec<u8>) = postcard::from_bytes(&state_corpus_serialized)?;
@ -262,14 +253,13 @@ pub mod unix_signals {
let state = (EVENT_MANAGER_PTR as *const State<I, R, FT>).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 manager = (EVENT_MANAGER_PTR as *mut EM).as_mut().unwrap();
manager.crash(input).expect("Error in sending Crash event");
if !CURRENT_ON_CRASH_FN.is_null() { if !CURRENT_ON_CRASH_FN.is_null() {
(*(CURRENT_ON_CRASH_FN as *mut OnCrashFunction<I, C, EM, FT, R>))( (*(CURRENT_ON_CRASH_FN as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))(
ExitKind::Crash, ExitKind::Crash,
input,
state, state,
corpus, corpus,
manager manager,
); );
} }
@ -300,13 +290,10 @@ pub mod unix_signals {
let state = (EVENT_MANAGER_PTR as *const State<I, R, FT>).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 manager = (EVENT_MANAGER_PTR as *mut EM).as_mut().unwrap();
manager
.timeout(input)
.expect("Error in sending Timeout event");
if !CURRENT_ON_CRASH_FN.is_null() { if !CURRENT_ON_CRASH_FN.is_null() {
(*(CURRENT_ON_CRASH_FN as *mut OnCrashFunction<I, C, EM, FT, R>))( (*(CURRENT_ON_CRASH_FN as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))(
ExitKind::Timeout, ExitKind::Timeout,
input,
state, state,
corpus, corpus,
manager manager
@ -400,10 +387,11 @@ mod tests {
#[test] #[test]
fn test_inmem_exec() { fn test_inmem_exec() {
let mut in_mem_executor = InMemoryExecutor { let mut in_mem_executor = InMemoryExecutor {
harness: test_harness_fn_nop, harness_fn: test_harness_fn_nop,
on_crash_fn: Box::new(|_, _| ()), on_crash_fn: Box::new(|_, _| ()),
observers: tuple_list!(), observers: tuple_list!(),
name: "main", name: "main",
phantom: PhantomData,
}; };
let mut input = NopInput {}; let mut input = NopInput {};
assert!(in_mem_executor.run_target(&mut input).is_ok()); assert!(in_mem_executor.run_target(&mut input).is_ok());

View File

@ -15,7 +15,7 @@ use afl::{
LlmpEventManager, SimpleStats, LlmpEventManager, SimpleStats,
}, },
executors::{ executors::{
inmemory::{deserialize_state_corpus, InMemoryExecutor}, inmemory::{serialize_state_corpus, deserialize_state_corpus, InMemoryExecutor},
Executor, ExitKind, Executor, ExitKind,
}, },
feedbacks::MaxMapFeedback, feedbacks::MaxMapFeedback,
@ -140,12 +140,15 @@ fn fuzz(input: Option<Vec<PathBuf>>, broker_port: u16) -> Result<(), AflError> {
"Libfuzzer", "Libfuzzer",
harness, harness,
tuple_list!(edges_observer), tuple_list!(edges_observer),
Box::new(move |exit_kind, state_corpus_serialized| { Box::new(move |exit_kind, input, state, corpus, mgr| {
match exit_kind {
ExitKind::Timeout => mgr.timeout(input).expect("Error sending Timeout event for input {:?}", input),
ExitKind::Crash => mgr.crash(input).expect("Error sending crash event for input {:?}", input),
}
let state_corpus_serialized = serialize_state_corpus(state, corpus).unwrap();
sender.send_buf(0x1, &state_corpus_serialized).unwrap(); sender.send_buf(0x1, &state_corpus_serialized).unwrap();
}), }),
&state, &mgr,
&corpus,
&mut mgr,
); );
let mut engine = Engine::new(executor); let mut engine = Engine::new(executor);