diff --git a/fuzzers/qemu/systemmode/linux/process/src/fuzzer.rs b/fuzzers/qemu/systemmode/linux/process/src/fuzzer.rs index df5ee52d11..cd1f6a076b 100644 --- a/fuzzers/qemu/systemmode/linux/process/src/fuzzer.rs +++ b/fuzzers/qemu/systemmode/linux/process/src/fuzzer.rs @@ -1,8 +1,8 @@ //! A fuzzer using qemu in systemmode for binary-only coverage of linux use core::{ptr::addr_of_mut, time::Duration}; -use std::{env, path::PathBuf, process}; -use std::thread::sleep; +use std::{env, path::PathBuf, process, thread::sleep}; + use libafl::{ corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, diff --git a/libafl_qemu/src/command/mod.rs b/libafl_qemu/src/command/mod.rs index aaecfa9273..3965ffce93 100644 --- a/libafl_qemu/src/command/mod.rs +++ b/libafl_qemu/src/command/mod.rs @@ -26,7 +26,7 @@ use crate::{ get_exit_arch_regs, modules::EmulatorModuleTuple, sync_exit::ExitArgs, - Emulator, EmulatorDriverError, EmulatorDriverResult, GuestPhysAddr, GuestReg, InputLocation, + Emulator, EmulatorDriverError, EmulatorDriverResult, GuestReg, InputLocation, IsSnapshotManager, Qemu, QemuMemoryChunk, QemuRWError, Regs, StdEmulatorDriver, CPU, }; @@ -444,6 +444,7 @@ where } // Auto page filtering if option is enabled + #[cfg(emulation_mode = "systemmode")] if emu.driver_mut().allow_page_on_start() { let page_id = qemu.current_cpu().unwrap().current_paging_id().unwrap(); emu.modules_mut().modules_mut().allow_page_id_all(page_id); diff --git a/libafl_qemu/src/emu/builder.rs b/libafl_qemu/src/emu/builder.rs index 32358e5f93..a7c1cac4a6 100644 --- a/libafl_qemu/src/emu/builder.rs +++ b/libafl_qemu/src/emu/builder.rs @@ -13,7 +13,7 @@ use crate::{ config::QemuConfig, modules::{EmulatorModule, EmulatorModuleTuple}, Emulator, NopEmulatorDriver, NopSnapshotManager, Qemu, QemuInitError, StdEmulatorDriver, - StdSnapshotManager, + StdEmulatorDriverBuilder, StdSnapshotManager, }; #[derive(Clone, Debug)] @@ -66,7 +66,7 @@ where modules: tuple_list!(), command_manager: StdCommandManager::default(), snapshot_manager: StdSnapshotManager::default(), - driver: StdEmulatorDriver::default(), + driver: StdEmulatorDriver::builder().build(), qemu_builder: None, phantom: PhantomData, } diff --git a/libafl_qemu/src/emu/drivers.rs b/libafl_qemu/src/emu/drivers.rs index 3340fbb38e..b32b4a4f2a 100644 --- a/libafl_qemu/src/emu/drivers.rs +++ b/libafl_qemu/src/emu/drivers.rs @@ -8,7 +8,7 @@ use libafl::{ inputs::{HasTargetBytes, UsesInput}, observers::ObserversTuple, }; -use libafl_bolts::{bolts_prelude::CTRL_C_EXIT, os::unix_signals::Signal}; +use libafl_bolts::os::{unix_signals::Signal, CTRL_C_EXIT}; use typed_builder::TypedBuilder; use crate::{ @@ -53,13 +53,17 @@ where { /// Just before calling user's harness for the first time. /// Called only once - fn first_harness_exec(emulator: &mut Emulator) { - emulator.modules.first_exec_all(); + fn first_harness_exec(emulator: &mut Emulator, state: &mut S) { + emulator.modules.first_exec_all(state); } /// Just before calling user's harness - fn pre_harness_exec(emulator: &mut Emulator, input: &S::Input) { - emulator.modules.pre_exec_all(input); + fn pre_harness_exec( + emulator: &mut Emulator, + input: &S::Input, + state: &mut S, + ) { + emulator.modules.pre_exec_all(input, state); } /// Just after returning from user's harness @@ -67,11 +71,14 @@ where emulator: &mut Emulator, input: &S::Input, observers: &mut OT, + state: &mut S, exit_kind: &mut ExitKind, ) where OT: ObserversTuple, { - emulator.modules.post_exec_all(input, observers, exit_kind); + emulator + .modules + .post_exec_all(input, observers, state, exit_kind); } /// Just before entering QEMU @@ -100,7 +107,7 @@ where { } -#[derive(Clone, Debug, TypedBuilder)] +#[derive(Clone, Debug, Default, TypedBuilder)] pub struct StdEmulatorDriver { #[builder(default = OnceCell::new())] snapshot_id: OnceCell, @@ -136,6 +143,7 @@ impl StdEmulatorDriver { was_locked } + #[cfg(emulation_mode = "systemmode")] pub fn allow_page_on_start(&self) -> bool { self.allow_page_on_start } @@ -154,15 +162,19 @@ where S::Input: HasTargetBytes, SM: IsSnapshotManager, { - fn first_harness_exec(emulator: &mut Emulator) { + fn first_harness_exec(emulator: &mut Emulator, state: &mut S) { if !emulator.driver.hooks_locked { - emulator.modules.first_exec_all(); + emulator.modules.first_exec_all(state); } } - fn pre_harness_exec(emulator: &mut Emulator, input: &S::Input) { + fn pre_harness_exec( + emulator: &mut Emulator, + input: &S::Input, + state: &mut S, + ) { if !emulator.driver.hooks_locked { - emulator.modules.pre_exec_all(input); + emulator.modules.pre_exec_all(input, state); } let input_location = { emulator.driver.input_location.get().cloned() }; @@ -181,12 +193,15 @@ where emulator: &mut Emulator, input: &S::Input, observers: &mut OT, + state: &mut S, exit_kind: &mut ExitKind, ) where OT: ObserversTuple, { if !emulator.driver.hooks_locked { - emulator.modules.post_exec_all(input, observers, exit_kind); + emulator + .modules + .post_exec_all(input, observers, state, exit_kind); } } diff --git a/libafl_qemu/src/emu/mod.rs b/libafl_qemu/src/emu/mod.rs index 0ae8e6f970..516e9b5389 100644 --- a/libafl_qemu/src/emu/mod.rs +++ b/libafl_qemu/src/emu/mod.rs @@ -421,21 +421,26 @@ where } /// First exec of Emulator, called before calling to user harness the first time - pub fn first_exec(&mut self) { - ED::first_harness_exec(self) + pub fn first_exec(&mut self, state: &mut S) { + ED::first_harness_exec(self, state) } /// Pre exec of Emulator, called before calling to user harness - pub fn pre_exec(&mut self, input: &S::Input) { - ED::pre_harness_exec(self, input) + pub fn pre_exec(&mut self, state: &mut S, input: &S::Input) { + ED::pre_harness_exec(self, state, input) } /// Post exec of Emulator, called before calling to user harness - pub fn post_exec(&mut self, input: &S::Input, observers: &mut OT, exit_kind: &mut ExitKind) - where + pub fn post_exec( + &mut self, + input: &S::Input, + observers: &mut OT, + state: &mut S, + exit_kind: &mut ExitKind, + ) where OT: ObserversTuple, { - ED::post_harness_exec(self, input, observers, exit_kind) + ED::post_harness_exec(self, input, observers, state, exit_kind) } } diff --git a/libafl_qemu/src/emu/snapshot.rs b/libafl_qemu/src/emu/snapshot.rs index f13f8316dc..8d9f1a2c55 100644 --- a/libafl_qemu/src/emu/snapshot.rs +++ b/libafl_qemu/src/emu/snapshot.rs @@ -6,7 +6,7 @@ use std::{ use crate::Qemu; pub trait IsSnapshotManager: Clone + Debug { - fn init(&mut self, _qemu :Qemu) {} + fn init(&mut self, _qemu: Qemu) {} fn save(&mut self, qemu: Qemu) -> SnapshotId; fn restore(&mut self, qemu: Qemu, snapshot_id: &SnapshotId) diff --git a/libafl_qemu/src/executor.rs b/libafl_qemu/src/executor.rs index 1d42d13372..3d2e5354e5 100644 --- a/libafl_qemu/src/executor.rs +++ b/libafl_qemu/src/executor.rs @@ -128,6 +128,7 @@ where timeout: Duration, ) -> Result where + ED: EmulatorDriver, EM: EventFirer + EventRestarter, OF: Feedback, S: Unpin + State + HasExecutions + HasCorpus + HasSolutions, @@ -211,11 +212,13 @@ where input: &Self::Input, ) -> Result { if self.first_exec { - self.inner.exposed_executor_state_mut().first_exec(); + self.inner.exposed_executor_state_mut().first_exec(state); self.first_exec = false; } - self.inner.exposed_executor_state_mut().pre_exec(input); + self.inner + .exposed_executor_state_mut() + .pre_exec(state, input); let mut exit_kind = self.inner.run_target(fuzzer, state, mgr, input)?; diff --git a/libafl_qemu/src/modules/calls.rs b/libafl_qemu/src/modules/calls.rs index 33b905919e..0b85887c14 100644 --- a/libafl_qemu/src/modules/calls.rs +++ b/libafl_qemu/src/modules/calls.rs @@ -389,6 +389,7 @@ where T: CallTraceCollectorTuple + Debug, { type ModuleAddressFilter = StdAddressFilter; + #[cfg(emulation_mode = "systemmode")] type ModulePageFilter = NopPageFilter; fn init_module(&self, emulator_modules: &mut EmulatorModules) @@ -443,10 +444,12 @@ where &mut self.filter } + #[cfg(emulation_mode = "systemmode")] fn page_filter(&self) -> &Self::ModulePageFilter { &NopPageFilter } + #[cfg(emulation_mode = "systemmode")] fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { unsafe { NOP_PAGE_FILTER.get_mut() } } diff --git a/libafl_qemu/src/modules/cmplog.rs b/libafl_qemu/src/modules/cmplog.rs index 91cc9102b1..4601ec8d2e 100644 --- a/libafl_qemu/src/modules/cmplog.rs +++ b/libafl_qemu/src/modules/cmplog.rs @@ -72,6 +72,7 @@ where S: Unpin + UsesInput + HasMetadata, { type ModuleAddressFilter = StdAddressFilter; + #[cfg(emulation_mode = "systemmode")] type ModulePageFilter = NopPageFilter; fn first_exec(&mut self, _state: &mut S, emulator_modules: &mut EmulatorModules) @@ -95,10 +96,12 @@ where &mut self.address_filter } + #[cfg(emulation_mode = "systemmode")] fn page_filter(&self) -> &Self::ModulePageFilter { &NopPageFilter } + #[cfg(emulation_mode = "systemmode")] fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { unsafe { NOP_PAGE_FILTER.get_mut() } } @@ -132,6 +135,7 @@ where S: Unpin + UsesInput + HasMetadata, { type ModuleAddressFilter = StdAddressFilter; + #[cfg(emulation_mode = "systemmode")] type ModulePageFilter = NopPageFilter; const HOOKS_DO_SIDE_EFFECTS: bool = false; @@ -157,10 +161,12 @@ where &mut self.address_filter } + #[cfg(emulation_mode = "systemmode")] fn page_filter(&self) -> &Self::ModulePageFilter { &NopPageFilter } + #[cfg(emulation_mode = "systemmode")] fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { unsafe { NOP_PAGE_FILTER.get_mut() } } @@ -381,6 +387,7 @@ where S: Unpin + UsesInput, { type ModuleAddressFilter = StdAddressFilter; + #[cfg(emulation_mode = "systemmode")] type ModulePageFilter = NopPageFilter; fn first_exec(&mut self, _state: &mut S, emulator_modules: &mut EmulatorModules) @@ -402,10 +409,12 @@ where &mut self.address_filter } + #[cfg(emulation_mode = "systemmode")] fn page_filter(&self) -> &Self::ModulePageFilter { &NopPageFilter } + #[cfg(emulation_mode = "systemmode")] fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { &mut NopPageFilter } diff --git a/libafl_qemu/src/modules/edges.rs b/libafl_qemu/src/modules/edges.rs index 9013816958..ac90605223 100644 --- a/libafl_qemu/src/modules/edges.rs +++ b/libafl_qemu/src/modules/edges.rs @@ -2,9 +2,9 @@ use std::{cell::UnsafeCell, cmp::max, fmt::Debug}; use hashbrown::{hash_map::Entry, HashMap}; use libafl::{inputs::UsesInput, HasMetadata}; -use libafl_qemu_sys::GuestAddr; #[cfg(emulation_mode = "systemmode")] use libafl_qemu_sys::GuestPhysAddr; +use libafl_qemu_sys::{GuestAddr, GuestPhysAddr}; pub use libafl_targets::{ edges_map_mut_ptr, EDGES_MAP, EDGES_MAP_PTR, EDGES_MAP_SIZE_IN_USE, EDGES_MAP_SIZE_MAX, MAX_EDGES_FOUND, @@ -174,7 +174,6 @@ impl EdgeCoverageVariant for EdgeCoverageClassicVariant { Hook::Empty, ); - fn first_exec(&mut self, _state: &mut S, emulator_modules: &mut EmulatorModules) unsafe { libafl_qemu_sys::libafl_qemu_block_hook_set_jit( hook_id.0, @@ -404,6 +403,13 @@ where AF: AddressFilter, PF: PageFilter, { + #[cfg(emulation_mode = "usermode")] + #[must_use] + pub fn must_instrument(&self, addr: GuestAddr) -> bool { + self.address_filter.allowed(&addr) + } + + #[cfg(emulation_mode = "systemmode")] #[must_use] pub fn must_instrument(&self, addr: GuestAddr, page_id: Option) -> bool { if let Some(page_id) = page_id { @@ -422,6 +428,7 @@ where V: EdgeCoverageVariant + 'static, { type ModuleAddressFilter = AF; + #[cfg(emulation_mode = "systemmode")] type ModulePageFilter = PF; fn first_exec(&mut self, _state: &mut S, emulator_modules: &mut EmulatorModules) @@ -451,10 +458,12 @@ where &mut self.address_filter } + #[cfg(emulation_mode = "systemmode")] fn page_filter(&self) -> &Self::ModulePageFilter { &self.page_filter } + #[cfg(emulation_mode = "systemmode")] fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { &mut self.page_filter } @@ -477,7 +486,7 @@ where if let Some(h) = emulator_modules.get::>() { #[cfg(emulation_mode = "usermode")] { - if !h.must_instrument(src, None) && !h.must_instrument(dest, None) { + if !h.must_instrument(src) && !h.must_instrument(dest) { return None; } } @@ -547,7 +556,7 @@ where { if let Some(h) = emulator_modules.get::>() { #[cfg(emulation_mode = "usermode")] - if !h.must_instrument(src, None) && !h.must_instrument(dest, None) { + if !h.must_instrument(src) && !h.must_instrument(dest) { return None; } @@ -605,7 +614,7 @@ where if let Some(h) = emulator_modules.get::>() { #[cfg(emulation_mode = "usermode")] { - if !h.must_instrument(pc, None) { + if !h.must_instrument(pc) { return None; } } diff --git a/libafl_qemu/src/modules/mod.rs b/libafl_qemu/src/modules/mod.rs index 4cc990fde3..e902b6f0b2 100644 --- a/libafl_qemu/src/modules/mod.rs +++ b/libafl_qemu/src/modules/mod.rs @@ -39,6 +39,8 @@ where S: UsesInput, { type ModuleAddressFilter: AddressFilter; + + #[cfg(emulation_mode = "systemmode")] type ModulePageFilter: PageFilter; const HOOKS_DO_SIDE_EFFECTS: bool = true; @@ -90,7 +92,9 @@ where fn address_filter(&self) -> &Self::ModuleAddressFilter; fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter; + #[cfg(emulation_mode = "systemmode")] fn page_filter(&self) -> &Self::ModulePageFilter; + #[cfg(emulation_mode = "systemmode")] fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter; } @@ -105,11 +109,8 @@ where where ET: EmulatorModuleTuple; - fn first_exec_all( - &mut self, - emulator_modules: &mut EmulatorModules, - state: &mut S, - ) where + fn first_exec_all(&mut self, emulator_modules: &mut EmulatorModules, state: &mut S) + where ET: EmulatorModuleTuple; fn pre_exec_all( @@ -133,6 +134,7 @@ where fn allow_address_range_all(&mut self, address_range: Range); + #[cfg(emulation_mode = "systemmode")] fn allow_page_id_all(&mut self, page_id: GuestPhysAddr); } @@ -179,6 +181,7 @@ where fn allow_address_range_all(&mut self, _address_range: Range) {} + #[cfg(emulation_mode = "systemmode")] fn allow_page_id_all(&mut self, _page_id: GuestPhysAddr) {} } @@ -240,6 +243,7 @@ where self.1.allow_address_range_all(address_range) } + #[cfg(emulation_mode = "systemmode")] fn allow_page_id_all(&mut self, page_id: GuestPhysAddr) { self.0.page_filter_mut().allow(page_id.clone()); self.1.allow_page_id_all(page_id) @@ -406,6 +410,5 @@ impl PageFilter for NopPageFilter { } } -// static mut NOP_ADDRESS_FILTER: UnsafeCell = -// UnsafeCell::new(NopAddressFilter); +static mut NOP_ADDRESS_FILTER: UnsafeCell = UnsafeCell::new(NopAddressFilter); static mut NOP_PAGE_FILTER: UnsafeCell = UnsafeCell::new(NopPageFilter); diff --git a/libafl_qemu/src/modules/usermode/asan.rs b/libafl_qemu/src/modules/usermode/asan.rs index 15f356f380..d7b7e88eb0 100644 --- a/libafl_qemu/src/modules/usermode/asan.rs +++ b/libafl_qemu/src/modules/usermode/asan.rs @@ -14,8 +14,7 @@ use rangemap::RangeMap; use crate::{ modules::{ calls::FullBacktraceCollector, snapshot::SnapshotModule, EmulatorModule, - EmulatorModuleTuple, HasInstrumentationFilter, IsFilter, - QemuInstrumentationAddressRangeFilter, + EmulatorModuleTuple, }, qemu::{MemAccessInfo, QemuInitError}, sys::TCGTemp, @@ -154,6 +153,7 @@ use object::{Object, ObjectSection}; use crate::{ emu::EmulatorModules, + modules::{AddressFilter, StdAddressFilter}, qemu::{Hook, QemuHooks, SyscallHookResult}, }; @@ -739,23 +739,19 @@ pub struct AsanModule { detect_leaks: bool, empty: bool, rt: Pin>, - filter: QemuInstrumentationAddressRangeFilter, + filter: StdAddressFilter, } impl AsanModule { #[must_use] pub fn default(rt: Pin>) -> Self { - Self::new( - rt, - QemuInstrumentationAddressRangeFilter::None, - QemuAsanOptions::Snapshot, - ) + Self::new(rt, StdAddressFilter::default(), QemuAsanOptions::Snapshot) } #[must_use] pub fn new( mut rt: Pin>, - filter: QemuInstrumentationAddressRangeFilter, + filter: StdAddressFilter, options: QemuAsanOptions, ) -> Self { assert!(unsafe { ASAN_INITED }, "The ASan runtime is not initialized, use init_qemu_with_asan(...) instead of just Qemu::init(...)"); @@ -778,7 +774,7 @@ impl AsanModule { #[must_use] pub fn with_error_callback( mut rt: Pin>, - filter: QemuInstrumentationAddressRangeFilter, + filter: StdAddressFilter, error_callback: AsanErrorCallback, options: QemuAsanOptions, ) -> Self { @@ -803,7 +799,7 @@ impl AsanModule { #[must_use] pub fn with_asan_report( rt: Pin>, - filter: QemuInstrumentationAddressRangeFilter, + filter: StdAddressFilter, options: QemuAsanOptions, ) -> Self { Self::with_error_callback(rt, filter, Box::new(asan_report), options) @@ -811,7 +807,7 @@ impl AsanModule { #[must_use] pub fn must_instrument(&self, addr: GuestAddr) -> bool { - self.filter.allowed(addr) + self.filter.allowed(&addr) } #[must_use] @@ -913,20 +909,11 @@ impl AsanModule { } } -impl HasInstrumentationFilter for AsanModule { - fn filter(&self) -> &QemuInstrumentationAddressRangeFilter { - &self.filter - } - - fn filter_mut(&mut self) -> &mut QemuInstrumentationAddressRangeFilter { - &mut self.filter - } -} - impl EmulatorModule for AsanModule where S: Unpin + UsesInput, { + type ModuleAddressFilter = StdAddressFilter; const HOOKS_DO_SIDE_EFFECTS: bool = false; fn init_module(&self, emulator_modules: &mut EmulatorModules) @@ -1004,6 +991,14 @@ where *exit_kind = ExitKind::Crash; } } + + fn address_filter(&self) -> &Self::ModuleAddressFilter { + &self.filter + } + + fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + &mut self.filter + } } pub fn oncrash_asan(emulator_modules: &mut EmulatorModules, target_sig: i32) diff --git a/libafl_qemu/src/modules/usermode/asan_guest.rs b/libafl_qemu/src/modules/usermode/asan_guest.rs index bfb05a4ef0..ad591fe3e2 100644 --- a/libafl_qemu/src/modules/usermode/asan_guest.rs +++ b/libafl_qemu/src/modules/usermode/asan_guest.rs @@ -14,10 +14,7 @@ use libafl_qemu_sys::{GuestAddr, MapInfo}; use crate::sys::libafl_tcg_gen_asan; use crate::{ emu::EmulatorModules, - modules::{ - EmulatorModule, EmulatorModuleTuple, HasInstrumentationFilter, IsFilter, - QemuInstrumentationAddressRangeFilter, - }, + modules::{AddressFilter, EmulatorModule, EmulatorModuleTuple, StdAddressFilter}, qemu::{Hook, MemAccessInfo, Qemu, QemuInitError}, sys::TCGTemp, }; @@ -121,13 +118,13 @@ impl From<&MapInfo> for QemuAsanGuestMapping { } #[derive(Debug)] -pub struct AsanGuestModule { - filter: QemuInstrumentationAddressRangeFilter, +pub struct AsanGuestModule { + filter: F, mappings: Vec, } #[cfg(any(cpu_target = "aarch64", cpu_target = "x86_64", feature = "clippy"))] -impl AsanGuestModule { +impl AsanGuestModule { const HIGH_SHADOW_START: GuestAddr = 0x02008fff7000; const HIGH_SHADOW_END: GuestAddr = 0x10007fff7fff; const LOW_SHADOW_START: GuestAddr = 0x00007fff8000; @@ -140,21 +137,26 @@ impl AsanGuestModule { cpu_target = "mips", cpu_target = "ppc" ))] -impl AsanGuestModule { +impl AsanGuestModule { const HIGH_SHADOW_START: GuestAddr = 0x28000000; const HIGH_SHADOW_END: GuestAddr = 0x3fffffff; const LOW_SHADOW_START: GuestAddr = 0x20000000; const LOW_SHADOW_END: GuestAddr = 0x23ffffff; } -impl AsanGuestModule { +impl AsanGuestModule { #[must_use] pub fn default(emu: &Qemu, asan: String) -> Self { - Self::new(emu, asan, QemuInstrumentationAddressRangeFilter::None) + Self::new(emu, asan, StdAddressFilter::default()) } +} +impl AsanGuestModule +where + F: AddressFilter, +{ #[must_use] - pub fn new(emu: &Qemu, asan: String, filter: QemuInstrumentationAddressRangeFilter) -> Self { + pub fn new(emu: &Qemu, asan: String, filter: F) -> Self { for mapping in emu.mappings() { println!("mapping: {mapping:#?}"); } @@ -193,21 +195,11 @@ impl AsanGuestModule { #[must_use] pub fn must_instrument(&self, addr: GuestAddr) -> bool { - self.filter.allowed(addr) + self.filter.allowed(&addr) } } -impl HasInstrumentationFilter for AsanGuestModule { - fn filter(&self) -> &QemuInstrumentationAddressRangeFilter { - &self.filter - } - - fn filter_mut(&mut self) -> &mut QemuInstrumentationAddressRangeFilter { - &mut self.filter - } -} - -fn gen_readwrite_guest_asan( +fn gen_readwrite_guest_asan( emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, @@ -215,10 +207,11 @@ fn gen_readwrite_guest_asan( info: MemAccessInfo, ) -> Option where + F: AddressFilter, S: Unpin + UsesInput, ET: EmulatorModuleTuple, { - let h = emulator_modules.get_mut::().unwrap(); + let h = emulator_modules.get_mut::>().unwrap(); if !h.must_instrument(pc) { return None; } @@ -269,17 +262,20 @@ fn guest_trace_error_n_asan( panic!("I really shouldn't be here either"); } -impl EmulatorModule for AsanGuestModule +impl EmulatorModule for AsanGuestModule where + F: AddressFilter, S: Unpin + UsesInput, { + type ModuleAddressFilter = F; + fn first_exec(&mut self, _state: &mut S, emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple, S: Unpin + UsesInput, { emulator_modules.reads( - Hook::Function(gen_readwrite_guest_asan::), + Hook::Function(gen_readwrite_guest_asan::), Hook::Function(guest_trace_error_asan::), Hook::Function(guest_trace_error_asan::), Hook::Function(guest_trace_error_asan::), @@ -288,7 +284,7 @@ where ); emulator_modules.writes( - Hook::Function(gen_readwrite_guest_asan::), + Hook::Function(gen_readwrite_guest_asan::), Hook::Function(guest_trace_error_asan::), Hook::Function(guest_trace_error_asan::), Hook::Function(guest_trace_error_asan::), @@ -296,4 +292,12 @@ where Hook::Function(guest_trace_error_n_asan::), ); } + + fn address_filter(&self) -> &Self::ModuleAddressFilter { + &self.filter + } + + fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + &mut self.filter + } } diff --git a/libafl_qemu/src/modules/usermode/drcov.rs b/libafl_qemu/src/modules/usermode/drcov.rs index 2755560ac9..145e4640a3 100644 --- a/libafl_qemu/src/modules/usermode/drcov.rs +++ b/libafl_qemu/src/modules/usermode/drcov.rs @@ -9,10 +9,7 @@ use serde::{Deserialize, Serialize}; use crate::{ emu::EmulatorModules, - modules::{ - EmulatorModule, EmulatorModuleTuple, HasInstrumentationFilter, IsFilter, - QemuInstrumentationAddressRangeFilter, - }, + modules::{AddressFilter, EmulatorModule, EmulatorModuleTuple}, qemu::Hook, }; @@ -39,22 +36,21 @@ impl DrCovMetadata { libafl_bolts::impl_serdeany!(DrCovMetadata); #[derive(Debug)] -pub struct DrCovModule { - filter: QemuInstrumentationAddressRangeFilter, +pub struct DrCovModule { + filter: F, module_mapping: RangeMap, filename: PathBuf, full_trace: bool, drcov_len: usize, } -impl DrCovModule { +impl DrCovModule +where + F: AddressFilter, +{ #[must_use] #[allow(clippy::let_underscore_untyped)] - pub fn new( - filter: QemuInstrumentationAddressRangeFilter, - filename: PathBuf, - full_trace: bool, - ) -> Self { + pub fn new(filter: F, filename: PathBuf, full_trace: bool) -> Self { if full_trace { let _ = DRCOV_IDS.lock().unwrap().insert(vec![]); } @@ -71,32 +67,25 @@ impl DrCovModule { #[must_use] pub fn must_instrument(&self, addr: GuestAddr) -> bool { - self.filter.allowed(addr) - } -} - -impl HasInstrumentationFilter for DrCovModule { - fn filter(&self) -> &QemuInstrumentationAddressRangeFilter { - &self.filter - } - - fn filter_mut(&mut self) -> &mut QemuInstrumentationAddressRangeFilter { - &mut self.filter + self.filter.allowed(&addr) } } -impl EmulatorModule for DrCovModule +impl EmulatorModule for DrCovModule where + F: AddressFilter, S: Unpin + UsesInput + HasMetadata, { + type ModuleAddressFilter = F; + fn init_module(&self, emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple, { emulator_modules.blocks( - Hook::Function(gen_unique_block_ids::), - Hook::Function(gen_block_lengths::), - Hook::Function(exec_trace_block::), + Hook::Function(gen_unique_block_ids::), + Hook::Function(gen_block_lengths::), + Hook::Function(exec_trace_block::), ); } @@ -208,18 +197,27 @@ where self.drcov_len = DRCOV_MAP.lock().unwrap().as_ref().unwrap().len(); } } + + fn address_filter(&self) -> &Self::ModuleAddressFilter { + &self.filter + } + + fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + &mut self.filter + } } -pub fn gen_unique_block_ids( +pub fn gen_unique_block_ids( emulator_modules: &mut EmulatorModules, state: Option<&mut S>, pc: GuestAddr, ) -> Option where + F: AddressFilter, S: Unpin + UsesInput + HasMetadata, ET: EmulatorModuleTuple, { - let drcov_module = emulator_modules.get::().unwrap(); + let drcov_module = emulator_modules.get::>().unwrap(); if !drcov_module.must_instrument(pc) { return None; } @@ -258,16 +256,17 @@ where } } -pub fn gen_block_lengths( +pub fn gen_block_lengths( emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, pc: GuestAddr, block_length: GuestUsize, ) where + F: AddressFilter, S: Unpin + UsesInput + HasMetadata, ET: EmulatorModuleTuple, { - let drcov_module = emulator_modules.get::().unwrap(); + let drcov_module = emulator_modules.get::>().unwrap(); if !drcov_module.must_instrument(pc) { return; } @@ -279,15 +278,16 @@ pub fn gen_block_lengths( .insert(pc, block_length); } -pub fn exec_trace_block( +pub fn exec_trace_block( emulator_modules: &mut EmulatorModules, _state: Option<&mut S>, id: u64, ) where + F: AddressFilter, ET: EmulatorModuleTuple, S: Unpin + UsesInput + HasMetadata, { - if emulator_modules.get::().unwrap().full_trace { + if emulator_modules.get::>().unwrap().full_trace { DRCOV_IDS.lock().unwrap().as_mut().unwrap().push(id); } } diff --git a/libafl_qemu/src/modules/usermode/injections.rs b/libafl_qemu/src/modules/usermode/injections.rs index dcc6fc0c9f..3fc508a243 100644 --- a/libafl_qemu/src/modules/usermode/injections.rs +++ b/libafl_qemu/src/modules/usermode/injections.rs @@ -23,7 +23,7 @@ use crate::SYS_execve; use crate::{ elf::EasyElf, emu::EmulatorModules, - modules::{EmulatorModule, EmulatorModuleTuple}, + modules::{EmulatorModule, EmulatorModuleTuple, NopAddressFilter, NOP_ADDRESS_FILTER}, qemu::{ArchExtras, Hook, SyscallHookResult}, CallingConvention, Qemu, }; @@ -260,6 +260,8 @@ impl EmulatorModule for InjectionModule where S: Unpin + UsesInput, { + type ModuleAddressFilter = NopAddressFilter; + fn init_module(&self, emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple, @@ -331,6 +333,14 @@ where } } } + + fn address_filter(&self) -> &Self::ModuleAddressFilter { + &NopAddressFilter + } + + fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + unsafe { NOP_ADDRESS_FILTER.get_mut() } + } } fn syscall_hook( diff --git a/libafl_qemu/src/modules/usermode/mod.rs b/libafl_qemu/src/modules/usermode/mod.rs index e98b81efbb..4afa1eac71 100644 --- a/libafl_qemu/src/modules/usermode/mod.rs +++ b/libafl_qemu/src/modules/usermode/mod.rs @@ -27,17 +27,3 @@ pub use asan::{init_qemu_with_asan, AsanModule}; pub mod asan_guest; #[cfg(not(cpu_target = "hexagon"))] pub use asan_guest::{init_qemu_with_asan_guest, AsanGuestModule}; - -use crate::modules::{HasInstrumentationFilter, QemuInstrumentationAddressRangeFilter}; - -pub trait StdInstrumentationFilter: - HasInstrumentationFilter + Debug -{ -} - -impl StdInstrumentationFilter for (Head, ()) where - Head: HasInstrumentationFilter + Debug -{ -} - -impl StdInstrumentationFilter for () {} diff --git a/libafl_qemu/src/modules/usermode/snapshot.rs b/libafl_qemu/src/modules/usermode/snapshot.rs index ff5bbbe777..6ee8671c68 100644 --- a/libafl_qemu/src/modules/usermode/snapshot.rs +++ b/libafl_qemu/src/modules/usermode/snapshot.rs @@ -21,7 +21,10 @@ use crate::SYS_mmap2; use crate::SYS_newfstatat; use crate::{ emu::EmulatorModules, - modules::{asan::AsanModule, EmulatorModule, EmulatorModuleTuple, Range}, + modules::{ + asan::AsanModule, EmulatorModule, EmulatorModuleTuple, NopAddressFilter, Range, + NOP_ADDRESS_FILTER, + }, qemu::{Hook, SyscallHookResult}, Qemu, SYS_brk, SYS_fstat, SYS_fstatfs, SYS_futex, SYS_getrandom, SYS_mprotect, SYS_mremap, SYS_munmap, SYS_pread64, SYS_read, SYS_readlinkat, SYS_statfs, @@ -667,6 +670,8 @@ impl EmulatorModule for SnapshotModule where S: Unpin + UsesInput, { + type ModuleAddressFilter = NopAddressFilter; + fn init_module(&self, emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple, @@ -703,6 +708,14 @@ where self.reset(emulator_modules.qemu()); } } + + fn address_filter(&self) -> &Self::ModuleAddressFilter { + &NopAddressFilter + } + + fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + unsafe { NOP_ADDRESS_FILTER.get_mut() } + } } pub fn trace_write_snapshot( diff --git a/libafl_qemu/src/qemu/mod.rs b/libafl_qemu/src/qemu/mod.rs index 582947a85b..494718c41f 100644 --- a/libafl_qemu/src/qemu/mod.rs +++ b/libafl_qemu/src/qemu/mod.rs @@ -668,7 +668,10 @@ impl Qemu { QemuExitReason::Breakpoint(bp_addr) }, libafl_qemu_sys::libafl_exit_reason_kind_SYNC_EXIT => QemuExitReason::SyncExit, + + #[cfg(emulation_mode = "systemmode")] libafl_qemu_sys::libafl_exit_reason_kind_TIMEOUT => QemuExitReason::Timeout, + _ => return Err(QemuExitError::UnknownKind), }) }