Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Revert #2935 #3031

Merged
merged 4 commits into from
Feb 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 44 additions & 17 deletions libafl/src/executors/hooks/inprocess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use core::sync::atomic::{Ordering, compiler_fence};
use core::{
ffi::c_void,
marker::PhantomData,
ptr::{self, null_mut},
ptr::{null, null_mut},
time::Duration,
};

Expand Down Expand Up @@ -43,6 +43,12 @@ use crate::{inputs::Input, observers::ObserversTuple, state::HasCurrentTestcase}
/// The inmem executor's handlers.
#[expect(missing_debug_implementations)]
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
#[cfg(feature = "std")]
pub timer: TimerStruct,
Expand Down Expand Up @@ -190,6 +196,19 @@ impl<I, S> ExecutorHook<I, S> for InProcessHooks<I, S> {
fn init(&mut self, _state: &mut S) {}
/// Call before running a target.
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"))))]
self.timer_mut().set_timer();
}
Expand All @@ -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.
#[cfg(all(feature = "std", not(all(miri, target_vendor = "apple"))))]
self.timer_mut().unset_timer();
#[cfg(feature = "std")]
unsafe {
let data = &raw mut GLOBAL_STATE;
(*data).crash_handler = null();
(*data).timeout_handler = null();
}
}
}

Expand Down Expand Up @@ -234,18 +259,15 @@ impl<I, S> InProcessHooks<I, S> {
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);
Ok(Self {
#[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),
phantom: PhantomData,
})
Expand Down Expand Up @@ -278,7 +300,7 @@ impl<I, S> InProcessHooks<I, S> {
>();
setup_exception_handler(data)?;
compiler_fence(Ordering::SeqCst);
(*data).crash_handler =
let crash_handler =
crate::executors::hooks::windows::windows_exception_handler::inproc_crash_handler::<
E,
EM,
Expand All @@ -296,9 +318,10 @@ impl<I, S> InProcessHooks<I, S> {
S,
Z,
> as *const c_void;
(*data).timeout_handler = timeout_handler;
let timer = TimerStruct::new(exec_tmout, timeout_handler);
ret = Ok(Self {
crash_handler,
timeout_handler,
timer,
phantom: PhantomData,
});
Expand Down Expand Up @@ -336,6 +359,10 @@ impl<I, S> InProcessHooks<I, S> {
#[cfg(not(windows))]
pub fn nop() -> Self {
Self {
#[cfg(feature = "std")]
crash_handler: null(),
#[cfg(feature = "std")]
timeout_handler: null(),
#[cfg(feature = "std")]
timer: TimerStruct::new(Duration::from_millis(5000)),
phantom: PhantomData,
Expand Down Expand Up @@ -414,7 +441,7 @@ impl InProcessExecutorHandlerData {
#[cfg(all(feature = "std", any(unix, windows)))]
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() };
self.current_input_ptr = ptr::null();
self.current_input_ptr = null();
r
}

Expand Down Expand Up @@ -509,19 +536,19 @@ pub static mut GLOBAL_STATE: InProcessExecutorHandlerData = InProcessExecutorHan
// The fuzzer ptr for signal handling
fuzzer_ptr: null_mut(),
// The executor ptr for signal handling
executor_ptr: ptr::null(),
executor_ptr: null(),
// The current input for signal handling
current_input_ptr: ptr::null(),
current_input_ptr: null(),

#[cfg(feature = "std")]
signal_handler_depth: 0,

// The crash handler fn
#[cfg(feature = "std")]
crash_handler: ptr::null(),
crash_handler: null(),
// The timeout handler fn
#[cfg(feature = "std")]
timeout_handler: ptr::null(),
timeout_handler: null(),
#[cfg(all(windows, feature = "std"))]
ptp_timer: None,
#[cfg(all(windows, feature = "std"))]
Expand Down
31 changes: 25 additions & 6 deletions libafl/src/executors/hooks/inprocess_fork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ use crate::{
/// The inmem fork executor's hooks.
#[derive(Debug)]
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)>,
}

Expand All @@ -34,9 +38,22 @@ impl<I, S> ExecutorHook<I, S> for InChildProcessHooks<I, S> {
fn init(&mut self, _state: &mut S) {}

/// 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> {
Expand All @@ -53,11 +70,11 @@ impl<I, S> InChildProcessHooks<I, S> {
#[cfg(not(miri))]
setup_signal_handler(data)?;
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 {
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,
})
}
Expand All @@ -67,6 +84,8 @@ impl<I, S> InChildProcessHooks<I, S> {
#[must_use]
pub fn nop() -> Self {
Self {
crash_handler: null(),
timeout_handler: null(),
phantom: PhantomData,
}
}
Expand Down
42 changes: 15 additions & 27 deletions libafl_qemu/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use libafl::{
events::{EventFirer, EventRestarter},
executors::{
Executor, ExitKind, HasObservers,
hooks::inprocess::{GLOBAL_STATE, InProcessExecutorHandlerData},
hooks::inprocess::InProcessExecutorHandlerData,
inprocess::{HasInProcessHooks, stateful::StatefulInProcessExecutor},
inprocess_fork::stateful::StatefulInProcessForkExecutor,
},
Expand Down Expand Up @@ -251,39 +251,27 @@ where
OF: Feedback<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,
)?;

let data = &raw mut GLOBAL_STATE;
// rewrite the crash handler pointer
#[cfg(feature = "usermode")]
unsafe {
// rewrite the crash handler pointer
(*data).crash_handler =
{
inner.inprocess_hooks_mut().crash_handler =
inproc_qemu_crash_handler::<Self, EM, ET, I, OF, S, Z> as *const c_void;
}

unsafe {
// rewrite the timeout handler pointer
(*data).timeout_handler = inproc_qemu_timeout_handler::<
StatefulInProcessExecutor<
'a,
EM,
Emulator<C, CM, ED, ET, I, S, SM>,
H,
I,
OT,
S,
Z,
>,
EM,
ET,
I,
OF,
S,
Z,
> as *const c_void;
}
// rewrite the timeout handler pointer
inner.inprocess_hooks_mut().timeout_handler = inproc_qemu_timeout_handler::<
StatefulInProcessExecutor<'a, EM, Emulator<C, CM, ED, ET, I, S, SM>, H, I, OT, S, Z>,
EM,
ET,
I,
OF,
S,
Z,
> as *const c_void;

Ok(Self {
inner,
Expand Down
Loading