diff --git a/libafl/src/fuzzer/mod.rs b/libafl/src/fuzzer/mod.rs index 3eb643faa4..b5331bb96d 100644 --- a/libafl/src/fuzzer/mod.rs +++ b/libafl/src/fuzzer/mod.rs @@ -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() diff --git a/libafl_qemu/build_linux.rs b/libafl_qemu/build_linux.rs index 70e7b46f8d..2c5e0c64bf 100644 --- a/libafl_qemu/build_linux.rs +++ b/libafl_qemu/build_linux.rs @@ -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 { diff --git a/libafl_qemu/src/emu.rs b/libafl_qemu/src/emu.rs index 2332b24266..6e09766325 100644 --- a/libafl_qemu/src/emu.rs +++ b/libafl_qemu/src/emu.rs @@ -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 { if let Ok(p) = MmapPerms::try_from(perms) { self.emu diff --git a/libafl_qemu/src/hooks.rs b/libafl_qemu/src/hooks.rs index 839a93ff4a..dd89cdbaba 100644 --- a/libafl_qemu/src/hooks.rs +++ b/libafl_qemu/src/hooks.rs @@ -1104,6 +1104,8 @@ where ); HOOKS_IS_INITIALIZED = true; } + // re-translate blocks with hooks + emulator.flush_jit(); let slf = Box::pin(Self { emulator, helpers, diff --git a/libafl_qemu/src/lib.rs b/libafl_qemu/src/lib.rs index b74ea0520d..9873eaa7a7 100644 --- a/libafl_qemu/src/lib.rs +++ b/libafl_qemu/src/lib.rs @@ -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(); diff --git a/libafl_qemu/src/snapshot.rs b/libafl_qemu/src/snapshot.rs index ed52866d06..93d9d186cd 100644 --- a/libafl_qemu/src/snapshot.rs +++ b/libafl_qemu/src/snapshot.rs @@ -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( } #[allow(clippy::too_many_arguments)] +#[allow(non_upper_case_globals)] pub fn trace_mmap_snapshot( _emulator: &Emulator, helpers: &mut QT, @@ -298,7 +303,7 @@ pub fn trace_mmap_snapshot( 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, { - 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::() .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::() - .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::() .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::() + .unwrap(); + h.access(a2 as GuestAddr, 4096); // stat is not greater than a page + } + } + SYS_getrandom => { + let h = helpers + .match_first_type_mut::() + .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::() + .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::() + .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::() + .unwrap(); + h.add_mapped(a0 as GuestAddr, a2 as usize, Some(prot)); + } + } } } result