Fix QEMU userspace crash handler (#1706)

* Fix QEMU userspace crash handler

* no_std
This commit is contained in:
Andrea Fioraldi 2023-12-01 13:26:10 +01:00 committed by GitHub
parent 5d83c9399a
commit 517d6962bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 25 deletions

View File

@ -634,6 +634,42 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
log::info!("Bye!"); log::info!("Bye!");
} }
// 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
#[cfg(any(unix, feature = "std"))]
pub fn generic_inproc_crash_handler<E, EM, OF, Z>()
where
E: Executor<EM, Z> + HasObservers,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>,
{
let data = unsafe { &mut GLOBAL_STATE };
let in_handler = data.set_in_handler(true);
if data.is_valid() {
let executor = data.executor_mut::<E>();
// disarms timeout in case of TimeoutExecutor
executor.post_run_reset();
let state = data.state_mut::<E::State>();
let event_mgr = data.event_mgr_mut::<EM>();
let fuzzer = data.fuzzer_mut::<Z>();
let input = data.take_current_input::<<E::State as UsesInput>::Input>();
run_observers_and_save_state::<E, EM, OF, Z>(
executor,
state,
input,
fuzzer,
event_mgr,
ExitKind::Crash,
);
}
data.set_in_handler(in_handler);
}
/// The inprocess executor singal handling code for unix /// The inprocess executor singal handling code for unix
#[cfg(unix)] #[cfg(unix)]
pub mod unix_signal_handler { pub mod unix_signal_handler {

View File

@ -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 = "c105904e6659b3fc90e938438a44254dfe47e1c3"; const QEMU_REVISION: &str = "32206d23c33a55c9e519e4ae67038ab27d713a24";
fn build_dep_check(tools: &[&str]) { fn build_dep_check(tools: &[&str]) {
for tool in tools { for tool in tools {

View File

@ -59,16 +59,7 @@ where
#[cfg(emulation_mode = "usermode")] #[cfg(emulation_mode = "usermode")]
extern "C" { extern "C" {
// Original QEMU user signal handler // Original QEMU user signal handler
fn libafl_qemu_handle_crash(signal: i32, info: *mut siginfo_t, puc: *mut c_void) -> i32; fn libafl_qemu_handle_crash(signal: i32, info: *mut siginfo_t, puc: *mut c_void);
}
#[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")] #[cfg(emulation_mode = "usermode")]
@ -76,7 +67,7 @@ pub unsafe fn inproc_qemu_crash_handler<E, EM, OF, Z>(
signal: Signal, signal: Signal,
info: &mut siginfo_t, info: &mut siginfo_t,
mut context: Option<&mut ucontext_t>, mut context: Option<&mut ucontext_t>,
data: &mut InProcessExecutorHandlerData, _data: &mut InProcessExecutorHandlerData,
) 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>,
@ -84,20 +75,11 @@ pub unsafe fn inproc_qemu_crash_handler<E, EM, OF, Z>(
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 real_crash = if USE_LIBAFL_CRASH_HANDLER {
true
} else {
let puc = match &mut context { let puc = match &mut context {
Some(v) => (*v) as *mut ucontext_t as *mut c_void, Some(v) => (*v) as *mut ucontext_t as *mut c_void,
None => core::ptr::null_mut(), None => core::ptr::null_mut(),
}; };
libafl_qemu_handle_crash(signal as i32, info, puc) != 0 libafl_qemu_handle_crash(signal as i32, info, puc);
};
if real_crash {
libafl::executors::inprocess::unix_signal_handler::inproc_crash_handler::<E, EM, OF, Z>(
signal, info, context, data,
);
}
} }
#[cfg(emulation_mode = "systemmode")] #[cfg(emulation_mode = "systemmode")]
@ -157,6 +139,21 @@ where
inner.handlers_mut().crash_handler = inner.handlers_mut().crash_handler =
inproc_qemu_crash_handler::<InProcessExecutor<'a, H, OT, S>, EM, OF, Z> inproc_qemu_crash_handler::<InProcessExecutor<'a, H, OT, S>, EM, OF, Z>
as *const c_void; as *const c_void;
let handler = |hooks: &mut QemuHooks<QT, S>, host_sig| {
eprintln!("Crashed with signal {host_sig}");
libafl::executors::inprocess::generic_inproc_crash_handler::<
InProcessExecutor<'a, H, OT, S>,
EM,
OF,
Z,
>();
if let Some(cpu) = hooks.emulator().current_cpu() {
eprint!("Context:\n{}", cpu.display_context());
}
};
hooks.crash_closure(Box::new(handler));
} }
#[cfg(emulation_mode = "systemmode")] #[cfg(emulation_mode = "systemmode")]
{ {