Call the original QEMU user crash handler in libafl_qemu (#1575)
* Call the original QEMU user crash handler in libafl_qemu * Return if real crash or not * merge * Fix singal handlers in libafl and libafl_qemu * doc and clippy * clippy * clippy * clippy * slirp * fix * fix system
This commit is contained in:
parent
d4e9107fc2
commit
cffbf069d2
@ -68,7 +68,7 @@ pub struct ShutdownSignalData {
|
|||||||
/// Type for shutdown handler
|
/// Type for shutdown handler
|
||||||
#[cfg(all(unix, feature = "std"))]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
pub type ShutdownFuncPtr =
|
pub type ShutdownFuncPtr =
|
||||||
unsafe fn(Signal, siginfo_t, &mut ucontext_t, data: &mut ShutdownSignalData);
|
unsafe fn(Signal, &mut siginfo_t, &mut ucontext_t, data: &mut ShutdownSignalData);
|
||||||
|
|
||||||
/// Shutdown handler. `SigTerm`, `SigInterrupt`, `SigQuit` call this
|
/// Shutdown handler. `SigTerm`, `SigInterrupt`, `SigQuit` call this
|
||||||
/// We can't handle SIGKILL in the signal handler, this means that you shouldn't kill your fuzzer with `kill -9` because then the shmem segments are never freed
|
/// We can't handle SIGKILL in the signal handler, this means that you shouldn't kill your fuzzer with `kill -9` because then the shmem segments are never freed
|
||||||
@ -79,7 +79,7 @@ pub type ShutdownFuncPtr =
|
|||||||
#[cfg(all(unix, feature = "std"))]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
pub unsafe fn shutdown_handler<SP>(
|
pub unsafe fn shutdown_handler<SP>(
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
_info: siginfo_t,
|
_info: &mut siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: &mut ucontext_t,
|
||||||
data: &ShutdownSignalData,
|
data: &ShutdownSignalData,
|
||||||
) where
|
) where
|
||||||
@ -106,7 +106,7 @@ pub unsafe fn shutdown_handler<SP>(
|
|||||||
|
|
||||||
#[cfg(all(unix, feature = "std"))]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
impl Handler for ShutdownSignalData {
|
impl Handler for ShutdownSignalData {
|
||||||
fn handle(&mut self, signal: Signal, info: siginfo_t, context: &mut ucontext_t) {
|
fn handle(&mut self, signal: Signal, info: &mut siginfo_t, context: &mut ucontext_t) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = &mut SHUTDOWN_SIGHANDLER_DATA;
|
let data = &mut SHUTDOWN_SIGHANDLER_DATA;
|
||||||
if !data.shutdown_handler.is_null() {
|
if !data.shutdown_handler.is_null() {
|
||||||
|
@ -418,13 +418,13 @@ impl InProcessHandlers {
|
|||||||
|
|
||||||
/// The global state of the in-process harness.
|
/// The global state of the in-process harness.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct InProcessExecutorHandlerData {
|
pub struct InProcessExecutorHandlerData {
|
||||||
state_ptr: *mut c_void,
|
state_ptr: *mut c_void,
|
||||||
event_mgr_ptr: *mut c_void,
|
event_mgr_ptr: *mut c_void,
|
||||||
fuzzer_ptr: *mut c_void,
|
fuzzer_ptr: *mut c_void,
|
||||||
executor_ptr: *const c_void,
|
executor_ptr: *const c_void,
|
||||||
pub current_input_ptr: *const c_void,
|
pub(crate) current_input_ptr: *const c_void,
|
||||||
pub in_handler: bool,
|
pub(crate) in_handler: bool,
|
||||||
|
|
||||||
/// The timeout handler
|
/// The timeout handler
|
||||||
#[cfg(any(unix, feature = "std"))]
|
#[cfg(any(unix, feature = "std"))]
|
||||||
@ -478,7 +478,7 @@ impl InProcessExecutorHandlerData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(unix, feature = "std"))]
|
#[cfg(any(unix, feature = "std"))]
|
||||||
pub fn is_valid(&self) -> bool {
|
pub(crate) fn is_valid(&self) -> bool {
|
||||||
!self.current_input_ptr.is_null()
|
!self.current_input_ptr.is_null()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,8 +631,9 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
|
|||||||
log::info!("Bye!");
|
log::info!("Bye!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The inprocess executor singal handling code for unix
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
mod unix_signal_handler {
|
pub mod unix_signal_handler {
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use alloc::{boxed::Box, string::String};
|
use alloc::{boxed::Box, string::String};
|
||||||
@ -658,12 +659,12 @@ mod unix_signal_handler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) type HandlerFuncPtr =
|
pub(crate) type HandlerFuncPtr =
|
||||||
unsafe fn(Signal, siginfo_t, &mut ucontext_t, data: &mut InProcessExecutorHandlerData);
|
unsafe fn(Signal, &mut siginfo_t, &mut ucontext_t, data: &mut InProcessExecutorHandlerData);
|
||||||
|
|
||||||
/// A handler that does nothing.
|
/// A handler that does nothing.
|
||||||
/*pub fn nop_handler(
|
/*pub fn nop_handler(
|
||||||
_signal: Signal,
|
_signal: Signal,
|
||||||
_info: siginfo_t,
|
_info: &mut siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: &mut ucontext_t,
|
||||||
_data: &mut InProcessExecutorHandlerData,
|
_data: &mut InProcessExecutorHandlerData,
|
||||||
) {
|
) {
|
||||||
@ -671,7 +672,7 @@ mod unix_signal_handler {
|
|||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
impl Handler for InProcessExecutorHandlerData {
|
impl Handler for InProcessExecutorHandlerData {
|
||||||
fn handle(&mut self, signal: Signal, info: siginfo_t, context: &mut ucontext_t) {
|
fn handle(&mut self, signal: Signal, info: &mut siginfo_t, context: &mut ucontext_t) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = &mut GLOBAL_STATE;
|
let data = &mut GLOBAL_STATE;
|
||||||
let in_handler = data.set_in_handler(true);
|
let in_handler = data.set_in_handler(true);
|
||||||
@ -748,10 +749,15 @@ mod unix_signal_handler {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Timeout-Handler for in-process fuzzing.
|
||||||
|
/// It will store the current State to shmem, then exit.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// Well, signal handling is not safe
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub(crate) unsafe fn inproc_timeout_handler<E, EM, OF, Z>(
|
pub unsafe fn inproc_timeout_handler<E, EM, OF, Z>(
|
||||||
_signal: Signal,
|
_signal: Signal,
|
||||||
_info: siginfo_t,
|
_info: &mut siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: &mut ucontext_t,
|
||||||
data: &mut InProcessExecutorHandlerData,
|
data: &mut InProcessExecutorHandlerData,
|
||||||
) where
|
) where
|
||||||
@ -795,10 +801,13 @@ mod unix_signal_handler {
|
|||||||
/// Crash-Handler for in-process fuzzing.
|
/// Crash-Handler for in-process fuzzing.
|
||||||
/// Will be used for signal handling.
|
/// Will be used for signal handling.
|
||||||
/// It will store the current State to shmem, then exit.
|
/// It will store the current State to shmem, then exit.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// Well, signal handling is not safe
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
pub(crate) unsafe fn inproc_crash_handler<E, EM, OF, Z>(
|
pub unsafe fn inproc_crash_handler<E, EM, OF, Z>(
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
_info: siginfo_t,
|
_info: &mut siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: &mut ucontext_t,
|
||||||
data: &mut InProcessExecutorHandlerData,
|
data: &mut InProcessExecutorHandlerData,
|
||||||
) where
|
) where
|
||||||
@ -991,7 +1000,7 @@ pub mod windows_asan_handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(windows, feature = "std"))]
|
#[cfg(all(windows, feature = "std"))]
|
||||||
mod windows_exception_handler {
|
pub mod windows_exception_handler {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::{string::String, vec::Vec};
|
use alloc::{string::String, vec::Vec};
|
||||||
@ -1058,6 +1067,9 @@ mod windows_exception_handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// invokes the `post_exec` hook on all observer in case of panic
|
/// invokes the `post_exec` hook on all observer in case of panic
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// Well, exception handling is not safe
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn setup_panic_hook<E, EM, OF, Z>()
|
pub fn setup_panic_hook<E, EM, OF, Z>()
|
||||||
where
|
where
|
||||||
@ -1117,6 +1129,9 @@ mod windows_exception_handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Timeout handler for windows
|
/// Timeout handler for windows
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// Well, exception handling is not safe
|
||||||
pub unsafe extern "system" fn inproc_timeout_handler<E, EM, OF, Z>(
|
pub unsafe extern "system" fn inproc_timeout_handler<E, EM, OF, Z>(
|
||||||
_p0: *mut u8,
|
_p0: *mut u8,
|
||||||
global_state: *mut c_void,
|
global_state: *mut c_void,
|
||||||
@ -1180,8 +1195,12 @@ mod windows_exception_handler {
|
|||||||
// log::info!("TIMER INVOKED!");
|
// log::info!("TIMER INVOKED!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Crash handler for windows
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// Well, exception handling is not safe
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
pub(crate) unsafe fn inproc_crash_handler<E, EM, OF, Z>(
|
pub unsafe fn inproc_crash_handler<E, EM, OF, Z>(
|
||||||
exception_pointers: *mut EXCEPTION_POINTERS,
|
exception_pointers: *mut EXCEPTION_POINTERS,
|
||||||
data: &mut InProcessExecutorHandlerData,
|
data: &mut InProcessExecutorHandlerData,
|
||||||
) where
|
) where
|
||||||
@ -1303,7 +1322,7 @@ mod windows_exception_handler {
|
|||||||
/// The signature of the crash handler function
|
/// The signature of the crash handler function
|
||||||
#[cfg(all(feature = "std", unix))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
pub(crate) type ForkHandlerFuncPtr =
|
pub(crate) type ForkHandlerFuncPtr =
|
||||||
unsafe fn(Signal, siginfo_t, &mut ucontext_t, data: &mut InProcessForkExecutorGlobalData);
|
unsafe fn(Signal, &mut siginfo_t, &mut ucontext_t, data: &mut InProcessForkExecutorGlobalData);
|
||||||
|
|
||||||
/// The inmem fork executor's handlers.
|
/// The inmem fork executor's handlers.
|
||||||
#[cfg(all(feature = "std", unix))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
@ -1443,7 +1462,7 @@ pub(crate) static mut FORK_EXECUTOR_GLOBAL_DATA: InProcessForkExecutorGlobalData
|
|||||||
|
|
||||||
#[cfg(all(feature = "std", unix))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
impl Handler for InProcessForkExecutorGlobalData {
|
impl Handler for InProcessForkExecutorGlobalData {
|
||||||
fn handle(&mut self, signal: Signal, info: siginfo_t, context: &mut ucontext_t) {
|
fn handle(&mut self, signal: Signal, info: &mut siginfo_t, context: &mut ucontext_t) {
|
||||||
match signal {
|
match signal {
|
||||||
Signal::SigUser2 | Signal::SigAlarm => unsafe {
|
Signal::SigUser2 | Signal::SigAlarm => unsafe {
|
||||||
if !FORK_EXECUTOR_GLOBAL_DATA.timeout_handler.is_null() {
|
if !FORK_EXECUTOR_GLOBAL_DATA.timeout_handler.is_null() {
|
||||||
@ -2052,7 +2071,7 @@ pub mod child_signal_handlers {
|
|||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub(crate) unsafe fn child_crash_handler<E>(
|
pub(crate) unsafe fn child_crash_handler<E>(
|
||||||
_signal: Signal,
|
_signal: Signal,
|
||||||
_info: siginfo_t,
|
_info: &mut siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: &mut ucontext_t,
|
||||||
data: &mut InProcessForkExecutorGlobalData,
|
data: &mut InProcessForkExecutorGlobalData,
|
||||||
) where
|
) where
|
||||||
@ -2074,7 +2093,7 @@ pub mod child_signal_handlers {
|
|||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub(crate) unsafe fn child_timeout_handler<E>(
|
pub(crate) unsafe fn child_timeout_handler<E>(
|
||||||
_signal: Signal,
|
_signal: Signal,
|
||||||
_info: siginfo_t,
|
_info: &mut siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: &mut ucontext_t,
|
||||||
data: &mut InProcessForkExecutorGlobalData,
|
data: &mut InProcessForkExecutorGlobalData,
|
||||||
) where
|
) where
|
||||||
|
@ -1939,7 +1939,7 @@ pub struct LlmpShutdownSignalHandler {
|
|||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
impl Handler for LlmpShutdownSignalHandler {
|
impl Handler for LlmpShutdownSignalHandler {
|
||||||
fn handle(&mut self, _signal: Signal, _info: siginfo_t, _context: &mut ucontext_t) {
|
fn handle(&mut self, _signal: Signal, _info: &mut siginfo_t, _context: &mut ucontext_t) {
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::write_volatile(&mut self.shutting_down, true);
|
ptr::write_volatile(&mut self.shutting_down, true);
|
||||||
}
|
}
|
||||||
|
@ -836,7 +836,7 @@ fn write_minibsod<W: Write>(writer: &mut BufWriter<W>) -> Result<(), std::io::Er
|
|||||||
pub fn generate_minibsod<W: Write>(
|
pub fn generate_minibsod<W: Write>(
|
||||||
writer: &mut BufWriter<W>,
|
writer: &mut BufWriter<W>,
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
_siginfo: siginfo_t,
|
_siginfo: &siginfo_t,
|
||||||
ucontext: &ucontext_t,
|
ucontext: &ucontext_t,
|
||||||
) -> Result<(), std::io::Error> {
|
) -> Result<(), std::io::Error> {
|
||||||
writeln!(writer, "{:━^100}", " CRASH ")?;
|
writeln!(writer, "{:━^100}", " CRASH ")?;
|
||||||
|
@ -378,7 +378,7 @@ impl Display for Signal {
|
|||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub trait Handler {
|
pub trait Handler {
|
||||||
/// Handle a signal
|
/// Handle a signal
|
||||||
fn handle(&mut self, signal: Signal, info: siginfo_t, _context: &mut ucontext_t);
|
fn handle(&mut self, signal: Signal, info: &mut siginfo_t, _context: &mut ucontext_t);
|
||||||
/// Return a list of signals to handle
|
/// Return a list of signals to handle
|
||||||
fn signals(&self) -> Vec<Signal>;
|
fn signals(&self) -> Vec<Signal>;
|
||||||
}
|
}
|
||||||
@ -414,7 +414,7 @@ static mut SIGNAL_HANDLERS: [Option<HandlerHolder>; 32] = [
|
|||||||
/// This should be somewhat safe to call for signals previously registered,
|
/// This should be somewhat safe to call for signals previously registered,
|
||||||
/// unless the signal handlers registered using [`setup_signal_handler()`] are broken.
|
/// unless the signal handlers registered using [`setup_signal_handler()`] are broken.
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
unsafe fn handle_signal(sig: c_int, info: siginfo_t, void: *mut c_void) {
|
unsafe fn handle_signal(sig: c_int, info: *mut siginfo_t, void: *mut c_void) {
|
||||||
let signal = &Signal::try_from(sig).unwrap();
|
let signal = &Signal::try_from(sig).unwrap();
|
||||||
let handler = {
|
let handler = {
|
||||||
match &SIGNAL_HANDLERS[*signal as usize] {
|
match &SIGNAL_HANDLERS[*signal as usize] {
|
||||||
@ -424,7 +424,7 @@ unsafe fn handle_signal(sig: c_int, info: siginfo_t, void: *mut c_void) {
|
|||||||
};
|
};
|
||||||
handler.handle(
|
handler.handle(
|
||||||
*signal,
|
*signal,
|
||||||
info,
|
&mut ptr::read_unaligned(info),
|
||||||
&mut ptr::read_unaligned(void as *mut ucontext_t),
|
&mut ptr::read_unaligned(void as *mut ucontext_t),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use which::which;
|
|||||||
|
|
||||||
const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge";
|
const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge";
|
||||||
const QEMU_DIRNAME: &str = "qemu-libafl-bridge";
|
const QEMU_DIRNAME: &str = "qemu-libafl-bridge";
|
||||||
const QEMU_REVISION: &str = "ff5bc3d934044a5a5466759525f0371ccf86152e";
|
const QEMU_REVISION: &str = "ead06288fd597e72cbf50db1c89386f952592860";
|
||||||
|
|
||||||
fn build_dep_check(tools: &[&str]) {
|
fn build_dep_check(tools: &[&str]) {
|
||||||
for tool in tools {
|
for tool in tools {
|
||||||
@ -216,7 +216,6 @@ pub fn build(
|
|||||||
.arg("--disable-gtk")
|
.arg("--disable-gtk")
|
||||||
.arg("--disable-guest-agent")
|
.arg("--disable-guest-agent")
|
||||||
.arg("--disable-guest-agent-msi")
|
.arg("--disable-guest-agent-msi")
|
||||||
.arg("--disable-hax")
|
|
||||||
.arg("--disable-hvf")
|
.arg("--disable-hvf")
|
||||||
.arg("--disable-iconv")
|
.arg("--disable-iconv")
|
||||||
.arg("--disable-jack")
|
.arg("--disable-jack")
|
||||||
|
@ -7,12 +7,14 @@ use core::{
|
|||||||
mem::MaybeUninit,
|
mem::MaybeUninit,
|
||||||
ptr::{addr_of, copy_nonoverlapping, null},
|
ptr::{addr_of, copy_nonoverlapping, null},
|
||||||
};
|
};
|
||||||
use std::{cell::OnceCell, slice::from_raw_parts, str::from_utf8_unchecked};
|
#[cfg(emulation_mode = "usermode")]
|
||||||
|
use std::cell::OnceCell;
|
||||||
#[cfg(emulation_mode = "systemmode")]
|
#[cfg(emulation_mode = "systemmode")]
|
||||||
use std::{
|
use std::{
|
||||||
ffi::{CStr, CString},
|
ffi::{CStr, CString},
|
||||||
ptr::null_mut,
|
ptr::null_mut,
|
||||||
};
|
};
|
||||||
|
use std::{slice::from_raw_parts, str::from_utf8_unchecked};
|
||||||
|
|
||||||
#[cfg(emulation_mode = "usermode")]
|
#[cfg(emulation_mode = "usermode")]
|
||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
//! A `QEMU`-based executor for binary-only instrumentation in `LibAFL`
|
//! A `QEMU`-based executor for binary-only instrumentation in `LibAFL`
|
||||||
|
#[cfg(emulation_mode = "usermode")]
|
||||||
|
use core::ffi::c_void;
|
||||||
use core::fmt::{self, Debug, Formatter};
|
use core::fmt::{self, Debug, Formatter};
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "usermode")]
|
||||||
|
use libafl::executors::inprocess::InProcessExecutorHandlerData;
|
||||||
#[cfg(feature = "fork")]
|
#[cfg(feature = "fork")]
|
||||||
use libafl::{
|
use libafl::{
|
||||||
events::EventManager,
|
events::EventManager,
|
||||||
@ -9,7 +13,7 @@ use libafl::{
|
|||||||
};
|
};
|
||||||
use libafl::{
|
use libafl::{
|
||||||
events::{EventFirer, EventRestarter},
|
events::{EventFirer, EventRestarter},
|
||||||
executors::{Executor, ExitKind, HasObservers, InProcessExecutor},
|
executors::{inprocess::InProcessExecutor, Executor, ExitKind, HasObservers},
|
||||||
feedbacks::Feedback,
|
feedbacks::Feedback,
|
||||||
fuzzer::HasObjective,
|
fuzzer::HasObjective,
|
||||||
inputs::UsesInput,
|
inputs::UsesInput,
|
||||||
@ -17,6 +21,8 @@ use libafl::{
|
|||||||
state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
#[cfg(emulation_mode = "usermode")]
|
||||||
|
use libafl_bolts::os::unix_signals::{siginfo_t, ucontext_t, Signal};
|
||||||
#[cfg(feature = "fork")]
|
#[cfg(feature = "fork")]
|
||||||
use libafl_bolts::shmem::ShMemProvider;
|
use libafl_bolts::shmem::ShMemProvider;
|
||||||
|
|
||||||
@ -29,9 +35,9 @@ where
|
|||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
QT: QemuHelperTuple<S>,
|
QT: QemuHelperTuple<S>,
|
||||||
{
|
{
|
||||||
first_exec: bool,
|
|
||||||
hooks: &'a mut QemuHooks<'a, QT, S>,
|
|
||||||
inner: InProcessExecutor<'a, H, OT, S>,
|
inner: InProcessExecutor<'a, H, OT, S>,
|
||||||
|
hooks: &'a mut QemuHooks<'a, QT, S>,
|
||||||
|
first_exec: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, H, OT, QT, S> Debug for QemuExecutor<'a, H, OT, QT, S>
|
impl<'a, H, OT, QT, S> Debug for QemuExecutor<'a, H, OT, QT, S>
|
||||||
@ -49,6 +55,46 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "usermode")]
|
||||||
|
extern "C" {
|
||||||
|
// Original QEMU user signal handler
|
||||||
|
fn libafl_qemu_handle_crash(signal: i32, info: *mut siginfo_t, puc: *mut c_void) -> i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "usermode")]
|
||||||
|
static mut USE_LIBAFL_CRASH_HANDLER: bool = false;
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "usermode")]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn libafl_executor_reinstall_handlers() {
|
||||||
|
USE_LIBAFL_CRASH_HANDLER = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(emulation_mode = "usermode")]
|
||||||
|
pub unsafe fn inproc_qemu_crash_handler<E, EM, OF, Z>(
|
||||||
|
signal: Signal,
|
||||||
|
info: &mut siginfo_t,
|
||||||
|
context: &mut ucontext_t,
|
||||||
|
data: &mut InProcessExecutorHandlerData,
|
||||||
|
) where
|
||||||
|
E: Executor<EM, Z> + HasObservers,
|
||||||
|
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||||
|
OF: Feedback<E::State>,
|
||||||
|
E::State: HasSolutions + HasClientPerfMonitor + HasCorpus,
|
||||||
|
Z: HasObjective<Objective = OF, State = E::State>,
|
||||||
|
{
|
||||||
|
let real_crash = if USE_LIBAFL_CRASH_HANDLER {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
libafl_qemu_handle_crash(signal as i32, info, context as *mut _ as *mut c_void) != 0
|
||||||
|
};
|
||||||
|
if real_crash {
|
||||||
|
libafl::executors::inprocess::unix_signal_handler::inproc_crash_handler::<E, EM, OF, Z>(
|
||||||
|
signal, info, context, data,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, H, OT, QT, S> QemuExecutor<'a, H, OT, QT, S>
|
impl<'a, H, OT, QT, S> QemuExecutor<'a, H, OT, QT, S>
|
||||||
where
|
where
|
||||||
H: FnMut(&S::Input) -> ExitKind,
|
H: FnMut(&S::Input) -> ExitKind,
|
||||||
@ -70,6 +116,20 @@ where
|
|||||||
S: State + HasExecutions + HasCorpus + HasSolutions + HasClientPerfMonitor,
|
S: State + HasExecutions + HasCorpus + HasSolutions + HasClientPerfMonitor,
|
||||||
Z: HasObjective<Objective = OF, State = S>,
|
Z: HasObjective<Objective = OF, State = S>,
|
||||||
{
|
{
|
||||||
|
#[cfg(emulation_mode = "usermode")]
|
||||||
|
{
|
||||||
|
let mut inner =
|
||||||
|
InProcessExecutor::new(harness_fn, observers, fuzzer, state, event_mgr)?;
|
||||||
|
inner.handlers_mut().crash_handler =
|
||||||
|
inproc_qemu_crash_handler::<InProcessExecutor<'a, H, OT, S>, EM, OF, Z>
|
||||||
|
as *const c_void;
|
||||||
|
Ok(Self {
|
||||||
|
first_exec: true,
|
||||||
|
hooks,
|
||||||
|
inner,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[cfg(not(emulation_mode = "usermode"))]
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
first_exec: true,
|
first_exec: true,
|
||||||
hooks,
|
hooks,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user