Fix snapshots in libafl_qemu (#556)
* afl_exec_sec feature, disabled by default * Fix snapshots in libafl_qemu * working memory snapshots
This commit is contained in:
parent
c4fb92a1a4
commit
bf9d2b4c57
@ -591,12 +591,12 @@ where
|
||||
executor.observers_mut().pre_exec_all(state, input)?;
|
||||
mark_feature_time!(state, PerfFeature::PreExecObservers);
|
||||
|
||||
*state.executions_mut() += 1;
|
||||
|
||||
start_timer!(state);
|
||||
let exit_kind = executor.run_target(self, state, event_mgr, input)?;
|
||||
mark_feature_time!(state, PerfFeature::TargetExecution);
|
||||
|
||||
*state.executions_mut() += 1;
|
||||
|
||||
start_timer!(state);
|
||||
executor
|
||||
.observers_mut()
|
||||
@ -651,12 +651,12 @@ where
|
||||
executor.observers_mut().pre_exec_all(state, input)?;
|
||||
mark_feature_time!(state, PerfFeature::PreExecObservers);
|
||||
|
||||
*state.executions_mut() += 1;
|
||||
|
||||
start_timer!(state);
|
||||
let exit_kind = executor.run_target(self, state, event_mgr, input)?;
|
||||
mark_feature_time!(state, PerfFeature::TargetExecution);
|
||||
|
||||
*state.executions_mut() += 1;
|
||||
|
||||
start_timer!(state);
|
||||
executor
|
||||
.observers_mut()
|
||||
|
@ -3,7 +3,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 = "35dcfc0c115da262622fdc811d089155f26a2abe";
|
||||
const QEMU_REVISION: &str = "17c1f083eefca42088d6a88df04c65713f1cc58a";
|
||||
|
||||
fn build_dep_check(tools: &[&str]) {
|
||||
for tool in tools {
|
||||
|
@ -188,6 +188,7 @@ extern "C" {
|
||||
fn libafl_qemu_num_regs() -> i32;
|
||||
fn libafl_qemu_set_breakpoint(addr: u64) -> i32;
|
||||
fn libafl_qemu_remove_breakpoint(addr: u64) -> i32;
|
||||
fn libafl_flush_jit();
|
||||
fn libafl_qemu_set_hook(addr: u64, callback: extern "C" fn(u64), val: u64) -> i32;
|
||||
fn libafl_qemu_remove_hook(addr: u64) -> i32;
|
||||
fn libafl_qemu_run() -> i32;
|
||||
@ -535,6 +536,12 @@ impl Emulator {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flush_jit(&self) {
|
||||
unsafe {
|
||||
libafl_flush_jit();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add has_X_hook() and panic when setting a hook for the second time
|
||||
|
||||
pub fn set_exec_edge_hook(&self, hook: extern "C" fn(id: u64)) {
|
||||
@ -814,6 +821,10 @@ pub mod pybind {
|
||||
self.emu.load_addr()
|
||||
}
|
||||
|
||||
fn flush_jit(&self) {
|
||||
self.emu.flush_jit();
|
||||
}
|
||||
|
||||
fn map_private(&self, addr: GuestAddr, size: usize, perms: i32) -> PyResult<GuestAddr> {
|
||||
if let Ok(p) = MmapPerms::try_from(perms) {
|
||||
self.emu
|
||||
|
@ -1104,6 +1104,8 @@ where
|
||||
);
|
||||
HOOKS_IS_INITIALIZED = true;
|
||||
}
|
||||
// re-translate blocks with hooks
|
||||
emulator.flush_jit();
|
||||
let slf = Box::pin(Self {
|
||||
emulator,
|
||||
helpers,
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
use std::env;
|
||||
|
||||
pub use strum::IntoEnumIterator;
|
||||
|
||||
#[cfg(cpu_target = "aarch64")]
|
||||
pub mod aarch64;
|
||||
#[cfg(all(cpu_target = "aarch64", not(feature = "clippy")))]
|
||||
@ -77,8 +79,6 @@ use pyo3::prelude::*;
|
||||
#[pyo3(name = "libafl_qemu")]
|
||||
#[allow(clippy::items_after_statements, clippy::too_many_lines)]
|
||||
pub fn python_module(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
let regsm = PyModule::new(py, "regs")?;
|
||||
for r in Regs::iter() {
|
||||
let v: i32 = r.into();
|
||||
|
@ -12,10 +12,12 @@ use crate::{
|
||||
emu::{Emulator, MmapPerms},
|
||||
helper::{QemuHelper, QemuHelperTuple},
|
||||
hooks::QemuHooks,
|
||||
GuestAddr, SYS_mmap, SYS_mprotect, SYS_mremap,
|
||||
GuestAddr, SYS_getrandom, SYS_mmap, SYS_mprotect, SYS_mremap, SYS_newfstatat, SYS_read,
|
||||
SYS_readlinkat,
|
||||
};
|
||||
|
||||
pub const SNAPSHOT_PAGE_SIZE: usize = 4096;
|
||||
pub const SNAPSHOT_PAGE_MASK: GuestAddr = !(SNAPSHOT_PAGE_SIZE as GuestAddr - 1);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SnapshotPageInfo {
|
||||
@ -106,9 +108,9 @@ impl QemuSnapshotHelper {
|
||||
|
||||
pub fn access(&mut self, addr: GuestAddr, size: usize) {
|
||||
debug_assert!(size > 0);
|
||||
let page = addr & (SNAPSHOT_PAGE_SIZE as GuestAddr - 1);
|
||||
let page = addr & SNAPSHOT_PAGE_MASK;
|
||||
self.page_access(page);
|
||||
let second_page = (addr + size as GuestAddr - 1) & (SNAPSHOT_PAGE_SIZE as GuestAddr - 1);
|
||||
let second_page = (addr + size as GuestAddr - 1) & SNAPSHOT_PAGE_MASK;
|
||||
if page != second_page {
|
||||
self.page_access(second_page);
|
||||
}
|
||||
@ -116,6 +118,7 @@ impl QemuSnapshotHelper {
|
||||
|
||||
pub fn reset(&mut self, emulator: &Emulator) {
|
||||
self.reset_maps(emulator);
|
||||
|
||||
for acc in self.accesses.iter_mut() {
|
||||
for page in unsafe { &(*acc.get()).dirty } {
|
||||
if let Some(info) = self.pages.get_mut(page) {
|
||||
@ -127,6 +130,7 @@ impl QemuSnapshotHelper {
|
||||
}
|
||||
unsafe { (*acc.get()).clear() };
|
||||
}
|
||||
|
||||
emulator.set_brk(self.brk);
|
||||
}
|
||||
|
||||
@ -146,7 +150,7 @@ impl QemuSnapshotHelper {
|
||||
let addr = r.interval().start;
|
||||
let end = r.interval().end;
|
||||
let perms = r.data();
|
||||
let mut page = addr & (SNAPSHOT_PAGE_SIZE as GuestAddr - 1);
|
||||
let mut page = addr & SNAPSHOT_PAGE_MASK;
|
||||
let mut prev = None;
|
||||
while page < end {
|
||||
if let Some(info) = self.pages.get(&page) {
|
||||
@ -289,6 +293,7 @@ pub fn trace_write_n_snapshot<I, QT, S>(
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub fn trace_mmap_snapshot<I, QT, S>(
|
||||
_emulator: &Emulator,
|
||||
helpers: &mut QT,
|
||||
@ -298,7 +303,7 @@ pub fn trace_mmap_snapshot<I, QT, S>(
|
||||
a0: u64,
|
||||
a1: u64,
|
||||
a2: u64,
|
||||
_a3: u64,
|
||||
a3: u64,
|
||||
_a4: u64,
|
||||
_a5: u64,
|
||||
_a6: u64,
|
||||
@ -308,29 +313,61 @@ where
|
||||
I: Input,
|
||||
QT: QemuHelperTuple<I, S>,
|
||||
{
|
||||
if result as GuestAddr == GuestAddr::MAX
|
||||
/* -1 */
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if i64::from(sys_num) == SYS_mmap {
|
||||
if let Ok(prot) = MmapPerms::try_from(a2 as i32) {
|
||||
// NOT A COMPLETE LIST OF MEMORY EFFECTS
|
||||
match i64::from(sys_num) {
|
||||
SYS_read => {
|
||||
let h = helpers
|
||||
.match_first_type_mut::<QemuSnapshotHelper>()
|
||||
.unwrap();
|
||||
h.add_mapped(result as GuestAddr, a1 as usize, Some(prot));
|
||||
h.access(a1 as GuestAddr, a2 as usize);
|
||||
}
|
||||
} else if i64::from(sys_num) == SYS_mremap {
|
||||
let h = helpers
|
||||
.match_first_type_mut::<QemuSnapshotHelper>()
|
||||
.unwrap();
|
||||
h.add_mapped(result as GuestAddr, a2 as usize, None);
|
||||
} else if i64::from(sys_num) == SYS_mprotect {
|
||||
if let Ok(prot) = MmapPerms::try_from(a2 as i32) {
|
||||
SYS_readlinkat => {
|
||||
let h = helpers
|
||||
.match_first_type_mut::<QemuSnapshotHelper>()
|
||||
.unwrap();
|
||||
h.add_mapped(a0 as GuestAddr, a2 as usize, Some(prot));
|
||||
h.access(a2 as GuestAddr, a3 as usize);
|
||||
}
|
||||
SYS_newfstatat => {
|
||||
if a2 != 0 {
|
||||
let h = helpers
|
||||
.match_first_type_mut::<QemuSnapshotHelper>()
|
||||
.unwrap();
|
||||
h.access(a2 as GuestAddr, 4096); // stat is not greater than a page
|
||||
}
|
||||
}
|
||||
SYS_getrandom => {
|
||||
let h = helpers
|
||||
.match_first_type_mut::<QemuSnapshotHelper>()
|
||||
.unwrap();
|
||||
h.access(a0 as GuestAddr, a1 as usize);
|
||||
}
|
||||
// mmap syscalls
|
||||
_ => {
|
||||
if result as GuestAddr == GuestAddr::MAX
|
||||
/* -1 */
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if i64::from(sys_num) == SYS_mmap {
|
||||
if let Ok(prot) = MmapPerms::try_from(a2 as i32) {
|
||||
let h = helpers
|
||||
.match_first_type_mut::<QemuSnapshotHelper>()
|
||||
.unwrap();
|
||||
h.add_mapped(result as GuestAddr, a1 as usize, Some(prot));
|
||||
}
|
||||
} else if i64::from(sys_num) == SYS_mremap {
|
||||
let h = helpers
|
||||
.match_first_type_mut::<QemuSnapshotHelper>()
|
||||
.unwrap();
|
||||
h.add_mapped(result as GuestAddr, a2 as usize, None);
|
||||
} else if i64::from(sys_num) == SYS_mprotect {
|
||||
if let Ok(prot) = MmapPerms::try_from(a2 as i32) {
|
||||
let h = helpers
|
||||
.match_first_type_mut::<QemuSnapshotHelper>()
|
||||
.unwrap();
|
||||
h.add_mapped(a0 as GuestAddr, a2 as usize, Some(prot));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
|
Loading…
x
Reference in New Issue
Block a user