Break on timeout in QEMU system mode (#1619)
* Break on timeout in QEMU system mode * fix * fix * fix
This commit is contained in:
parent
31f4669794
commit
47cd4dfea6
@ -18,3 +18,4 @@ codegen-units = 1
|
||||
libafl = { path = "../../libafl/" }
|
||||
libafl_bolts = { path = "../../libafl_bolts/" }
|
||||
libafl_qemu = { path = "../../libafl_qemu/", features = ["arm", "systemmode"] }
|
||||
env_logger = "*"
|
||||
|
@ -1,12 +1,11 @@
|
||||
int BREAKPOINT() {
|
||||
int __attribute__ ((noinline)) BREAKPOINT() {
|
||||
for (;;) {}
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(unsigned int *Data, unsigned int Size) {
|
||||
// if (Data[3] == 0) {while(1){}} // cause a timeout
|
||||
if (Data[3] == 0) {while(1){}} // cause a timeout
|
||||
for (int i = 0; i < Size; i++) {
|
||||
// if (Data[i] > 0xFFd0 && Data[i] < 0xFFFF) {return 1;} // cause qemu to
|
||||
// crash
|
||||
// if (Data[i] > 0xFFd0 && Data[i] < 0xFFFF) {return 1;} // cause qemu to crash
|
||||
for (int j = i + 1; j < Size; j++) {
|
||||
if (Data[j] == 0) { continue; }
|
||||
if (Data[j] > Data[i]) {
|
||||
|
@ -37,6 +37,8 @@ use libafl_qemu::{
|
||||
pub static mut MAX_INPUT_SIZE: usize = 50;
|
||||
|
||||
pub fn fuzz() {
|
||||
env_logger::init();
|
||||
|
||||
if let Ok(s) = env::var("FUZZ_SIZE") {
|
||||
str::parse::<usize>(&s).expect("FUZZ_SIZE was not a number");
|
||||
};
|
||||
@ -193,7 +195,7 @@ pub fn fuzz() {
|
||||
let mut hooks = QemuHooks::new(&emu, tuple_list!(QemuEdgeCoverageHelper::default()));
|
||||
|
||||
// Create a QEMU in-process executor
|
||||
let executor = QemuExecutor::new(
|
||||
let mut executor = QemuExecutor::new(
|
||||
&mut hooks,
|
||||
&mut harness,
|
||||
tuple_list!(edges_observer, time_observer),
|
||||
@ -203,6 +205,9 @@ pub fn fuzz() {
|
||||
)
|
||||
.expect("Failed to create QemuExecutor");
|
||||
|
||||
// Instead of calling the timeout handler and restart the process, trigger a breakpoint ASAP
|
||||
executor.break_on_timeout();
|
||||
|
||||
// Wrap the executor to keep track of the timeout
|
||||
let mut executor = TimeoutExecutor::new(executor, timeout);
|
||||
|
||||
|
@ -845,7 +845,7 @@ pub fn generate_minibsod<W: Write>(
|
||||
writeln!(writer, "{:━^100}", " REGISTERS ")?;
|
||||
dump_registers(writer, uctx)?;
|
||||
} else {
|
||||
writeln!(writer, "Received signal {}", signal)?;
|
||||
writeln!(writer, "Received signal {signal}")?;
|
||||
}
|
||||
writeln!(writer, "{:━^100}", " BACKTRACE ")?;
|
||||
writeln!(writer, "{:?}", backtrace::Backtrace::new())?;
|
||||
|
@ -1,10 +1,9 @@
|
||||
//! 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::{
|
||||
ffi::c_void,
|
||||
fmt::{self, Debug, Formatter},
|
||||
};
|
||||
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
use libafl::executors::inprocess::InProcessExecutorHandlerData;
|
||||
#[cfg(feature = "fork")]
|
||||
use libafl::{
|
||||
events::EventManager,
|
||||
@ -13,7 +12,10 @@ use libafl::{
|
||||
};
|
||||
use libafl::{
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{inprocess::InProcessExecutor, Executor, ExitKind, HasObservers},
|
||||
executors::{
|
||||
inprocess::{InProcessExecutor, InProcessExecutorHandlerData},
|
||||
Executor, ExitKind, HasObservers,
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
@ -21,7 +23,6 @@ use libafl::{
|
||||
state::{HasClientPerfMonitor, HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
||||
Error,
|
||||
};
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
use libafl_bolts::os::unix_signals::{siginfo_t, ucontext_t, Signal};
|
||||
#[cfg(feature = "fork")]
|
||||
use libafl_bolts::shmem::ShMemProvider;
|
||||
@ -74,7 +75,7 @@ pub unsafe extern "C" fn libafl_executor_reinstall_handlers() {
|
||||
pub unsafe fn inproc_qemu_crash_handler<E, EM, OF, Z>(
|
||||
signal: Signal,
|
||||
info: &mut siginfo_t,
|
||||
context: &mut ucontext_t,
|
||||
mut context: Option<&mut ucontext_t>,
|
||||
data: &mut InProcessExecutorHandlerData,
|
||||
) where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
@ -86,7 +87,11 @@ pub unsafe fn inproc_qemu_crash_handler<E, EM, OF, Z>(
|
||||
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
|
||||
let puc = match &mut context {
|
||||
Some(v) => (*v) as *mut ucontext_t as *mut c_void,
|
||||
None => core::ptr::null_mut(),
|
||||
};
|
||||
libafl_qemu_handle_crash(signal as i32, info, puc) != 0
|
||||
};
|
||||
if real_crash {
|
||||
libafl::executors::inprocess::unix_signal_handler::inproc_crash_handler::<E, EM, OF, Z>(
|
||||
@ -95,6 +100,36 @@ pub unsafe fn inproc_qemu_crash_handler<E, EM, OF, Z>(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(emulation_mode = "systemmode")]
|
||||
static mut BREAK_ON_TMOUT: bool = false;
|
||||
|
||||
#[cfg(emulation_mode = "systemmode")]
|
||||
extern "C" {
|
||||
fn qemu_system_debug_request();
|
||||
}
|
||||
|
||||
#[cfg(emulation_mode = "systemmode")]
|
||||
pub unsafe fn inproc_qemu_timeout_handler<E, EM, OF, Z>(
|
||||
signal: Signal,
|
||||
info: &mut siginfo_t,
|
||||
context: Option<&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>,
|
||||
{
|
||||
if BREAK_ON_TMOUT {
|
||||
qemu_system_debug_request();
|
||||
} else {
|
||||
libafl::executors::inprocess::unix_signal_handler::inproc_timeout_handler::<E, EM, OF, Z>(
|
||||
signal, info, context, data,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, H, OT, QT, S> QemuExecutor<'a, H, OT, QT, S>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
@ -116,24 +151,23 @@ where
|
||||
S: State + HasExecutions + HasCorpus + HasSolutions + HasClientPerfMonitor,
|
||||
Z: HasObjective<Objective = OF, State = S>,
|
||||
{
|
||||
let mut inner = InProcessExecutor::new(harness_fn, observers, fuzzer, state, event_mgr)?;
|
||||
#[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"))]
|
||||
#[cfg(emulation_mode = "systemmode")]
|
||||
{
|
||||
inner.handlers_mut().timeout_handler =
|
||||
inproc_qemu_timeout_handler::<InProcessExecutor<'a, H, OT, S>, EM, OF, Z>
|
||||
as *const c_void;
|
||||
}
|
||||
Ok(Self {
|
||||
first_exec: true,
|
||||
hooks,
|
||||
inner: InProcessExecutor::new(harness_fn, observers, fuzzer, state, event_mgr)?,
|
||||
inner,
|
||||
})
|
||||
}
|
||||
|
||||
@ -141,6 +175,13 @@ where
|
||||
&self.inner
|
||||
}
|
||||
|
||||
#[cfg(emulation_mode = "systemmode")]
|
||||
pub fn break_on_timeout(&mut self) {
|
||||
unsafe {
|
||||
BREAK_ON_TMOUT = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inner_mut(&mut self) -> &mut InProcessExecutor<'a, H, OT, S> {
|
||||
&mut self.inner
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user