Don't write pointers to the crash handlers at every execution (#2935)
* make it safe * aa * forgot to put it back * stateful * comment * lol * aa * aa * aa * win * lol * lol * a * a * i hate rust --------- Co-authored-by: Your Name <you@example.com>
This commit is contained in:
parent
8398f8f99a
commit
c09feeba4e
@ -43,12 +43,6 @@ 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,
|
||||||
@ -196,20 +190,12 @@ 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")]
|
|
||||||
unsafe {
|
|
||||||
let data = &raw mut GLOBAL_STATE;
|
|
||||||
(*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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call after running a target.
|
/// Call after running a target.
|
||||||
fn post_exec(&mut self, _state: &mut S, _input: &I) {
|
fn post_exec(&mut self, _state: &mut S, _input: &I) {
|
||||||
// timeout stuff
|
|
||||||
// # Safety
|
// # Safety
|
||||||
// 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"))))]
|
||||||
@ -247,15 +233,19 @@ impl<I, S> InProcessHooks<I, S> {
|
|||||||
unsafe {
|
unsafe {
|
||||||
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,
|
||||||
})
|
})
|
||||||
@ -288,7 +278,7 @@ impl<I, S> InProcessHooks<I, S> {
|
|||||||
>();
|
>();
|
||||||
setup_exception_handler(data)?;
|
setup_exception_handler(data)?;
|
||||||
compiler_fence(Ordering::SeqCst);
|
compiler_fence(Ordering::SeqCst);
|
||||||
let crash_handler =
|
(*data).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,
|
||||||
@ -306,10 +296,9 @@ 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,
|
||||||
});
|
});
|
||||||
@ -347,10 +336,6 @@ 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: ptr::null(),
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
timeout_handler: ptr::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,
|
||||||
@ -374,10 +359,10 @@ pub struct InProcessExecutorHandlerData {
|
|||||||
|
|
||||||
/// The timeout handler
|
/// The timeout handler
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub(crate) crash_handler: *const c_void,
|
pub crash_handler: *const c_void,
|
||||||
/// The timeout handler
|
/// The timeout handler
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub(crate) timeout_handler: *const c_void,
|
pub timeout_handler: *const c_void,
|
||||||
|
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(all(windows, feature = "std"))]
|
||||||
pub(crate) ptp_timer: Option<PTP_TIMER>,
|
pub(crate) ptp_timer: Option<PTP_TIMER>,
|
||||||
@ -501,7 +486,7 @@ impl InProcessExecutorHandlerData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Exception handling needs some nasty unsafe.
|
/// Exception handling needs some nasty unsafe.
|
||||||
pub(crate) static mut GLOBAL_STATE: InProcessExecutorHandlerData = InProcessExecutorHandlerData {
|
pub static mut GLOBAL_STATE: InProcessExecutorHandlerData = InProcessExecutorHandlerData {
|
||||||
// The state ptr for signal handling
|
// The state ptr for signal handling
|
||||||
state_ptr: null_mut(),
|
state_ptr: null_mut(),
|
||||||
// The event manager ptr for signal handling
|
// The event manager ptr for signal handling
|
||||||
|
@ -27,10 +27,6 @@ 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)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,14 +35,7 @@ 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) {}
|
||||||
}
|
}
|
||||||
@ -65,11 +54,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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -79,8 +68,6 @@ 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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,16 +90,19 @@ where
|
|||||||
input: &I,
|
input: &I,
|
||||||
) -> Result<ExitKind, Error> {
|
) -> Result<ExitKind, Error> {
|
||||||
*state.executions_mut() += 1;
|
*state.executions_mut() += 1;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let executor_ptr = ptr::from_ref(self) as *const c_void;
|
let executor_ptr = ptr::from_ref(self) as *const c_void;
|
||||||
self.inner
|
self.inner
|
||||||
.enter_target(fuzzer, state, mgr, input, executor_ptr);
|
.enter_target(fuzzer, state, mgr, input, executor_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.inner.hooks.pre_exec_all(state, input);
|
self.inner.hooks.pre_exec_all(state, input);
|
||||||
|
|
||||||
let ret = self.harness_fn.borrow_mut()(input);
|
let ret = self.harness_fn.borrow_mut()(input);
|
||||||
|
|
||||||
self.inner.hooks.post_exec_all(state, input);
|
self.inner.hooks.post_exec_all(state, input);
|
||||||
|
|
||||||
self.inner.leave_target(fuzzer, state, mgr, input);
|
self.inner.leave_target(fuzzer, state, mgr, input);
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,7 @@ where
|
|||||||
input: &I,
|
input: &I,
|
||||||
) -> Result<ExitKind, Error> {
|
) -> Result<ExitKind, Error> {
|
||||||
*state.executions_mut() += 1;
|
*state.executions_mut() += 1;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let executor_ptr = ptr::from_ref(self) as *const c_void;
|
let executor_ptr = ptr::from_ref(self) as *const c_void;
|
||||||
self.inner
|
self.inner
|
||||||
@ -96,6 +97,7 @@ where
|
|||||||
let ret = self.harness_fn.borrow_mut()(&mut self.exposed_executor_state, state, input);
|
let ret = self.harness_fn.borrow_mut()(&mut self.exposed_executor_state, state, input);
|
||||||
|
|
||||||
self.inner.hooks.post_exec_all(state, input);
|
self.inner.hooks.post_exec_all(state, input);
|
||||||
|
|
||||||
self.inner.leave_target(fuzzer, state, mgr, input);
|
self.inner.leave_target(fuzzer, state, mgr, input);
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ use libafl::state::HasCorpus;
|
|||||||
use libafl::{
|
use libafl::{
|
||||||
events::{EventFirer, EventRestarter},
|
events::{EventFirer, EventRestarter},
|
||||||
executors::{
|
executors::{
|
||||||
hooks::inprocess::InProcessExecutorHandlerData,
|
hooks::inprocess::{InProcessExecutorHandlerData, GLOBAL_STATE},
|
||||||
inprocess::{stateful::StatefulInProcessExecutor, HasInProcessHooks},
|
inprocess::{stateful::StatefulInProcessExecutor, HasInProcessHooks},
|
||||||
inprocess_fork::stateful::StatefulInProcessForkExecutor,
|
inprocess_fork::stateful::StatefulInProcessForkExecutor,
|
||||||
Executor, ExitKind, HasObservers,
|
Executor, ExitKind, HasObservers,
|
||||||
@ -243,25 +243,39 @@ 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 mut inner = StatefulInProcessExecutor::with_timeout(
|
let 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;
|
||||||
#[cfg(feature = "usermode")]
|
#[cfg(feature = "usermode")]
|
||||||
{
|
unsafe {
|
||||||
inner.inprocess_hooks_mut().crash_handler =
|
// rewrite the crash handler pointer
|
||||||
|
(*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;
|
||||||
}
|
}
|
||||||
|
|
||||||
inner.inprocess_hooks_mut().timeout_handler = inproc_qemu_timeout_handler::<
|
unsafe {
|
||||||
StatefulInProcessExecutor<'a, EM, Emulator<C, CM, ED, ET, I, S, SM>, H, I, OT, S, Z>,
|
// rewrite the timeout handler pointer
|
||||||
EM,
|
(*data).timeout_handler = inproc_qemu_timeout_handler::<
|
||||||
ET,
|
StatefulInProcessExecutor<
|
||||||
I,
|
'a,
|
||||||
OF,
|
EM,
|
||||||
S,
|
Emulator<C, CM, ED, ET, I, S, SM>,
|
||||||
Z,
|
H,
|
||||||
> as *const c_void;
|
I,
|
||||||
|
OT,
|
||||||
|
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