Skip to content

Commit d96d833

Browse files
authored
Support on_crash & on_timeout callbacks for libafl_qemu modules (#2620)
* support (unsafe) on_crash / on_timeout callbacks for modules * use libc types in bindgen
1 parent f0da4d1 commit d96d833

File tree

6 files changed

+186
-143
lines changed

6 files changed

+186
-143
lines changed

libafl_qemu/libafl_qemu_build/src/bindings.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ pub fn generate(
181181
.allowlist_function("qemu_main_loop")
182182
.allowlist_function("qemu_cleanup")
183183
.blocklist_function("main_loop_wait") // bindgen issue #1313
184+
.blocklist_type("siginfo_t")
185+
.raw_line("use libc::siginfo_t;")
184186
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()));
185187

186188
// arch specific functions

libafl_qemu/libafl_qemu_sys/src/bindings/x86_64_stub_bindings.rs

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
/* 1.83.0-nightly */
2-
/* qemu git hash: d6637939526f453c69f4c6bfe4635feb5dc5c0be */
1+
/* 1.84.0-nightly */
2+
/* qemu git hash: 805b14ffc44999952562e8f219d81c21a4fa50b9 */
33
/* automatically generated by rust-bindgen 0.70.1 */
44

5+
use libc::siginfo_t;
6+
57
#[repr(C)]
68
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
79
pub struct __BindgenBitfieldUnit<Storage> {
@@ -516,15 +518,6 @@ impl ::std::fmt::Debug for sigval {
516518
pub type __sigval_t = sigval;
517519
#[repr(C)]
518520
#[derive(Copy, Clone)]
519-
pub struct siginfo_t {
520-
pub si_signo: ::std::os::raw::c_int,
521-
pub si_errno: ::std::os::raw::c_int,
522-
pub si_code: ::std::os::raw::c_int,
523-
pub __pad0: ::std::os::raw::c_int,
524-
pub _sifields: siginfo_t__bindgen_ty_1,
525-
}
526-
#[repr(C)]
527-
#[derive(Copy, Clone)]
528521
pub union siginfo_t__bindgen_ty_1 {
529522
pub _pad: [::std::os::raw::c_int; 28usize],
530523
pub _kill: siginfo_t__bindgen_ty_1__bindgen_ty_1,
@@ -827,31 +820,6 @@ impl ::std::fmt::Debug for siginfo_t__bindgen_ty_1 {
827820
write!(f, "siginfo_t__bindgen_ty_1 {{ union }}")
828821
}
829822
}
830-
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
831-
const _: () = {
832-
["Size of siginfo_t"][::std::mem::size_of::<siginfo_t>() - 128usize];
833-
["Alignment of siginfo_t"][::std::mem::align_of::<siginfo_t>() - 8usize];
834-
["Offset of field: siginfo_t::si_signo"][::std::mem::offset_of!(siginfo_t, si_signo) - 0usize];
835-
["Offset of field: siginfo_t::si_errno"][::std::mem::offset_of!(siginfo_t, si_errno) - 4usize];
836-
["Offset of field: siginfo_t::si_code"][::std::mem::offset_of!(siginfo_t, si_code) - 8usize];
837-
["Offset of field: siginfo_t::__pad0"][::std::mem::offset_of!(siginfo_t, __pad0) - 12usize];
838-
["Offset of field: siginfo_t::_sifields"]
839-
[::std::mem::offset_of!(siginfo_t, _sifields) - 16usize];
840-
};
841-
impl Default for siginfo_t {
842-
fn default() -> Self {
843-
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
844-
unsafe {
845-
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
846-
s.assume_init()
847-
}
848-
}
849-
}
850-
impl ::std::fmt::Debug for siginfo_t {
851-
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
852-
write ! (f , "siginfo_t {{ si_signo: {:?}, si_errno: {:?}, si_code: {:?}, __pad0: {:?}, _sifields: {:?} }}" , self . si_signo , self . si_errno , self . si_code , self . __pad0 , self . _sifields)
853-
}
854-
}
855823
pub type guint8 = ::std::os::raw::c_uchar;
856824
pub type gchar = ::std::os::raw::c_char;
857825
pub type guint = ::std::os::raw::c_uint;

libafl_qemu/runtime/libafl_qemu_stub_bindings.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
/* 1.83.0-nightly */
2-
/* qemu git hash: d6637939526f453c69f4c6bfe4635feb5dc5c0be */
1+
/* 1.84.0-nightly */
2+
/* qemu git hash: 805b14ffc44999952562e8f219d81c21a4fa50b9 */
33
/* automatically generated by rust-bindgen 0.70.1 */
44

55
pub const LIBAFL_SYNC_EXIT_OPCODE: u32 = 1727150607;

libafl_qemu/src/executor.rs

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ use libafl_bolts::{
3535
use libafl_qemu_sys::libafl_exit_request_timeout;
3636
#[cfg(emulation_mode = "usermode")]
3737
use libafl_qemu_sys::libafl_qemu_handle_crash;
38-
#[cfg(emulation_mode = "usermode")]
39-
use libafl_qemu_sys::siginfo_t;
40-
#[cfg(emulation_mode = "systemmode")]
4138
use libc::siginfo_t;
4239

4340
#[cfg(emulation_mode = "usermode")]
@@ -60,17 +57,26 @@ where
6057
///
6158
/// This should be used as a crash handler, and nothing else.
6259
#[cfg(emulation_mode = "usermode")]
63-
unsafe fn inproc_qemu_crash_handler(
60+
unsafe fn inproc_qemu_crash_handler<ET, S>(
6461
signal: Signal,
6562
info: &mut siginfo_t,
6663
mut context: Option<&mut ucontext_t>,
6764
_data: &mut InProcessExecutorHandlerData,
68-
) {
65+
) where
66+
ET: EmulatorModuleTuple<S>,
67+
S: UsesInput + Unpin,
68+
{
6969
let puc = match &mut context {
7070
Some(v) => ptr::from_mut::<ucontext_t>(*v) as *mut c_void,
7171
None => ptr::null_mut(),
7272
};
73-
libafl_qemu_handle_crash(signal as i32, ptr::from_mut::<siginfo_t>(info), puc);
73+
74+
// run modules' crash callback
75+
if let Some(emulator_modules) = EmulatorModules::<ET, S>::emulator_modules_mut() {
76+
emulator_modules.modules_mut().on_crash_all();
77+
}
78+
79+
libafl_qemu_handle_crash(signal as i32, info, puc);
7480
}
7581

7682
#[cfg(emulation_mode = "systemmode")]
@@ -79,25 +85,44 @@ pub(crate) static BREAK_ON_TMOUT: AtomicBool = AtomicBool::new(false);
7985
/// # Safety
8086
/// Can call through the `unix_signal_handler::inproc_timeout_handler`.
8187
/// Calling this method multiple times concurrently can lead to race conditions.
82-
#[cfg(emulation_mode = "systemmode")]
83-
pub unsafe fn inproc_qemu_timeout_handler<E, EM, OF, Z>(
88+
pub unsafe fn inproc_qemu_timeout_handler<E, EM, ET, OF, S, Z>(
8489
signal: Signal,
8590
info: &mut siginfo_t,
8691
context: Option<&mut ucontext_t>,
8792
data: &mut InProcessExecutorHandlerData,
8893
) where
8994
E: HasObservers + HasInProcessHooks<E::State> + Executor<EM, Z>,
9095
E::Observers: ObserversTuple<E::Input, E::State>,
96+
E::State: HasExecutions + HasSolutions + HasCorpus,
9197
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
98+
ET: EmulatorModuleTuple<S>,
9299
OF: Feedback<EM, E::Input, E::Observers, E::State>,
93-
E::State: HasExecutions + HasSolutions + HasCorpus,
100+
S: State + Unpin,
94101
Z: HasObjective<Objective = OF, State = E::State>,
95102
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
96103
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
97104
{
98-
if BREAK_ON_TMOUT.load(Ordering::Acquire) {
99-
libafl_exit_request_timeout();
100-
} else {
105+
#[cfg(emulation_mode = "systemmode")]
106+
{
107+
if BREAK_ON_TMOUT.load(Ordering::Acquire) {
108+
libafl_exit_request_timeout();
109+
} else {
110+
libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::<
111+
E,
112+
EM,
113+
OF,
114+
Z,
115+
>(signal, info, context, data);
116+
}
117+
}
118+
119+
#[cfg(emulation_mode = "usermode")]
120+
{
121+
// run modules' crash callback
122+
if let Some(emulator_modules) = EmulatorModules::<ET, S>::emulator_modules_mut() {
123+
emulator_modules.modules_mut().on_timeout_all();
124+
}
125+
101126
libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::<E, EM, OF, Z>(
102127
signal, info, context, data,
103128
);
@@ -153,7 +178,8 @@ where
153178

154179
#[cfg(emulation_mode = "usermode")]
155180
{
156-
inner.inprocess_hooks_mut().crash_handler = inproc_qemu_crash_handler as *const c_void;
181+
inner.inprocess_hooks_mut().crash_handler =
182+
inproc_qemu_crash_handler::<ET, S> as *const c_void;
157183

158184
let handler = |emulator_modules: &mut EmulatorModules<ET, S>, host_sig| {
159185
eprintln!("Crashed with signal {host_sig}");
@@ -175,15 +201,14 @@ where
175201
}
176202
}
177203

178-
#[cfg(emulation_mode = "systemmode")]
179-
{
180-
inner.inprocess_hooks_mut().timeout_handler = inproc_qemu_timeout_handler::<
181-
StatefulInProcessExecutor<'a, H, OT, S, Emulator<CM, ED, ET, S, SM>>,
182-
EM,
183-
OF,
184-
Z,
185-
> as *const c_void;
186-
}
204+
inner.inprocess_hooks_mut().timeout_handler = inproc_qemu_timeout_handler::<
205+
StatefulInProcessExecutor<'a, H, OT, S, Emulator<CM, ED, ET, S, SM>>,
206+
EM,
207+
ET,
208+
OF,
209+
S,
210+
Z,
211+
> as *const c_void;
187212

188213
Ok(Self {
189214
inner,

0 commit comments

Comments
 (0)