libafl_qemu snapshot device filter (#1386)

* libafl_qemu snapshot device filter

* Working device list

* regenerate bindings stub
This commit is contained in:
Andrea Fioraldi 2023-08-01 12:01:10 +02:00 committed by GitHub
parent fc9caa8314
commit ac4a0e7330
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 1102 additions and 1440 deletions

View File

@ -90,6 +90,9 @@ pub fn fuzz() {
emu.set_breakpoint(breakpoint); // BREAKPOINT
let devices = emu.list_devices();
println!("Devices = {:?}", devices);
// let saved_cpu_states: Vec<_> = (0..emu.num_cpus())
// .map(|i| emu.cpu_from_index(i).save_state())
// .collect();

View File

@ -51,6 +51,7 @@ const WRAPPER_HEADER: &str = r#"
#include "sysemu/tcg.h"
#include "sysemu/replay.h"
#include "libafl_extras/syx-snapshot/device-save.h"
#include "libafl_extras/syx-snapshot/syx-snapshot.h"
#endif
@ -101,6 +102,7 @@ pub fn generate(
.allowlist_type("qemu_plugin_mem_rw")
.allowlist_type("MemOpIdx")
.allowlist_type("MemOp")
.allowlist_type("device_snapshot_kind_t")
.allowlist_function("qemu_user_init")
.allowlist_function("target_mmap")
.allowlist_function("target_mprotect")
@ -117,6 +119,7 @@ pub fn generate(
.allowlist_function("syx_snapshot_create")
.allowlist_function("syx_snapshot_root_restore")
.allowlist_function("syx_snapshot_dirty_list_add")
.allowlist_function("device_list_all")
.blocklist_function("main_loop_wait") // bindgen issue #1313
.parse_callbacks(Box::new(bindgen::CargoCallbacks));

View File

@ -8,7 +8,7 @@ use which::which;
const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge";
const QEMU_DIRNAME: &str = "qemu-libafl-bridge";
const QEMU_REVISION: &str = "6df19ab8f161791b7b16a896d1da1d16b8749006";
const QEMU_REVISION: &str = "659539eaceb7acf242f2f6a573b705e1be1befb6";
fn build_dep_check(tools: &[&str]) {
for tool in tools {

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,10 @@ use core::{
ptr::{addr_of, copy_nonoverlapping, null},
};
#[cfg(emulation_mode = "systemmode")]
use std::ffi::CString;
use std::{
ffi::{CStr, CString},
ptr::null_mut,
};
use std::{slice::from_raw_parts, str::from_utf8_unchecked};
#[cfg(emulation_mode = "usermode")]
@ -30,6 +33,43 @@ pub type GuestHwAddrInfo = libafl_qemu_sys::qemu_plugin_hwaddr;
#[cfg(emulation_mode = "systemmode")]
pub type FastSnapshot = *mut libafl_qemu_sys::syx_snapshot_t;
#[cfg(emulation_mode = "systemmode")]
pub enum DeviceSnapshotFilter {
All,
AllowList(Vec<String>),
DenyList(Vec<String>),
}
#[cfg(emulation_mode = "systemmode")]
impl DeviceSnapshotFilter {
fn enum_id(&self) -> libafl_qemu_sys::device_snapshot_kind_t {
match self {
DeviceSnapshotFilter::All => {
libafl_qemu_sys::device_snapshot_kind_e_DEVICE_SNAPSHOT_ALL
}
DeviceSnapshotFilter::AllowList(_) => {
libafl_qemu_sys::device_snapshot_kind_e_DEVICE_SNAPSHOT_ALLOWLIST
}
DeviceSnapshotFilter::DenyList(_) => {
libafl_qemu_sys::device_snapshot_kind_e_DEVICE_SNAPSHOT_DENYLIST
}
}
}
fn devices(&self, v: &mut Vec<*mut i8>) -> *mut *mut i8 {
v.clear();
match self {
DeviceSnapshotFilter::All => null_mut(),
DeviceSnapshotFilter::AllowList(l) | DeviceSnapshotFilter::DenyList(l) => {
for name in l {
v.push(name.as_bytes().as_ptr() as *mut i8);
}
v.as_mut_ptr()
}
}
}
}
#[repr(transparent)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct MemAccessInfo {
@ -1142,7 +1182,30 @@ impl Emulator {
#[cfg(emulation_mode = "systemmode")]
#[must_use]
pub fn create_fast_snapshot(&self, track: bool) -> FastSnapshot {
unsafe { libafl_qemu_sys::syx_snapshot_create(track) }
unsafe {
libafl_qemu_sys::syx_snapshot_create(
track,
libafl_qemu_sys::device_snapshot_kind_e_DEVICE_SNAPSHOT_ALL,
null_mut(),
)
}
}
#[cfg(emulation_mode = "systemmode")]
#[must_use]
pub fn create_fast_snapshot_filter(
&self,
track: bool,
device_filter: &DeviceSnapshotFilter,
) -> FastSnapshot {
let mut v = vec![];
unsafe {
libafl_qemu_sys::syx_snapshot_create(
track,
device_filter.enum_id(),
device_filter.devices(&mut v),
)
}
}
#[cfg(emulation_mode = "systemmode")]
@ -1150,6 +1213,29 @@ impl Emulator {
unsafe { libafl_qemu_sys::syx_snapshot_root_restore(snapshot) }
}
#[cfg(emulation_mode = "systemmode")]
pub fn list_devices(&self) -> Vec<String> {
let mut r = vec![];
unsafe {
let devices = libafl_qemu_sys::device_list_all();
if devices.is_null() {
return r;
}
let mut ptr = devices;
while !(*ptr).is_null() {
let c_str: &CStr = CStr::from_ptr(*ptr);
let name = c_str.to_str().unwrap().to_string();
r.push(name);
ptr = ptr.add(1);
}
libc::free(devices as *mut c_void);
r
}
}
#[cfg(emulation_mode = "usermode")]
pub fn set_pre_syscall_hook(
&self,