parent
86d6fa005e
commit
89342b22c2
@ -6,7 +6,7 @@ use core::sync::atomic::{Ordering, compiler_fence};
|
|||||||
use core::{
|
use core::{
|
||||||
ffi::c_void,
|
ffi::c_void,
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
ptr::{self, null_mut},
|
ptr::{null, null_mut},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,6 +43,12 @@ use crate::{inputs::Input, observers::ObserversTuple, state::HasCurrentTestcase}
|
|||||||
/// The inmem executor's handlers.
|
/// The inmem executor's handlers.
|
||||||
#[expect(missing_debug_implementations)]
|
#[expect(missing_debug_implementations)]
|
||||||
pub struct InProcessHooks<I, S> {
|
pub struct InProcessHooks<I, S> {
|
||||||
|
/// On crash C function pointer
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub crash_handler: *const c_void,
|
||||||
|
/// On timeout C function pointer
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub timeout_handler: *const c_void,
|
||||||
/// `TImer` struct
|
/// `TImer` struct
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub timer: TimerStruct,
|
pub timer: TimerStruct,
|
||||||
@ -190,6 +196,19 @@ impl<I, S> ExecutorHook<I, S> for InProcessHooks<I, S> {
|
|||||||
fn init(&mut self, _state: &mut S) {}
|
fn init(&mut self, _state: &mut S) {}
|
||||||
/// Call before running a target.
|
/// Call before running a target.
|
||||||
fn pre_exec(&mut self, _state: &mut S, _input: &I) {
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) {
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
// This is very important!!!!!
|
||||||
|
// Don't remove these pointer settings.
|
||||||
|
// Imagine there are two executors, you have to set the correct crash handlers for each of the executor.
|
||||||
|
unsafe {
|
||||||
|
let data = &raw mut GLOBAL_STATE;
|
||||||
|
assert!((*data).crash_handler == null());
|
||||||
|
// usually timeout handler and crash handler is set together
|
||||||
|
// so no check for timeout handler is null or not
|
||||||
|
(*data).crash_handler = self.crash_handler;
|
||||||
|
(*data).timeout_handler = self.timeout_handler;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", not(all(miri, target_vendor = "apple"))))]
|
#[cfg(all(feature = "std", not(all(miri, target_vendor = "apple"))))]
|
||||||
self.timer_mut().set_timer();
|
self.timer_mut().set_timer();
|
||||||
}
|
}
|
||||||
@ -200,6 +219,12 @@ impl<I, S> ExecutorHook<I, S> for InProcessHooks<I, S> {
|
|||||||
// We're calling this only once per execution, in a single thread.
|
// We're calling this only once per execution, in a single thread.
|
||||||
#[cfg(all(feature = "std", not(all(miri, target_vendor = "apple"))))]
|
#[cfg(all(feature = "std", not(all(miri, target_vendor = "apple"))))]
|
||||||
self.timer_mut().unset_timer();
|
self.timer_mut().unset_timer();
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
unsafe {
|
||||||
|
let data = &raw mut GLOBAL_STATE;
|
||||||
|
(*data).crash_handler = null();
|
||||||
|
(*data).timeout_handler = null();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,18 +259,15 @@ impl<I, S> InProcessHooks<I, S> {
|
|||||||
setup_signal_handler(data)?;
|
setup_signal_handler(data)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
unsafe {
|
|
||||||
let data = &raw mut GLOBAL_STATE;
|
|
||||||
(*data).crash_handler =
|
|
||||||
unix_signal_handler::inproc_crash_handler::<E, EM, I, OF, S, Z> as *const c_void;
|
|
||||||
(*data).timeout_handler =
|
|
||||||
unix_signal_handler::inproc_timeout_handler::<E, EM, I, OF, S, Z> as *const _;
|
|
||||||
}
|
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
crash_handler: unix_signal_handler::inproc_crash_handler::<E, EM, I, OF, S, Z>
|
||||||
|
as *const c_void,
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
timeout_handler: unix_signal_handler::inproc_timeout_handler::<E, EM, I, OF, S, Z>
|
||||||
|
as *const _,
|
||||||
|
#[cfg(feature = "std")]
|
||||||
timer: TimerStruct::new(exec_tmout),
|
timer: TimerStruct::new(exec_tmout),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
})
|
})
|
||||||
@ -278,7 +300,7 @@ impl<I, S> InProcessHooks<I, S> {
|
|||||||
>();
|
>();
|
||||||
setup_exception_handler(data)?;
|
setup_exception_handler(data)?;
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
(*data).crash_handler =
|
let crash_handler =
|
||||||
crate::executors::hooks::windows::windows_exception_handler::inproc_crash_handler::<
|
crate::executors::hooks::windows::windows_exception_handler::inproc_crash_handler::<
|
||||||
E,
|
E,
|
||||||
EM,
|
EM,
|
||||||
@ -296,9 +318,10 @@ impl<I, S> InProcessHooks<I, S> {
|
|||||||
S,
|
S,
|
||||||
Z,
|
Z,
|
||||||
> as *const c_void;
|
> as *const c_void;
|
||||||
(*data).timeout_handler = timeout_handler;
|
|
||||||
let timer = TimerStruct::new(exec_tmout, timeout_handler);
|
let timer = TimerStruct::new(exec_tmout, timeout_handler);
|
||||||
ret = Ok(Self {
|
ret = Ok(Self {
|
||||||
|
crash_handler,
|
||||||
|
timeout_handler,
|
||||||
timer,
|
timer,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
});
|
});
|
||||||
@ -336,6 +359,10 @@ impl<I, S> InProcessHooks<I, S> {
|
|||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
pub fn nop() -> Self {
|
pub fn nop() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
crash_handler: null(),
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
timeout_handler: null(),
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
timer: TimerStruct::new(Duration::from_millis(5000)),
|
timer: TimerStruct::new(Duration::from_millis(5000)),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
@ -414,7 +441,7 @@ impl InProcessExecutorHandlerData {
|
|||||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||||
pub(crate) unsafe fn take_current_input<'a, I>(&mut self) -> &'a I {
|
pub(crate) unsafe fn take_current_input<'a, I>(&mut self) -> &'a I {
|
||||||
let r = unsafe { (self.current_input_ptr as *const I).as_ref().unwrap() };
|
let r = unsafe { (self.current_input_ptr as *const I).as_ref().unwrap() };
|
||||||
self.current_input_ptr = ptr::null();
|
self.current_input_ptr = null();
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -509,19 +536,19 @@ pub static mut GLOBAL_STATE: InProcessExecutorHandlerData = InProcessExecutorHan
|
|||||||
// The fuzzer ptr for signal handling
|
// The fuzzer ptr for signal handling
|
||||||
fuzzer_ptr: null_mut(),
|
fuzzer_ptr: null_mut(),
|
||||||
// The executor ptr for signal handling
|
// The executor ptr for signal handling
|
||||||
executor_ptr: ptr::null(),
|
executor_ptr: null(),
|
||||||
// The current input for signal handling
|
// The current input for signal handling
|
||||||
current_input_ptr: ptr::null(),
|
current_input_ptr: null(),
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
signal_handler_depth: 0,
|
signal_handler_depth: 0,
|
||||||
|
|
||||||
// The crash handler fn
|
// The crash handler fn
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
crash_handler: ptr::null(),
|
crash_handler: null(),
|
||||||
// The timeout handler fn
|
// The timeout handler fn
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
timeout_handler: ptr::null(),
|
timeout_handler: null(),
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(all(windows, feature = "std"))]
|
||||||
ptp_timer: None,
|
ptp_timer: None,
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(all(windows, feature = "std"))]
|
||||||
|
@ -26,6 +26,10 @@ use crate::{
|
|||||||
/// The inmem fork executor's hooks.
|
/// The inmem fork executor's hooks.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct InChildProcessHooks<I, S> {
|
pub struct InChildProcessHooks<I, S> {
|
||||||
|
/// On crash C function pointer
|
||||||
|
pub crash_handler: *const c_void,
|
||||||
|
/// On timeout C function pointer
|
||||||
|
pub timeout_handler: *const c_void,
|
||||||
phantom: PhantomData<(I, S)>,
|
phantom: PhantomData<(I, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,9 +38,22 @@ impl<I, S> ExecutorHook<I, S> for InChildProcessHooks<I, S> {
|
|||||||
fn init(&mut self, _state: &mut S) {}
|
fn init(&mut self, _state: &mut S) {}
|
||||||
|
|
||||||
/// Call before running a target.
|
/// Call before running a target.
|
||||||
fn pre_exec(&mut self, _state: &mut S, _input: &I) {}
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) {
|
||||||
|
unsafe {
|
||||||
|
let data = &raw mut FORK_EXECUTOR_GLOBAL_DATA;
|
||||||
|
(*data).crash_handler = self.crash_handler;
|
||||||
|
(*data).timeout_handler = self.timeout_handler;
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn post_exec(&mut self, _state: &mut S, _input: &I) {}
|
fn post_exec(&mut self, _state: &mut S, _input: &I) {
|
||||||
|
unsafe {
|
||||||
|
let data = &raw mut FORK_EXECUTOR_GLOBAL_DATA;
|
||||||
|
(*data).crash_handler = null();
|
||||||
|
(*data).timeout_handler = null();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, S> InChildProcessHooks<I, S> {
|
impl<I, S> InChildProcessHooks<I, S> {
|
||||||
@ -53,11 +70,11 @@ impl<I, S> InChildProcessHooks<I, S> {
|
|||||||
#[cfg(not(miri))]
|
#[cfg(not(miri))]
|
||||||
setup_signal_handler(data)?;
|
setup_signal_handler(data)?;
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
(*data).crash_handler =
|
|
||||||
child_signal_handlers::child_crash_handler::<E, I, S> as *const c_void;
|
|
||||||
(*data).timeout_handler =
|
|
||||||
child_signal_handlers::child_timeout_handler::<E, I, S> as *const c_void;
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
crash_handler: child_signal_handlers::child_crash_handler::<E, I, S>
|
||||||
|
as *const c_void,
|
||||||
|
timeout_handler: child_signal_handlers::child_timeout_handler::<E, I, S>
|
||||||
|
as *const c_void,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -67,6 +84,8 @@ impl<I, S> InChildProcessHooks<I, S> {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn nop() -> Self {
|
pub fn nop() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
crash_handler: null(),
|
||||||
|
timeout_handler: null(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ use libafl::{
|
|||||||
events::{EventFirer, EventRestarter},
|
events::{EventFirer, EventRestarter},
|
||||||
executors::{
|
executors::{
|
||||||
Executor, ExitKind, HasObservers,
|
Executor, ExitKind, HasObservers,
|
||||||
hooks::inprocess::{GLOBAL_STATE, InProcessExecutorHandlerData},
|
hooks::inprocess::InProcessExecutorHandlerData,
|
||||||
inprocess::{HasInProcessHooks, stateful::StatefulInProcessExecutor},
|
inprocess::{HasInProcessHooks, stateful::StatefulInProcessExecutor},
|
||||||
inprocess_fork::stateful::StatefulInProcessForkExecutor,
|
inprocess_fork::stateful::StatefulInProcessForkExecutor,
|
||||||
},
|
},
|
||||||
@ -251,39 +251,27 @@ where
|
|||||||
OF: Feedback<EM, I, OT, S>,
|
OF: Feedback<EM, I, OT, S>,
|
||||||
Z: HasObjective<Objective = OF> + HasScheduler<I, S> + ExecutionProcessor<EM, I, OT, S>,
|
Z: HasObjective<Objective = OF> + HasScheduler<I, S> + ExecutionProcessor<EM, I, OT, S>,
|
||||||
{
|
{
|
||||||
let inner = StatefulInProcessExecutor::with_timeout(
|
let mut inner = StatefulInProcessExecutor::with_timeout(
|
||||||
harness_fn, emulator, observers, fuzzer, state, event_mgr, timeout,
|
harness_fn, emulator, observers, fuzzer, state, event_mgr, timeout,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let data = &raw mut GLOBAL_STATE;
|
// rewrite the crash handler pointer
|
||||||
#[cfg(feature = "usermode")]
|
#[cfg(feature = "usermode")]
|
||||||
unsafe {
|
{
|
||||||
// rewrite the crash handler pointer
|
inner.inprocess_hooks_mut().crash_handler =
|
||||||
(*data).crash_handler =
|
|
||||||
inproc_qemu_crash_handler::<Self, EM, ET, I, OF, S, Z> as *const c_void;
|
inproc_qemu_crash_handler::<Self, EM, ET, I, OF, S, Z> as *const c_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
// rewrite the timeout handler pointer
|
||||||
// rewrite the timeout handler pointer
|
inner.inprocess_hooks_mut().timeout_handler = inproc_qemu_timeout_handler::<
|
||||||
(*data).timeout_handler = inproc_qemu_timeout_handler::<
|
StatefulInProcessExecutor<'a, EM, Emulator<C, CM, ED, ET, I, S, SM>, H, I, OT, S, Z>,
|
||||||
StatefulInProcessExecutor<
|
EM,
|
||||||
'a,
|
ET,
|
||||||
EM,
|
I,
|
||||||
Emulator<C, CM, ED, ET, I, S, SM>,
|
OF,
|
||||||
H,
|
S,
|
||||||
I,
|
Z,
|
||||||
OT,
|
> as *const c_void;
|
||||||
S,
|
|
||||||
Z,
|
|
||||||
>,
|
|
||||||
EM,
|
|
||||||
ET,
|
|
||||||
I,
|
|
||||||
OF,
|
|
||||||
S,
|
|
||||||
Z,
|
|
||||||
> as *const c_void;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner,
|
inner,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user