Replace static borrows with addr_of!, rust 2024 compatibility (#1800)

* Less UB

* fmt

* fix warning

* clippy fixes

* addr_of_mut allthethings

* removed duplicate import

* fix imports

* remove comment

* more windows

* fmt

* fix tests

* fixes

* qemu

* fix more cases, qemu

* fix

* fmt
This commit is contained in:
Dominik Maier 2024-01-24 17:47:55 +01:00 committed by GitHub
parent bb443027f7
commit 0cb7b25f39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 263 additions and 193 deletions

View File

@ -73,7 +73,7 @@ You can then link this observer to `FridaInProcessExecutor` as follows:
tuple_list!( tuple_list!(
edges_observer, edges_observer,
time_observer, time_observer,
AsanErrorsObserver::new(&ASAN_ERRORS) AsanErrorsObserver::new(addr_of!(ASAN_ERRORS))
), ),
&mut fuzzer, &mut fuzzer,
&mut state, &mut state,

View File

@ -5,6 +5,8 @@ use alloc::{
string::{String, ToString}, string::{String, ToString},
vec::Vec, vec::Vec,
}; };
#[cfg(all(unix, not(miri), feature = "std"))]
use core::ptr::addr_of_mut;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, Ordering};
use core::{marker::PhantomData, num::NonZeroUsize, time::Duration}; use core::{marker::PhantomData, num::NonZeroUsize, time::Duration};
@ -1261,7 +1263,9 @@ where
// We setup signal handlers to clean up shmem segments used by state restorer // We setup signal handlers to clean up shmem segments used by state restorer
#[cfg(all(unix, not(miri)))] #[cfg(all(unix, not(miri)))]
if let Err(_e) = unsafe { setup_signal_handler(&mut EVENTMGR_SIGHANDLER_STATE) } { if let Err(_e) =
unsafe { setup_signal_handler(addr_of_mut!(EVENTMGR_SIGHANDLER_STATE)) }
{
// We can live without a proper ctrl+c signal handler. Print and ignore. // We can live without a proper ctrl+c signal handler. Print and ignore.
log::error!("Failed to setup signal handlers: {_e}"); log::error!("Failed to setup signal handlers: {_e}");
} }

View File

@ -697,6 +697,8 @@ impl<S> HasEventManagerId for NopEventManager<S> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use core::ptr::addr_of_mut;
use libafl_bolts::{current_time, tuples::tuple_list, Named}; use libafl_bolts::{current_time, tuples::tuple_list, Named};
use tuple_list::tuple_list_type; use tuple_list::tuple_list_type;
@ -711,7 +713,9 @@ mod tests {
#[test] #[test]
fn test_event_serde() { fn test_event_serde() {
let obv = unsafe { StdMapObserver::new("test", &mut MAP) }; let obv = unsafe {
StdMapObserver::from_mut_ptr("test", addr_of_mut!(MAP) as *mut u32, MAP.len())
};
let map = tuple_list!(obv); let map = tuple_list!(obv);
let observers_buf = postcard::to_allocvec(&map).unwrap(); let observers_buf = postcard::to_allocvec(&map).unwrap();

View File

@ -5,6 +5,8 @@ use alloc::{
string::{String, ToString}, string::{String, ToString},
vec::Vec, vec::Vec,
}; };
#[cfg(all(unix, not(miri), feature = "std"))]
use core::ptr::addr_of_mut;
use core::{fmt::Debug, marker::PhantomData}; use core::{fmt::Debug, marker::PhantomData};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use core::{ use core::{
@ -485,7 +487,9 @@ where
// We setup signal handlers to clean up shmem segments used by state restorer // We setup signal handlers to clean up shmem segments used by state restorer
#[cfg(all(unix, not(miri)))] #[cfg(all(unix, not(miri)))]
if let Err(_e) = unsafe { setup_signal_handler(&mut EVENTMGR_SIGHANDLER_STATE) } { if let Err(_e) =
unsafe { setup_signal_handler(addr_of_mut!(EVENTMGR_SIGHANDLER_STATE)) }
{
// We can live without a proper ctrl+c signal handler. Print and ignore. // We can live without a proper ctrl+c signal handler. Print and ignore.
log::error!("Failed to setup signal handlers: {_e}"); log::error!("Failed to setup signal handlers: {_e}");
} }

View File

@ -5,6 +5,8 @@ use alloc::{
string::{String, ToString}, string::{String, ToString},
vec::Vec, vec::Vec,
}; };
#[cfg(all(unix, feature = "std", not(miri)))]
use core::ptr::addr_of_mut;
use core::{ use core::{
marker::PhantomData, marker::PhantomData,
num::NonZeroUsize, num::NonZeroUsize,
@ -1143,7 +1145,9 @@ where
// We setup signal handlers to clean up shmem segments used by state restorer // We setup signal handlers to clean up shmem segments used by state restorer
#[cfg(all(unix, not(miri)))] #[cfg(all(unix, not(miri)))]
if let Err(_e) = unsafe { setup_signal_handler(&mut EVENTMGR_SIGHANDLER_STATE) } { if let Err(_e) =
unsafe { setup_signal_handler(addr_of_mut!(EVENTMGR_SIGHANDLER_STATE)) }
{
// We can live without a proper ctrl+c signal handler. Print and ignore. // We can live without a proper ctrl+c signal handler. Print and ignore.
log::error!("Failed to setup signal handlers: {_e}"); log::error!("Failed to setup signal handlers: {_e}");
} }

View File

@ -1,4 +1,6 @@
//! The hook for `InProcessExecutor` //! The hook for `InProcessExecutor`
#[cfg(any(unix, feature = "std"))]
use core::ptr::addr_of_mut;
#[cfg(any(unix, all(windows, feature = "std")))] #[cfg(any(unix, all(windows, feature = "std")))]
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, Ordering};
use core::{ use core::{
@ -123,7 +125,7 @@ impl HasTimeout for InProcessHooks {
fn handle_timeout(&mut self, data: &mut InProcessExecutorHandlerData) -> bool { fn handle_timeout(&mut self, data: &mut InProcessExecutorHandlerData) -> bool {
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]
{ {
return false; false
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
@ -190,10 +192,10 @@ impl ExecutorHook for InProcessHooks {
#[allow(unused_variables)] #[allow(unused_variables)]
fn pre_exec<EM, I, S, Z>(&mut self, fuzzer: &mut Z, state: &mut S, mgr: &mut EM, input: &I) { fn pre_exec<EM, I, S, Z>(&mut self, fuzzer: &mut Z, state: &mut S, mgr: &mut EM, input: &I) {
#[cfg(feature = "std")] #[cfg(feature = "std")]
{ unsafe {
let data = unsafe { &mut GLOBAL_STATE }; let data = addr_of_mut!(GLOBAL_STATE);
data.crash_handler = self.crash_handler; (*data).crash_handler = self.crash_handler;
data.timeout_handler = self.timeout_handler; (*data).timeout_handler = self.timeout_handler;
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -209,7 +211,6 @@ impl ExecutorHook for InProcessHooks {
_mgr: &mut EM, _mgr: &mut EM,
_input: &I, _input: &I,
) { ) {
// let _data = unsafe { &mut GLOBAL_STATE };
// timeout stuff // timeout stuff
#[cfg(feature = "std")] #[cfg(feature = "std")]
self.timer_mut().unset_timer(); self.timer_mut().unset_timer();
@ -230,7 +231,7 @@ impl InProcessHooks {
{ {
#[cfg_attr(miri, allow(unused_variables))] #[cfg_attr(miri, allow(unused_variables))]
unsafe { unsafe {
let data = &mut GLOBAL_STATE; let data = addr_of_mut!(GLOBAL_STATE);
#[cfg(feature = "std")] #[cfg(feature = "std")]
unix_signal_handler::setup_panic_hook::<E, EM, OF, Z>(); unix_signal_handler::setup_panic_hook::<E, EM, OF, Z>();
#[cfg(all(not(miri), unix, feature = "std"))] #[cfg(all(not(miri), unix, feature = "std"))]
@ -263,7 +264,7 @@ impl InProcessHooks {
let ret; let ret;
#[cfg(feature = "std")] #[cfg(feature = "std")]
unsafe { unsafe {
let data = &mut GLOBAL_STATE; let data = addr_of_mut!(GLOBAL_STATE);
crate::executors::hooks::windows::windows_exception_handler::setup_panic_hook::< crate::executors::hooks::windows::windows_exception_handler::setup_panic_hook::<
E, E,
EM, EM,

View File

@ -2,7 +2,7 @@
use alloc::vec::Vec; use alloc::vec::Vec;
use core::{ use core::{
ffi::c_void, ffi::c_void,
ptr::null, ptr::{addr_of_mut, null},
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{compiler_fence, Ordering},
}; };
use std::intrinsics::transmute; use std::intrinsics::transmute;
@ -44,9 +44,9 @@ impl ExecutorHook for InChildProcessHooks {
_input: &I, _input: &I,
) { ) {
unsafe { unsafe {
let data = &mut FORK_EXECUTOR_GLOBAL_DATA; let data = addr_of_mut!(FORK_EXECUTOR_GLOBAL_DATA);
data.crash_handler = self.crash_handler; (*data).crash_handler = self.crash_handler;
data.timeout_handler = self.timeout_handler; (*data).timeout_handler = self.timeout_handler;
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
} }
} }
@ -69,7 +69,7 @@ impl InChildProcessHooks {
{ {
#[cfg_attr(miri, allow(unused_variables))] #[cfg_attr(miri, allow(unused_variables))]
unsafe { unsafe {
let data = &mut FORK_EXECUTOR_GLOBAL_DATA; let data = addr_of_mut!(FORK_EXECUTOR_GLOBAL_DATA);
// child_signal_handlers::setup_child_panic_hook::<E, I, OT, S>(); // child_signal_handlers::setup_child_panic_hook::<E, I, OT, S>();
#[cfg(not(miri))] #[cfg(not(miri))]
setup_signal_handler(data)?; setup_signal_handler(data)?;
@ -153,14 +153,24 @@ impl Handler for InProcessForkExecutorGlobalData {
if !FORK_EXECUTOR_GLOBAL_DATA.timeout_handler.is_null() { if !FORK_EXECUTOR_GLOBAL_DATA.timeout_handler.is_null() {
let func: ForkHandlerFuncPtr = let func: ForkHandlerFuncPtr =
transmute(FORK_EXECUTOR_GLOBAL_DATA.timeout_handler); transmute(FORK_EXECUTOR_GLOBAL_DATA.timeout_handler);
(func)(signal, info, context, &mut FORK_EXECUTOR_GLOBAL_DATA); (func)(
signal,
info,
context,
addr_of_mut!(FORK_EXECUTOR_GLOBAL_DATA),
);
} }
}, },
_ => unsafe { _ => unsafe {
if !FORK_EXECUTOR_GLOBAL_DATA.crash_handler.is_null() { if !FORK_EXECUTOR_GLOBAL_DATA.crash_handler.is_null() {
let func: ForkHandlerFuncPtr = let func: ForkHandlerFuncPtr =
transmute(FORK_EXECUTOR_GLOBAL_DATA.crash_handler); transmute(FORK_EXECUTOR_GLOBAL_DATA.crash_handler);
(func)(signal, info, context, &mut FORK_EXECUTOR_GLOBAL_DATA); (func)(
signal,
info,
context,
addr_of_mut!(FORK_EXECUTOR_GLOBAL_DATA),
);
} }
}, },
} }

View File

@ -12,7 +12,7 @@ use core::{
}; };
#[cfg(all(unix, not(target_os = "linux")))] #[cfg(all(unix, not(target_os = "linux")))]
pub const ITIMER_REAL: core::ffi::c_int = 0; pub(crate) const ITIMER_REAL: core::ffi::c_int = 0;
#[cfg(windows)] #[cfg(windows)]
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, Ordering};
@ -64,7 +64,7 @@ pub(crate) struct Itimerval {
#[cfg(all(feature = "std", unix, not(target_os = "linux")))] #[cfg(all(feature = "std", unix, not(target_os = "linux")))]
extern "C" { extern "C" {
pub fn setitimer( pub(crate) fn setitimer(
which: libc::c_int, which: libc::c_int,
new_value: *mut Itimerval, new_value: *mut Itimerval,
old_value: *mut Itimerval, old_value: *mut Itimerval,
@ -156,6 +156,7 @@ impl TimerStruct {
/// Create a `TimerStruct` with the specified timeout /// Create a `TimerStruct` with the specified timeout
#[cfg(all(unix, not(target_os = "linux")))] #[cfg(all(unix, not(target_os = "linux")))]
#[must_use]
pub fn new(exec_tmout: Duration) -> Self { pub fn new(exec_tmout: Duration) -> Self {
let milli_sec = exec_tmout.as_millis(); let milli_sec = exec_tmout.as_millis();
let it_value = Timeval { let it_value = Timeval {
@ -264,11 +265,11 @@ impl TimerStruct {
/// Set timer /// Set timer
pub fn set_timer(&mut self) { pub fn set_timer(&mut self) {
unsafe { unsafe {
let data = &mut GLOBAL_STATE; let data = addr_of_mut!(GLOBAL_STATE);
write_volatile(&mut data.ptp_timer, Some(*self.ptp_timer())); write_volatile(addr_of_mut!((*data).ptp_timer), Some(*self.ptp_timer()));
write_volatile( write_volatile(
&mut data.critical, addr_of_mut!((*data).critical),
addr_of_mut!(*self.critical_mut()) as *mut c_void, addr_of_mut!(*self.critical_mut()) as *mut c_void,
); );
let tm: i64 = -self.milli_sec() * 10 * 1000; let tm: i64 = -self.milli_sec() * 10 * 1000;
@ -281,7 +282,7 @@ impl TimerStruct {
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
EnterCriticalSection(self.critical_mut()); EnterCriticalSection(self.critical_mut());
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
data.in_target = 1; (*data).in_target = 1;
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
LeaveCriticalSection(self.critical_mut()); LeaveCriticalSection(self.critical_mut());
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
@ -295,8 +296,11 @@ impl TimerStruct {
pub fn set_timer(&mut self) { pub fn set_timer(&mut self) {
unsafe { unsafe {
if self.batch_mode { if self.batch_mode {
let data = &mut GLOBAL_STATE; let data = addr_of_mut!(GLOBAL_STATE);
write_volatile(&mut data.executor_ptr, self as *mut _ as *mut c_void); write_volatile(
addr_of_mut!((*data).executor_ptr),
self as *mut _ as *mut c_void,
);
if self.executions == 0 { if self.executions == 0 {
libc::timer_settime(self.timerid, 0, addr_of_mut!(self.itimerspec), null_mut()); libc::timer_settime(self.timerid, 0, addr_of_mut!(self.itimerspec), null_mut());
@ -360,13 +364,13 @@ impl TimerStruct {
/// Disalarm /// Disalarm
pub fn unset_timer(&mut self) { pub fn unset_timer(&mut self) {
unsafe { unsafe {
let data = &mut GLOBAL_STATE; let data = addr_of_mut!(GLOBAL_STATE);
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
EnterCriticalSection(self.critical_mut()); EnterCriticalSection(self.critical_mut());
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
// Timeout handler will do nothing after we increment in_target value. // Timeout handler will do nothing after we increment in_target value.
data.in_target = 0; (*data).in_target = 0;
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
LeaveCriticalSection(self.critical_mut()); LeaveCriticalSection(self.critical_mut());
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);

View File

@ -2,7 +2,7 @@
#[cfg(unix)] #[cfg(unix)]
pub mod unix_signal_handler { pub mod unix_signal_handler {
use alloc::{boxed::Box, string::String, vec::Vec}; use alloc::{boxed::Box, string::String, vec::Vec};
use core::mem::transmute; use core::{mem::transmute, ptr::addr_of_mut};
use std::{io::Write, panic}; use std::{io::Write, panic};
use libafl_bolts::os::unix_signals::{ucontext_t, Handler, Signal}; use libafl_bolts::os::unix_signals::{ucontext_t, Handler, Signal};
@ -26,7 +26,7 @@ pub mod unix_signal_handler {
Signal, Signal,
&mut siginfo_t, &mut siginfo_t,
Option<&mut ucontext_t>, Option<&mut ucontext_t>,
data: &mut InProcessExecutorHandlerData, data: *mut InProcessExecutorHandlerData,
); );
/// A handler that does nothing. /// A handler that does nothing.
@ -47,23 +47,23 @@ pub mod unix_signal_handler {
context: Option<&mut ucontext_t>, context: Option<&mut ucontext_t>,
) { ) {
unsafe { unsafe {
let data = &mut GLOBAL_STATE; let data = addr_of_mut!(GLOBAL_STATE);
let in_handler = data.set_in_handler(true); let in_handler = (*data).set_in_handler(true);
match signal { match signal {
Signal::SigUser2 | Signal::SigAlarm => { Signal::SigUser2 | Signal::SigAlarm => {
if !data.timeout_handler.is_null() { if !(*data).timeout_handler.is_null() {
let func: HandlerFuncPtr = transmute(data.timeout_handler); let func: HandlerFuncPtr = transmute((*data).timeout_handler);
(func)(signal, info, context, data); (func)(signal, info, context, data);
} }
} }
_ => { _ => {
if !data.crash_handler.is_null() { if !(*data).crash_handler.is_null() {
let func: HandlerFuncPtr = transmute(data.crash_handler); let func: HandlerFuncPtr = transmute((*data).crash_handler);
(func)(signal, info, context, data); (func)(signal, info, context, data);
} }
} }
} }
data.set_in_handler(in_handler); (*data).set_in_handler(in_handler);
} }
} }
@ -82,17 +82,17 @@ pub mod unix_signal_handler {
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
{ {
let old_hook = panic::take_hook(); let old_hook = panic::take_hook();
panic::set_hook(Box::new(move |panic_info| { panic::set_hook(Box::new(move |panic_info| unsafe {
old_hook(panic_info); old_hook(panic_info);
let data = unsafe { &mut GLOBAL_STATE }; let data = addr_of_mut!(GLOBAL_STATE);
let in_handler = data.set_in_handler(true); let in_handler = (*data).set_in_handler(true);
if data.is_valid() { if (*data).is_valid() {
// We are fuzzing! // We are fuzzing!
let executor = data.executor_mut::<E>(); let executor = (*data).executor_mut::<E>();
let state = data.state_mut::<E::State>(); let state = (*data).state_mut::<E::State>();
let input = data.take_current_input::<<E::State as UsesInput>::Input>(); let input = (*data).take_current_input::<<E::State as UsesInput>::Input>();
let fuzzer = data.fuzzer_mut::<Z>(); let fuzzer = (*data).fuzzer_mut::<Z>();
let event_mgr = data.event_mgr_mut::<EM>(); let event_mgr = (*data).event_mgr_mut::<EM>();
run_observers_and_save_state::<E, EM, OF, Z>( run_observers_and_save_state::<E, EM, OF, Z>(
executor, executor,
@ -103,11 +103,9 @@ pub mod unix_signal_handler {
ExitKind::Crash, ExitKind::Crash,
); );
unsafe { libc::_exit(128 + 6); // SIGABRT exit code
libc::_exit(128 + 6);
} // SIGABRT exit code
} }
data.set_in_handler(in_handler); (*data).set_in_handler(in_handler);
})); }));
} }

View File

@ -2,7 +2,10 @@
#[cfg(all(windows, feature = "std"))] #[cfg(all(windows, feature = "std"))]
pub mod windows_asan_handler { pub mod windows_asan_handler {
use alloc::string::String; use alloc::string::String;
use core::sync::atomic::{compiler_fence, Ordering}; use core::{
ptr::addr_of_mut,
sync::atomic::{compiler_fence, Ordering},
};
use windows::Win32::System::Threading::{ use windows::Win32::System::Threading::{
EnterCriticalSection, LeaveCriticalSection, CRITICAL_SECTION, EnterCriticalSection, LeaveCriticalSection, CRITICAL_SECTION,
@ -30,26 +33,26 @@ pub mod windows_asan_handler {
E::State: HasExecutions + HasSolutions + HasCorpus, E::State: HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
{ {
let data = &mut GLOBAL_STATE; let data = addr_of_mut!(GLOBAL_STATE);
data.set_in_handler(true); (*data).set_in_handler(true);
// Have we set a timer_before? // Have we set a timer_before?
if data.ptp_timer.is_some() { if (*data).ptp_timer.is_some() {
/* /*
We want to prevent the timeout handler being run while the main thread is executing the crash handler We want to prevent the timeout handler being run while the main thread is executing the crash handler
Timeout handler runs if it has access to the critical section or data.in_target == 0 Timeout handler runs if it has access to the critical section or data.in_target == 0
Writing 0 to the data.in_target makes the timeout handler makes the timeout handler invalid. Writing 0 to the data.in_target makes the timeout handler makes the timeout handler invalid.
*/ */
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
EnterCriticalSection(data.critical as *mut CRITICAL_SECTION); EnterCriticalSection((*data).critical as *mut CRITICAL_SECTION);
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
data.in_target = 0; (*data).in_target = 0;
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
LeaveCriticalSection(data.critical as *mut CRITICAL_SECTION); LeaveCriticalSection((*data).critical as *mut CRITICAL_SECTION);
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
} }
log::error!("ASAN detected crash!"); log::error!("ASAN detected crash!");
if data.current_input_ptr.is_null() { if (*data).current_input_ptr.is_null() {
{ {
log::error!("Double crash\n"); log::error!("Double crash\n");
log::error!( log::error!(
@ -67,20 +70,20 @@ pub mod windows_asan_handler {
// TODO tell the parent to not restart // TODO tell the parent to not restart
} else { } else {
let executor = data.executor_mut::<E>(); let executor = (*data).executor_mut::<E>();
// reset timer // reset timer
if data.ptp_timer.is_some() { if (*data).ptp_timer.is_some() {
data.ptp_timer = None; (*data).ptp_timer = None;
} }
let state = data.state_mut::<E::State>(); let state = (*data).state_mut::<E::State>();
let fuzzer = data.fuzzer_mut::<Z>(); let fuzzer = (*data).fuzzer_mut::<Z>();
let event_mgr = data.event_mgr_mut::<EM>(); let event_mgr = (*data).event_mgr_mut::<EM>();
log::error!("Child crashed!"); log::error!("Child crashed!");
// Make sure we don't crash in the crash handler forever. // Make sure we don't crash in the crash handler forever.
let input = data.take_current_input::<<E::State as UsesInput>::Input>(); let input = (*data).take_current_input::<<E::State as UsesInput>::Input>();
run_observers_and_save_state::<E, EM, OF, Z>( run_observers_and_save_state::<E, EM, OF, Z>(
executor, executor,
@ -106,6 +109,7 @@ pub mod windows_exception_handler {
ffi::c_void, ffi::c_void,
mem::transmute, mem::transmute,
ptr, ptr,
ptr::addr_of_mut,
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{compiler_fence, Ordering},
}; };
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -132,7 +136,7 @@ pub mod windows_exception_handler {
}; };
pub(crate) type HandlerFuncPtr = pub(crate) type HandlerFuncPtr =
unsafe fn(*mut EXCEPTION_POINTERS, &mut InProcessExecutorHandlerData); unsafe fn(*mut EXCEPTION_POINTERS, *mut InProcessExecutorHandlerData);
/*pub unsafe fn nop_handler( /*pub unsafe fn nop_handler(
_code: ExceptionCode, _code: ExceptionCode,
@ -145,13 +149,13 @@ pub mod windows_exception_handler {
#[allow(clippy::not_unsafe_ptr_arg_deref)] #[allow(clippy::not_unsafe_ptr_arg_deref)]
fn handle(&mut self, _code: ExceptionCode, exception_pointers: *mut EXCEPTION_POINTERS) { fn handle(&mut self, _code: ExceptionCode, exception_pointers: *mut EXCEPTION_POINTERS) {
unsafe { unsafe {
let data = &mut GLOBAL_STATE; let data = addr_of_mut!(GLOBAL_STATE);
let in_handler = data.set_in_handler(true); let in_handler = (*data).set_in_handler(true);
if !data.crash_handler.is_null() { if !(*data).crash_handler.is_null() {
let func: HandlerFuncPtr = transmute(data.crash_handler); let func: HandlerFuncPtr = transmute((*data).crash_handler);
(func)(exception_pointers, data); (func)(exception_pointers, data);
} }
data.set_in_handler(in_handler); (*data).set_in_handler(in_handler);
} }
} }
@ -176,35 +180,33 @@ pub mod windows_exception_handler {
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
{ {
let old_hook = panic::take_hook(); let old_hook = panic::take_hook();
panic::set_hook(Box::new(move |panic_info| { panic::set_hook(Box::new(move |panic_info| unsafe {
let data = unsafe { &mut GLOBAL_STATE }; let data = addr_of_mut!(GLOBAL_STATE);
let in_handler = data.set_in_handler(true); let in_handler = (*data).set_in_handler(true);
// Have we set a timer_before? // Have we set a timer_before?
unsafe { if (*data).ptp_timer.is_some() {
if data.ptp_timer.is_some() { /*
/* We want to prevent the timeout handler being run while the main thread is executing the crash handler
We want to prevent the timeout handler being run while the main thread is executing the crash handler Timeout handler runs if it has access to the critical section or data.in_target == 0
Timeout handler runs if it has access to the critical section or data.in_target == 0 Writing 0 to the data.in_target makes the timeout handler makes the timeout handler invalid.
Writing 0 to the data.in_target makes the timeout handler makes the timeout handler invalid. */
*/ compiler_fence(Ordering::SeqCst);
compiler_fence(Ordering::SeqCst); EnterCriticalSection((*data).critical as *mut CRITICAL_SECTION);
EnterCriticalSection(data.critical as *mut CRITICAL_SECTION); compiler_fence(Ordering::SeqCst);
compiler_fence(Ordering::SeqCst); (*data).in_target = 0;
data.in_target = 0; compiler_fence(Ordering::SeqCst);
compiler_fence(Ordering::SeqCst); LeaveCriticalSection((*data).critical as *mut CRITICAL_SECTION);
LeaveCriticalSection(data.critical as *mut CRITICAL_SECTION); compiler_fence(Ordering::SeqCst);
compiler_fence(Ordering::SeqCst);
}
} }
if data.is_valid() { if (*data).is_valid() {
// We are fuzzing! // We are fuzzing!
let executor = data.executor_mut::<E>(); let executor = (*data).executor_mut::<E>();
let state = data.state_mut::<E::State>(); let state = (*data).state_mut::<E::State>();
let fuzzer = data.fuzzer_mut::<Z>(); let fuzzer = (*data).fuzzer_mut::<Z>();
let event_mgr = data.event_mgr_mut::<EM>(); let event_mgr = (*data).event_mgr_mut::<EM>();
let input = data.take_current_input::<<E::State as UsesInput>::Input>(); let input = (*data).take_current_input::<<E::State as UsesInput>::Input>();
run_observers_and_save_state::<E, EM, OF, Z>( run_observers_and_save_state::<E, EM, OF, Z>(
executor, executor,
@ -215,12 +217,10 @@ pub mod windows_exception_handler {
ExitKind::Crash, ExitKind::Crash,
); );
unsafe { ExitProcess(1);
ExitProcess(1);
}
} }
old_hook(panic_info); old_hook(panic_info);
data.set_in_handler(in_handler); (*data).set_in_handler(in_handler);
})); }));
} }

View File

@ -10,7 +10,7 @@ use core::{
ffi::c_void, ffi::c_void,
fmt::{self, Debug, Formatter}, fmt::{self, Debug, Formatter},
marker::PhantomData, marker::PhantomData,
ptr::{null, write_volatile}, ptr::{addr_of_mut, null, write_volatile},
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{compiler_fence, Ordering},
time::Duration, time::Duration,
}; };
@ -175,17 +175,29 @@ where
input: &<Self as UsesInput>::Input, input: &<Self as UsesInput>::Input,
) { ) {
unsafe { unsafe {
let data = &mut GLOBAL_STATE; let data = addr_of_mut!(GLOBAL_STATE);
write_volatile( write_volatile(
&mut data.current_input_ptr, addr_of_mut!((*data).current_input_ptr),
input as *const _ as *const c_void, input as *const _ as *const c_void,
); );
write_volatile(&mut data.executor_ptr, self as *const _ as *const c_void); write_volatile(
addr_of_mut!((*data).executor_ptr),
self as *const _ as *const c_void,
);
// Direct raw pointers access /aliasing is pretty undefined behavior. // Direct raw pointers access /aliasing is pretty undefined behavior.
// Since the state and event may have moved in memory, refresh them right before the signal may happen // Since the state and event may have moved in memory, refresh them right before the signal may happen
write_volatile(&mut data.state_ptr, state as *mut _ as *mut c_void); write_volatile(
write_volatile(&mut data.event_mgr_ptr, mgr as *mut _ as *mut c_void); addr_of_mut!((*data).state_ptr),
write_volatile(&mut data.fuzzer_ptr, fuzzer as *mut _ as *mut c_void); state as *mut _ as *mut c_void,
);
write_volatile(
addr_of_mut!((*data).event_mgr_ptr),
mgr as *mut _ as *mut c_void,
);
write_volatile(
addr_of_mut!((*data).fuzzer_ptr),
fuzzer as *mut _ as *mut c_void,
);
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
} }
} }
@ -200,9 +212,9 @@ where
_input: &<Self as UsesInput>::Input, _input: &<Self as UsesInput>::Input,
) { ) {
unsafe { unsafe {
let data = &mut GLOBAL_STATE; let data = addr_of_mut!(GLOBAL_STATE);
write_volatile(&mut data.current_input_ptr, null()); write_volatile(addr_of_mut!((*data).current_input_ptr), null());
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
} }
} }
@ -559,8 +571,11 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
// TODO remove this after executor refactor and libafl qemu new executor // TODO remove this after executor refactor and libafl qemu new executor
/// Expose a version of the crash handler that can be called from e.g. an emulator /// Expose a version of the crash handler that can be called from e.g. an emulator
///
/// # Safety
/// This will directly access `GLOBAL_STATE` and related data pointers
#[cfg(any(unix, feature = "std"))] #[cfg(any(unix, feature = "std"))]
pub fn generic_inproc_crash_handler<E, EM, OF, Z>() pub unsafe fn generic_inproc_crash_handler<E, EM, OF, Z>()
where where
E: Executor<EM, Z> + HasObservers, E: Executor<EM, Z> + HasObservers,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>, EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
@ -568,15 +583,15 @@ where
E::State: HasExecutions + HasSolutions + HasCorpus, E::State: HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
{ {
let data = unsafe { &mut GLOBAL_STATE }; let data = addr_of_mut!(GLOBAL_STATE);
let in_handler = data.set_in_handler(true); let in_handler = (*data).set_in_handler(true);
if data.is_valid() { if (*data).is_valid() {
let executor = data.executor_mut::<E>(); let executor = (*data).executor_mut::<E>();
let state = data.state_mut::<E::State>(); let state = (*data).state_mut::<E::State>();
let event_mgr = data.event_mgr_mut::<EM>(); let event_mgr = (*data).event_mgr_mut::<EM>();
let fuzzer = data.fuzzer_mut::<Z>(); let fuzzer = (*data).fuzzer_mut::<Z>();
let input = data.take_current_input::<<E::State as UsesInput>::Input>(); let input = (*data).take_current_input::<<E::State as UsesInput>::Input>();
run_observers_and_save_state::<E, EM, OF, Z>( run_observers_and_save_state::<E, EM, OF, Z>(
executor, executor,
@ -588,7 +603,7 @@ where
); );
} }
data.set_in_handler(in_handler); (*data).set_in_handler(in_handler);
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,11 +1,9 @@
//! The `GenericInProcessForkExecutor` to do forking before executing the harness in-processly //! The `GenericInProcessForkExecutor` to do forking before executing the harness in-processly
#[cfg(target_os = "linux")]
use core::ptr::addr_of_mut;
use core::{ use core::{
ffi::c_void, ffi::c_void,
fmt::{self, Debug, Formatter}, fmt::{self, Debug, Formatter},
marker::PhantomData, marker::PhantomData,
ptr::{null_mut, write_volatile}, ptr::{addr_of_mut, null_mut, write_volatile},
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{compiler_fence, Ordering},
time::Duration, time::Duration,
}; };
@ -42,7 +40,7 @@ pub(crate) type ForkHandlerFuncPtr = unsafe fn(
Signal, Signal,
&mut siginfo_t, &mut siginfo_t,
Option<&mut ucontext_t>, Option<&mut ucontext_t>,
data: &mut InProcessForkExecutorGlobalData, data: *mut InProcessForkExecutorGlobalData,
); );
#[cfg(all(unix, not(target_os = "linux")))] #[cfg(all(unix, not(target_os = "linux")))]
@ -277,13 +275,19 @@ where
input: &<Self as UsesInput>::Input, input: &<Self as UsesInput>::Input,
) { ) {
unsafe { unsafe {
let data = &mut FORK_EXECUTOR_GLOBAL_DATA; let data = addr_of_mut!(FORK_EXECUTOR_GLOBAL_DATA);
write_volatile(&mut data.executor_ptr, self as *const _ as *const c_void);
write_volatile( write_volatile(
&mut data.current_input_ptr, addr_of_mut!((*data).executor_ptr),
self as *const _ as *const c_void,
);
write_volatile(
addr_of_mut!((*data).current_input_ptr),
input as *const _ as *const c_void, input as *const _ as *const c_void,
); );
write_volatile(&mut data.state_ptr, state as *mut _ as *mut c_void); write_volatile(
addr_of_mut!((*data).state_ptr),
state as *mut _ as *mut c_void,
);
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
} }
} }
@ -440,6 +444,7 @@ where
pub mod child_signal_handlers { pub mod child_signal_handlers {
use alloc::boxed::Box; use alloc::boxed::Box;
use core::ptr::addr_of_mut;
use std::panic; use std::panic;
use libafl_bolts::os::unix_signals::{ucontext_t, Signal}; use libafl_bolts::os::unix_signals::{ucontext_t, Signal};
@ -460,21 +465,21 @@ pub mod child_signal_handlers {
E: HasObservers, E: HasObservers,
{ {
let old_hook = panic::take_hook(); let old_hook = panic::take_hook();
panic::set_hook(Box::new(move |panic_info| { panic::set_hook(Box::new(move |panic_info| unsafe {
old_hook(panic_info); old_hook(panic_info);
let data = unsafe { &mut FORK_EXECUTOR_GLOBAL_DATA }; let data = addr_of_mut!(FORK_EXECUTOR_GLOBAL_DATA);
if data.is_valid() { if !data.is_null() && (*data).is_valid() {
let executor = data.executor_mut::<E>(); let executor = (*data).executor_mut::<E>();
let observers = executor.observers_mut(); let observers = executor.observers_mut();
let state = data.state_mut::<E::State>(); let state = (*data).state_mut::<E::State>();
// Invalidate data to not execute again the observer hooks in the crash handler // Invalidate data to not execute again the observer hooks in the crash handler
let input = data.take_current_input::<<E::State as UsesInput>::Input>(); let input = (*data).take_current_input::<<E::State as UsesInput>::Input>();
observers observers
.post_exec_child_all(state, input, &ExitKind::Crash) .post_exec_child_all(state, input, &ExitKind::Crash)
.expect("Failed to run post_exec on observers"); .expect("Failed to run post_exec on observers");
// std::process::abort(); // std::process::abort();
unsafe { libc::_exit(128 + 6) }; // ABORT exit code libc::_exit(128 + 6); // ABORT exit code
} }
})); }));
} }

View File

@ -1384,7 +1384,10 @@ pub mod pybind {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use core::ptr::addr_of_mut;
use libafl_bolts::{ use libafl_bolts::{
ownedref::OwnedMutSlice,
tuples::{tuple_list, tuple_list_type}, tuples::{tuple_list, tuple_list_type},
Named, Named,
}; };
@ -1396,7 +1399,10 @@ mod tests {
#[test] #[test]
fn test_observer_serde() { fn test_observer_serde() {
let obv = tuple_list!(TimeObserver::new("time"), unsafe { let obv = tuple_list!(TimeObserver::new("time"), unsafe {
StdMapObserver::new("map", &mut MAP) StdMapObserver::from_ownedref(
"map",
OwnedMutSlice::from_raw_parts_mut(addr_of_mut!(MAP) as *mut u32, MAP.len()),
)
}); });
let vec = postcard::to_allocvec(&obv).unwrap(); let vec = postcard::to_allocvec(&obv).unwrap();
log::info!("{vec:?}"); log::info!("{vec:?}");

View File

@ -2267,9 +2267,7 @@ where
#[cfg(any(all(unix, not(miri)), all(windows, feature = "std")))] #[cfg(any(all(unix, not(miri)), all(windows, feature = "std")))]
fn setup_handlers() { fn setup_handlers() {
#[cfg(all(unix, not(miri)))] #[cfg(all(unix, not(miri)))]
if let Err(e) = if let Err(e) = unsafe { setup_signal_handler(ptr::addr_of_mut!(LLMP_SIGHANDLER_STATE)) } {
unsafe { setup_signal_handler(&mut *ptr::addr_of_mut!(LLMP_SIGHANDLER_STATE)) }
{
// We can live without a proper ctrl+c signal handler - Ignore. // We can live without a proper ctrl+c signal handler - Ignore.
log::info!("Failed to setup signal handlers: {e}"); log::info!("Failed to setup signal handlers: {e}");
} else { } else {

View File

@ -101,6 +101,7 @@ pub struct ucontext_t {
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))] #[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
#[derive(Debug)] #[derive(Debug)]
#[repr(C)] #[repr(C)]
#[allow(clippy::pub_underscore_fields)]
pub struct arm_exception_state64 { pub struct arm_exception_state64 {
/// Virtual Fault Address /// Virtual Fault Address
pub __far: u64, pub __far: u64,
@ -125,6 +126,7 @@ pub struct arm_exception_state64 {
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))] #[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
#[derive(Debug)] #[derive(Debug)]
#[repr(C)] #[repr(C)]
#[allow(clippy::pub_underscore_fields)]
pub struct arm_thread_state64 { pub struct arm_thread_state64 {
/// General purpose registers x0-x28 /// General purpose registers x0-x28
pub __x: [u64; 29], pub __x: [u64; 29],
@ -170,6 +172,7 @@ pub struct arm_neon_state64 {
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Debug)] #[derive(Debug)]
#[repr(C)] #[repr(C)]
#[allow(clippy::pub_underscore_fields)]
pub struct mcontext64 { pub struct mcontext64 {
/// _STRUCT_ARM_EXCEPTION_STATE64 /// _STRUCT_ARM_EXCEPTION_STATE64
pub __es: arm_exception_state64, pub __es: arm_exception_state64,
@ -427,9 +430,10 @@ unsafe fn handle_signal(sig: c_int, info: *mut siginfo_t, void: *mut c_void) {
/// # Safety /// # Safety
/// ///
/// The signal handlers will be called on any signal. They should (tm) be async safe. /// The signal handlers will be called on any signal. They should (tm) be async safe.
/// The handler pointer will be dereferenced, and the data the pointer points to may therefore not move.
/// A lot can go south in signal handling. Be sure you know what you are doing. /// A lot can go south in signal handling. Be sure you know what you are doing.
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub unsafe fn setup_signal_handler<T: 'static + Handler>(handler: &mut T) -> Result<(), Error> { pub unsafe fn setup_signal_handler<T: 'static + Handler>(handler: *mut T) -> Result<(), Error> {
// First, set up our own stack to be used during segfault handling. (and specify `SA_ONSTACK` in `sigaction`) // First, set up our own stack to be used during segfault handling. (and specify `SA_ONSTACK` in `sigaction`)
if SIGNAL_STACK_PTR.is_null() { if SIGNAL_STACK_PTR.is_null() {
SIGNAL_STACK_PTR = malloc(SIGNAL_STACK_SIZE); SIGNAL_STACK_PTR = malloc(SIGNAL_STACK_SIZE);
@ -450,10 +454,10 @@ pub unsafe fn setup_signal_handler<T: 'static + Handler>(handler: &mut T) -> Res
sigaddset(addr_of_mut!(sa.sa_mask), SIGALRM); sigaddset(addr_of_mut!(sa.sa_mask), SIGALRM);
sa.sa_flags = SA_NODEFER | SA_SIGINFO | SA_ONSTACK; sa.sa_flags = SA_NODEFER | SA_SIGINFO | SA_ONSTACK;
sa.sa_sigaction = handle_signal as usize; sa.sa_sigaction = handle_signal as usize;
let signals = handler.signals(); let signals = unsafe { (*handler).signals() };
for sig in signals { for sig in signals {
write_volatile( write_volatile(
&mut SIGNAL_HANDLERS[sig as usize], addr_of_mut!(SIGNAL_HANDLERS[sig as usize]),
Some(HandlerHolder { Some(HandlerHolder {
handler: UnsafeCell::new(handler as *mut dyn Handler), handler: UnsafeCell::new(handler as *mut dyn Handler),
}), }),

View File

@ -5,8 +5,7 @@ use alloc::vec::Vec;
use core::{ use core::{
cell::UnsafeCell, cell::UnsafeCell,
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
ptr, ptr::{self, addr_of_mut, write_volatile},
ptr::write_volatile,
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{compiler_fence, Ordering},
}; };
use std::os::raw::{c_long, c_void}; use std::os::raw::{c_long, c_void};
@ -384,8 +383,8 @@ unsafe extern "C" fn handle_signal(_signum: i32) {
/// # Safety /// # Safety
/// Exception handlers are usually ugly, handle with care! /// Exception handlers are usually ugly, handle with care!
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: &mut T) -> Result<(), Error> { pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: *mut T) -> Result<(), Error> {
let exceptions = handler.exceptions(); let exceptions = (*handler).exceptions();
let mut catch_assertions = false; let mut catch_assertions = false;
for exception_code in exceptions { for exception_code in exceptions {
if exception_code == ExceptionCode::AssertionFailure { if exception_code == ExceptionCode::AssertionFailure {
@ -396,7 +395,7 @@ pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: &mut T) ->
.position(|x| *x == exception_code) .position(|x| *x == exception_code)
.unwrap(); .unwrap();
write_volatile( write_volatile(
&mut EXCEPTION_HANDLERS[index], addr_of_mut!(EXCEPTION_HANDLERS[index]),
Some(HandlerHolder { Some(HandlerHolder {
handler: UnsafeCell::new(handler as *mut dyn Handler), handler: UnsafeCell::new(handler as *mut dyn Handler),
}), }),
@ -404,7 +403,7 @@ pub unsafe fn setup_exception_handler<T: 'static + Handler>(handler: &mut T) ->
} }
write_volatile( write_volatile(
&mut EXCEPTION_HANDLERS[EXCEPTION_HANDLERS_SIZE - 1], addr_of_mut!(EXCEPTION_HANDLERS[EXCEPTION_HANDLERS_SIZE - 1]),
Some(HandlerHolder { Some(HandlerHolder {
handler: UnsafeCell::new(handler as *mut dyn Handler), handler: UnsafeCell::new(handler as *mut dyn Handler),
}), }),
@ -442,7 +441,7 @@ pub(crate) unsafe fn setup_ctrl_handler<T: 'static + CtrlHandler>(
handler: *mut T, handler: *mut T,
) -> Result<(), Error> { ) -> Result<(), Error> {
write_volatile( write_volatile(
&mut CTRL_HANDLER, addr_of_mut!(CTRL_HANDLER),
Some(CtrlHandlerHolder { Some(CtrlHandlerHolder {
handler: UnsafeCell::new(handler as *mut dyn CtrlHandler), handler: UnsafeCell::new(handler as *mut dyn CtrlHandler),
}), }),

View File

@ -10,7 +10,12 @@ use core::{
fmt::{self, Debug, Formatter}, fmt::{self, Debug, Formatter},
ptr::addr_of_mut, ptr::addr_of_mut,
}; };
use std::{ffi::c_void, num::NonZeroUsize, ptr::write_volatile, rc::Rc}; use std::{
ffi::c_void,
num::NonZeroUsize,
ptr::{addr_of, write_volatile},
rc::Rc,
};
use backtrace::Backtrace; use backtrace::Backtrace;
use dynasmrt::{dynasm, DynasmApi, DynasmLabelApi}; use dynasmrt::{dynasm, DynasmApi, DynasmLabelApi};
@ -338,7 +343,7 @@ impl AsanRuntime {
/// Returns the `AsanErrors` from the recent run /// Returns the `AsanErrors` from the recent run
#[allow(clippy::unused_self)] #[allow(clippy::unused_self)]
pub fn errors(&mut self) -> &Option<AsanErrors> { pub fn errors(&mut self) -> &Option<AsanErrors> {
unsafe { &ASAN_ERRORS } unsafe { &*addr_of!(ASAN_ERRORS) }
} }
/// Make sure the specified memory is unpoisoned /// Make sure the specified memory is unpoisoned

View File

@ -578,9 +578,9 @@ impl Named for AsanErrorsObserver {
impl AsanErrorsObserver { impl AsanErrorsObserver {
/// Creates a new `AsanErrorsObserver`, pointing to a constant `AsanErrors` field /// Creates a new `AsanErrorsObserver`, pointing to a constant `AsanErrors` field
#[must_use] #[must_use]
pub fn new(errors: &'static Option<AsanErrors>) -> Self { pub fn new(errors: *const Option<AsanErrors>) -> Self {
Self { Self {
errors: OwnedPtr::Ptr(errors as *const Option<AsanErrors>), errors: OwnedPtr::Ptr(errors),
} }
} }

View File

@ -346,7 +346,7 @@ impl Default for FridaOptions {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::OnceLock; use std::{ptr::addr_of, sync::OnceLock};
use clap::Parser; use clap::Parser;
use frida_gum::Gum; use frida_gum::Gum;
@ -438,7 +438,7 @@ mod tests {
let mut fuzzer = StdFuzzer::new(StdScheduler::new(), feedback, objective); let mut fuzzer = StdFuzzer::new(StdScheduler::new(), feedback, objective);
let observers = tuple_list!( let observers = tuple_list!(
AsanErrorsObserver::new(&ASAN_ERRORS) //, AsanErrorsObserver::new(addr_of!(ASAN_ERRORS)) //,
); );
{ {

View File

@ -4,7 +4,7 @@ use std::{
fs::{rename, File}, fs::{rename, File},
io::Write, io::Write,
os::fd::{AsRawFd, FromRawFd}, os::fd::{AsRawFd, FromRawFd},
time::{SystemTime, UNIX_EPOCH}, time::{SystemTime, UNIX_EPOCH}, ptr::addr_of_mut,
}; };
use libafl::{ use libafl::{
@ -97,7 +97,7 @@ pub fn merge(
} }
} }
let edges = unsafe { core::mem::take(&mut COUNTERS_MAPS) }; let edges = unsafe { core::mem::take(&mut *addr_of_mut!(COUNTERS_MAPS)) };
let edges_observer = MultiMapObserver::new("edges", edges); let edges_observer = MultiMapObserver::new("edges", edges);
let time = TimeObserver::new("time"); let time = TimeObserver::new("time");

View File

@ -49,12 +49,12 @@ macro_rules! extern_c_checked {
paste! { paste! {
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[allow(unused)] #[allow(unused)]
struct [<__ $c_var:upper _STRUCT__>] { member: &'static $c_var_ty } struct [<__ $c_var:upper _STRUCT__>] { member: *const $c_var_ty }
unsafe impl Sync for [<__ $c_var:upper _STRUCT__>] {} unsafe impl Sync for [<__ $c_var:upper _STRUCT__>] {}
#[cfg_attr(nightly, used(linker))] #[cfg_attr(nightly, used(linker))]
static [<__ $c_var:upper __>]: [<__ $c_var:upper _STRUCT__>] = unsafe { [<__ $c_var:upper _STRUCT__>] { member: &$c_var } }; static [<__ $c_var:upper __>]: [<__ $c_var:upper _STRUCT__>] = unsafe { [<__ $c_var:upper _STRUCT__>] { member: core::ptr::addr_of!($c_var) } };
} }
extern "C" { extern "C" {
@ -68,12 +68,12 @@ macro_rules! extern_c_checked {
paste! { paste! {
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[allow(unused)] #[allow(unused)]
struct [<__ $c_var:upper _STRUCT__>] { member: &'static $c_var_ty } struct [<__ $c_var:upper _STRUCT__>] { member: *const $c_var_ty }
unsafe impl Sync for [<__ $c_var:upper _STRUCT__>] {} unsafe impl Sync for [<__ $c_var:upper _STRUCT__>] {}
#[cfg_attr(nightly, used(linker))] #[cfg_attr(nightly, used(linker))]
static mut [<__ $c_var:upper __>]: [<__ $c_var:upper _STRUCT__>] = unsafe { [<__ $c_var:upper _STRUCT__>] { member: &$c_var } }; static mut [<__ $c_var:upper __>]: [<__ $c_var:upper _STRUCT__>] = unsafe { [<__ $c_var:upper _STRUCT__>] { member: core::ptr::addr_of!($c_var) } };
} }
extern "C" { extern "C" {

View File

@ -5,6 +5,8 @@ use core::{
time::Duration, time::Duration,
}; };
#[cfg(feature = "fork")]
use libafl::inputs::UsesInput;
#[cfg(feature = "fork")] #[cfg(feature = "fork")]
use libafl::{ use libafl::{
events::EventManager, events::EventManager,
@ -14,13 +16,12 @@ use libafl::{
use libafl::{ use libafl::{
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
hooks::{inprocess::InProcessExecutorHandlerData, ExecutorHooksTuple}, hooks::inprocess::InProcessExecutorHandlerData,
inprocess::{HasInProcessHooks, InProcessExecutor}, inprocess::{HasInProcessHooks, InProcessExecutor},
Executor, ExitKind, HasObservers, Executor, ExitKind, HasObservers,
}, },
feedbacks::Feedback, feedbacks::Feedback,
fuzzer::HasObjective, fuzzer::HasObjective,
inputs::UsesInput,
observers::{ObserversTuple, UsesObservers}, observers::{ObserversTuple, UsesObservers},
state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState}, state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState},
Error, Error,
@ -147,12 +148,14 @@ where
let handler = |hooks: &mut QemuHooks<QT, S>, host_sig| { let handler = |hooks: &mut QemuHooks<QT, S>, host_sig| {
eprintln!("Crashed with signal {host_sig}"); eprintln!("Crashed with signal {host_sig}");
libafl::executors::inprocess::generic_inproc_crash_handler::< unsafe {
InProcessExecutor<'a, H, OT, S>, libafl::executors::inprocess::generic_inproc_crash_handler::<
EM, InProcessExecutor<'a, H, OT, S>,
OF, EM,
Z, OF,
>(); Z,
>();
}
if let Some(cpu) = hooks.emulator().current_cpu() { if let Some(cpu) = hooks.emulator().current_cpu() {
eprint!("Context:\n{}", cpu.display_context()); eprint!("Context:\n{}", cpu.display_context());
} }

View File

@ -6,7 +6,7 @@ use core::{
fmt::{self, Debug, Formatter}, fmt::{self, Debug, Formatter},
marker::PhantomData, marker::PhantomData,
mem::transmute, mem::transmute,
ptr::{self, addr_of}, ptr::{self, addr_of, addr_of_mut},
}; };
use libafl::{executors::hooks::inprocess::inprocess_get_state, inputs::UsesInput}; use libafl::{executors::hooks::inprocess::inprocess_get_state, inputs::UsesInput};
@ -317,7 +317,7 @@ where
{ {
unsafe { unsafe {
let hooks = get_qemu_hooks::<QT, S>(); let hooks = get_qemu_hooks::<QT, S>();
for hook in &mut CRASH_HOOKS { for hook in &mut (*addr_of_mut!(CRASH_HOOKS)) {
match hook { match hook {
HookRepr::Function(ptr) => { HookRepr::Function(ptr) => {
let func: fn(&mut QemuHooks<QT, S>, i32) = transmute(*ptr); let func: fn(&mut QemuHooks<QT, S>, i32) = transmute(*ptr);
@ -334,7 +334,6 @@ where
} }
static mut HOOKS_IS_INITIALIZED: bool = false; static mut HOOKS_IS_INITIALIZED: bool = false;
static mut FIRST_EXEC: bool = true;
pub struct QemuHooks<QT, S> pub struct QemuHooks<QT, S>
where where
@ -461,7 +460,7 @@ where
let fat: FatPtr = transmute(hook); let fat: FatPtr = transmute(hook);
GENERIC_HOOKS.push((HookId(0), fat)); GENERIC_HOOKS.push((HookId(0), fat));
let id = self.emulator.set_hook( let id = self.emulator.set_hook(
&mut GENERIC_HOOKS.last_mut().unwrap().1, &mut ((*addr_of_mut!(GENERIC_HOOKS)).last_mut().unwrap().1),
addr, addr,
closure_generic_hook_wrapper::<QT, S>, closure_generic_hook_wrapper::<QT, S>,
invalidate_block, invalidate_block,
@ -662,6 +661,7 @@ where
} }
} }
#[allow(clippy::similar_names)]
pub fn writes( pub fn writes(
&self, &self,
generation_hook: Hook< generation_hook: Hook<
@ -728,7 +728,6 @@ where
write_3_exec_hook_wrapper::<QT, S>, write_3_exec_hook_wrapper::<QT, S>,
extern "C" fn(&mut HookState<5>, id: u64, addr: GuestAddr) extern "C" fn(&mut HookState<5>, id: u64, addr: GuestAddr)
); );
#[allow(clippy::similar_names)]
let execn = get_raw_hook!( let execn = get_raw_hook!(
execution_hook_n, execution_hook_n,
write_4_exec_hook_wrapper::<QT, S>, write_4_exec_hook_wrapper::<QT, S>,
@ -874,7 +873,7 @@ where
let fat: FatPtr = transmute(hook); let fat: FatPtr = transmute(hook);
BACKDOOR_HOOKS.push((HookId(0), fat)); BACKDOOR_HOOKS.push((HookId(0), fat));
let id = self.emulator.add_backdoor_hook( let id = self.emulator.add_backdoor_hook(
&mut BACKDOOR_HOOKS.last_mut().unwrap().1, &mut ((*addr_of_mut!(BACKDOOR_HOOKS)).last_mut().unwrap().1),
closure_backdoor_hook_wrapper::<QT, S>, closure_backdoor_hook_wrapper::<QT, S>,
); );
BACKDOOR_HOOKS.last_mut().unwrap().0 = id; BACKDOOR_HOOKS.last_mut().unwrap().0 = id;
@ -988,7 +987,7 @@ where
let fat: FatPtr = transmute(hook); let fat: FatPtr = transmute(hook);
PRE_SYSCALL_HOOKS.push((HookId(0), fat)); PRE_SYSCALL_HOOKS.push((HookId(0), fat));
let id = self.emulator.add_pre_syscall_hook( let id = self.emulator.add_pre_syscall_hook(
&mut PRE_SYSCALL_HOOKS.last_mut().unwrap().1, &mut ((*addr_of_mut!(PRE_SYSCALL_HOOKS)).last_mut().unwrap().1),
closure_pre_syscall_hook_wrapper::<QT, S>, closure_pre_syscall_hook_wrapper::<QT, S>,
); );
PRE_SYSCALL_HOOKS.last_mut().unwrap().0 = id; PRE_SYSCALL_HOOKS.last_mut().unwrap().0 = id;
@ -1107,7 +1106,7 @@ where
let fat: FatPtr = transmute(hook); let fat: FatPtr = transmute(hook);
POST_SYSCALL_HOOKS.push((HookId(0), fat)); POST_SYSCALL_HOOKS.push((HookId(0), fat));
let id = self.emulator.add_post_syscall_hook( let id = self.emulator.add_post_syscall_hook(
&mut POST_SYSCALL_HOOKS.last_mut().unwrap().1, &mut ((*addr_of_mut!(POST_SYSCALL_HOOKS)).last_mut().unwrap().1),
closure_post_syscall_hook_wrapper::<QT, S>, closure_post_syscall_hook_wrapper::<QT, S>,
); );
POST_SYSCALL_HOOKS.last_mut().unwrap().0 = id; POST_SYSCALL_HOOKS.last_mut().unwrap().0 = id;
@ -1155,7 +1154,7 @@ where
let fat: FatPtr = transmute(hook); let fat: FatPtr = transmute(hook);
NEW_THREAD_HOOKS.push((HookId(0), fat)); NEW_THREAD_HOOKS.push((HookId(0), fat));
let id = self.emulator.add_new_thread_hook( let id = self.emulator.add_new_thread_hook(
&mut NEW_THREAD_HOOKS.last_mut().unwrap().1, &mut (*addr_of_mut!(NEW_THREAD_HOOKS)).last_mut().unwrap().1,
closure_new_thread_hook_wrapper::<QT, S>, closure_new_thread_hook_wrapper::<QT, S>,
); );
NEW_THREAD_HOOKS.last_mut().unwrap().0 = id; NEW_THREAD_HOOKS.last_mut().unwrap().0 = id;

View File

@ -7,6 +7,7 @@ fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap(); let out_dir = env::var_os("OUT_DIR").unwrap();
let out_dir = out_dir.to_string_lossy().to_string(); let out_dir = out_dir.to_string_lossy().to_string();
//let out_dir_path = Path::new(&out_dir); //let out_dir_path = Path::new(&out_dir);
#[allow(unused_variables)]
let src_dir = Path::new("src"); let src_dir = Path::new("src");
let dest_path = Path::new(&out_dir).join("constants.rs"); let dest_path = Path::new(&out_dir).join("constants.rs");

View File

@ -1,5 +1,6 @@
//! [`LLVM` `8-bit-counters`](https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards) runtime for `LibAFL`. //! [`LLVM` `8-bit-counters`](https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards) runtime for `LibAFL`.
use alloc::vec::Vec; use alloc::vec::Vec;
use core::ptr::addr_of_mut;
use libafl_bolts::{ownedref::OwnedMutSlice, AsMutSlice, AsSlice}; use libafl_bolts::{ownedref::OwnedMutSlice, AsMutSlice, AsSlice};
@ -30,7 +31,7 @@ pub unsafe fn extra_counters() -> Vec<OwnedMutSlice<'static, u8>> {
#[allow(clippy::not_unsafe_ptr_arg_deref)] #[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop: *mut u8) { pub extern "C" fn __sanitizer_cov_8bit_counters_init(start: *mut u8, stop: *mut u8) {
unsafe { unsafe {
for existing in &mut COUNTERS_MAPS { for existing in &mut *addr_of_mut!(COUNTERS_MAPS) {
let range = existing.as_mut_slice().as_mut_ptr() let range = existing.as_mut_slice().as_mut_ptr()
..=existing ..=existing
.as_mut_slice() .as_mut_slice()
@ -66,6 +67,7 @@ mod observers {
fmt::Debug, fmt::Debug,
hash::{BuildHasher, Hasher}, hash::{BuildHasher, Hasher},
iter::Flatten, iter::Flatten,
ptr::{addr_of, addr_of_mut},
slice::{from_raw_parts, Iter, IterMut}, slice::{from_raw_parts, Iter, IterMut},
}; };
@ -165,7 +167,7 @@ mod observers {
let elem = self.intervals.query(idx..=idx).next().unwrap(); let elem = self.intervals.query(idx..=idx).next().unwrap();
let i = elem.value; let i = elem.value;
let j = idx - elem.interval.start; let j = idx - elem.interval.start;
unsafe { &COUNTERS_MAPS[*i].as_slice()[j] } unsafe { &(*addr_of!(COUNTERS_MAPS[*i])).as_slice()[j] }
} }
#[inline] #[inline]
@ -173,7 +175,7 @@ mod observers {
let elem = self.intervals.query_mut(idx..=idx).next().unwrap(); let elem = self.intervals.query_mut(idx..=idx).next().unwrap();
let i = elem.value; let i = elem.value;
let j = idx - elem.interval.start; let j = idx - elem.interval.start;
unsafe { &mut COUNTERS_MAPS[*i].as_mut_slice()[j] } unsafe { &mut (*addr_of_mut!(COUNTERS_MAPS[*i])).as_mut_slice()[j] }
} }
#[inline] #[inline]
@ -184,7 +186,7 @@ mod observers {
fn count_bytes(&self) -> u64 { fn count_bytes(&self) -> u64 {
let initial = self.initial(); let initial = self.initial();
let mut res = 0; let mut res = 0;
for map in unsafe { &COUNTERS_MAPS } { for map in unsafe { &*addr_of!(COUNTERS_MAPS) } {
for x in map.as_slice() { for x in map.as_slice() {
if *x != initial { if *x != initial {
res += 1; res += 1;
@ -196,7 +198,7 @@ mod observers {
fn hash(&self) -> u64 { fn hash(&self) -> u64 {
let mut hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher(); let mut hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher();
for map in unsafe { &COUNTERS_MAPS } { for map in unsafe { &*addr_of!(COUNTERS_MAPS) } {
let slice = map.as_slice(); let slice = map.as_slice();
let ptr = slice.as_ptr(); let ptr = slice.as_ptr();
let map_size = slice.len() / core::mem::size_of::<u8>(); let map_size = slice.len() / core::mem::size_of::<u8>();
@ -209,7 +211,7 @@ mod observers {
fn reset_map(&mut self) -> Result<(), Error> { fn reset_map(&mut self) -> Result<(), Error> {
let initial = self.initial(); let initial = self.initial();
for map in unsafe { &mut COUNTERS_MAPS } { for map in unsafe { &mut *addr_of_mut!(COUNTERS_MAPS) } {
for x in map.as_mut_slice() { for x in map.as_mut_slice() {
*x = initial; *x = initial;
} }
@ -250,7 +252,7 @@ mod observers {
fn maybe_differential(name: &'static str) -> Self { fn maybe_differential(name: &'static str) -> Self {
let mut idx = 0; let mut idx = 0;
let mut intervals = IntervalTree::new(); let mut intervals = IntervalTree::new();
for (v, x) in unsafe { &COUNTERS_MAPS }.iter().enumerate() { for (v, x) in unsafe { &*addr_of!(COUNTERS_MAPS) }.iter().enumerate() {
let l = x.as_slice().len(); let l = x.as_slice().len();
intervals.insert(idx..(idx + l), v); intervals.insert(idx..(idx + l), v);
idx += l; idx += l;
@ -286,12 +288,14 @@ mod observers {
let mut idx = 0; let mut idx = 0;
let mut v = 0; let mut v = 0;
let mut intervals = IntervalTree::new(); let mut intervals = IntervalTree::new();
unsafe { &mut COUNTERS_MAPS }.iter_mut().for_each(|m| { unsafe { &mut *addr_of_mut!(COUNTERS_MAPS) }
let l = m.as_mut_slice().len(); .iter_mut()
intervals.insert(idx..(idx + l), v); .for_each(|m| {
idx += l; let l = m.as_mut_slice().len();
v += 1; intervals.insert(idx..(idx + l), v);
}); idx += l;
v += 1;
});
Self { Self {
intervals, intervals,
len: idx, len: idx,
@ -325,7 +329,7 @@ mod observers {
type IntoIter = Flatten<Iter<'it, OwnedMutSlice<'static, u8>>>; type IntoIter = Flatten<Iter<'it, OwnedMutSlice<'static, u8>>>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
unsafe { &COUNTERS_MAPS }.iter().flatten() unsafe { &*addr_of!(COUNTERS_MAPS) }.iter().flatten()
} }
} }
@ -336,7 +340,9 @@ mod observers {
type IntoIter = Flatten<IterMut<'it, OwnedMutSlice<'static, u8>>>; type IntoIter = Flatten<IterMut<'it, OwnedMutSlice<'static, u8>>>;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
unsafe { &mut COUNTERS_MAPS }.iter_mut().flatten() unsafe { &mut *addr_of_mut!(COUNTERS_MAPS) }
.iter_mut()
.flatten()
} }
} }