From e864bc28b15357f1925d6c9b4fdefe08ef2a2e66 Mon Sep 17 00:00:00 2001 From: Romain Malmain Date: Fri, 28 Feb 2025 15:44:22 +0100 Subject: [PATCH] Abort on triple fault for in process executors, refactor AddressFilter and PageFilter (#3026) * abort on triple fault in generic inprocess signal handler * refactor qemu filters --------- Co-authored-by: Toka --- .github/workflows/build_and_test.yml | 4 + .gitignore | 8 +- .../qemu_linux_kernel/src/fuzzer.rs | 6 +- .../qemu_linux_process/src/fuzzer.rs | 6 +- libafl/src/events/simple.rs | 11 +- libafl/src/executors/hooks/inprocess.rs | 34 ++- libafl/src/executors/hooks/mod.rs | 2 +- libafl/src/executors/hooks/unix.rs | 32 +- libafl/src/executors/hooks/windows.rs | 34 ++- libafl_bolts/src/os/mod.rs | 3 + libafl_qemu/src/command/mod.rs | 14 +- libafl_qemu/src/command/nyx.rs | 14 +- libafl_qemu/src/command/parser/mod.rs | 8 +- libafl_qemu/src/command/parser/nyx.rs | 8 +- libafl_qemu/src/modules/calls.rs | 43 +-- libafl_qemu/src/modules/cmplog.rs | 72 +++-- libafl_qemu/src/modules/drcov.rs | 21 +- libafl_qemu/src/modules/edges/mod.rs | 26 +- libafl_qemu/src/modules/usermode/asan.rs | 6 +- .../src/modules/usermode/asan_guest.rs | 6 +- .../src/modules/usermode/injections.rs | 6 +- libafl_qemu/src/modules/usermode/snapshot.rs | 6 +- libafl_qemu/src/modules/utils/filters.rs | 286 +++++++++++------- 23 files changed, 393 insertions(+), 263 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 60f729d0dd..76643e51dd 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -120,6 +120,10 @@ jobs: # ---- build normal and examples ---- - name: Run a normal build run: cargo build --verbose + - name: Run libafl_qemu usermode tests + run: cd libafl_qemu && cargo test + - name: Run libafl_qemu systemmode tests + run: cd libafl_qemu && cargo test --no-default-features --features x86_64,systemmode - name: Build examples run: cargo build --examples --verbose diff --git a/.gitignore b/.gitignore index b87f3e393e..b9f06407c7 100644 --- a/.gitignore +++ b/.gitignore @@ -78,4 +78,10 @@ fuzzer_libpng* *.patch # Sometimes this happens -rustc-ice-* \ No newline at end of file +rustc-ice-* + +# perf files +*.mm_profdata + +# backup files +*.bak diff --git a/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs b/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs index 909f9e2a6d..704346da90 100644 --- a/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs +++ b/fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs @@ -41,7 +41,7 @@ use libafl_qemu::{ executor::QemuExecutor, modules::{ cmplog::CmpLogObserver, edges::StdEdgeCoverageClassicModule, - utils::filters::HasAddressFilterTuples, CmpLogModule, EmulatorModuleTuple, + utils::filters::HasAddressFilterTuple, CmpLogModule, EmulatorModuleTuple, }, FastSnapshotManager, NopSnapshotManager, QemuInitError, }; @@ -78,12 +78,12 @@ fn get_emulator( QemuInitError, > where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasAddressFilterTuple, I: HasTargetBytes + Unpin, S: HasExecutions + Unpin, { // Allow linux process address space addresses as feedback - modules.allow_address_range_all(LINUX_PROCESS_ADDRESS_RANGE); + modules.allow_address_range_all(&LINUX_PROCESS_ADDRESS_RANGE); Emulator::builder() .qemu_parameters(args) diff --git a/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs b/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs index 1253fea6e6..badb02d59c 100644 --- a/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs +++ b/fuzzers/full_system/qemu_linux_process/src/fuzzer.rs @@ -41,7 +41,7 @@ use libafl_qemu::{ executor::QemuExecutor, modules::{ cmplog::CmpLogObserver, edges::StdEdgeCoverageClassicModule, - utils::filters::HasAddressFilterTuples, CmpLogModule, EmulatorModuleTuple, + utils::filters::HasAddressFilterTuple, CmpLogModule, EmulatorModuleTuple, }, FastSnapshotManager, NopSnapshotManager, QemuInitError, QemuSnapshotManager, }; @@ -78,12 +78,12 @@ fn get_emulator( QemuInitError, > where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasAddressFilterTuple, I: HasTargetBytes + Unpin, S: HasExecutions + Unpin, { // Allow linux process address space addresses as feedback - modules.allow_address_range_all(LINUX_PROCESS_ADDRESS_RANGE); + modules.allow_address_range_all(&LINUX_PROCESS_ADDRESS_RANGE); Emulator::builder() .qemu_parameters(args) diff --git a/libafl/src/events/simple.rs b/libafl/src/events/simple.rs index 7caeb629c9..5a4907baf7 100644 --- a/libafl/src/events/simple.rs +++ b/libafl/src/events/simple.rs @@ -8,10 +8,10 @@ use core::{fmt::Debug, marker::PhantomData, time::Duration}; use libafl_bolts::ClientId; #[cfg(all(feature = "std", any(windows, not(feature = "fork"))))] use libafl_bolts::os::startable_self; -#[cfg(all(unix, feature = "std", not(miri)))] -use libafl_bolts::os::unix_signals::setup_signal_handler; #[cfg(all(feature = "std", feature = "fork", unix))] use libafl_bolts::os::{ForkResult, fork}; +#[cfg(all(unix, feature = "std", not(miri)))] +use libafl_bolts::os::{SIGNAL_RECURSION_EXIT, unix_signals::setup_signal_handler}; #[cfg(feature = "std")] use libafl_bolts::{ os::CTRL_C_EXIT, @@ -510,6 +510,13 @@ where return Err(Error::shutting_down()); } + #[cfg(all(unix, feature = "std"))] + if child_status == SIGNAL_RECURSION_EXIT { + return Err(Error::illegal_state( + "The client is stuck in an unexpected signal handler recursion. It is most likely a fuzzer bug.", + )); + } + #[expect(clippy::manual_assert)] if !staterestorer.has_content() { #[cfg(unix)] diff --git a/libafl/src/executors/hooks/inprocess.rs b/libafl/src/executors/hooks/inprocess.rs index f09c7512fb..404b8d4812 100644 --- a/libafl/src/executors/hooks/inprocess.rs +++ b/libafl/src/executors/hooks/inprocess.rs @@ -355,7 +355,9 @@ pub struct InProcessExecutorHandlerData { /// the pointer to the executor pub executor_ptr: *const c_void, pub(crate) current_input_ptr: *const c_void, - pub(crate) in_handler: bool, + + #[cfg(feature = "std")] + pub(crate) signal_handler_depth: usize, /// The timeout handler #[cfg(feature = "std")] @@ -376,6 +378,9 @@ unsafe impl Send for InProcessExecutorHandlerData {} unsafe impl Sync for InProcessExecutorHandlerData {} impl InProcessExecutorHandlerData { + #[cfg(feature = "std")] + const SIGNAL_HANDLER_MAX_DEPTH: usize = 3; + /// # Safety /// Only safe if not called twice and if the executor is not used from another borrow after this. #[cfg(all(feature = "std", any(unix, windows)))] @@ -418,11 +423,19 @@ impl InProcessExecutorHandlerData { !self.current_input_ptr.is_null() } + /// Returns true if signal handling max depth has been reached, false otherwise #[cfg(all(feature = "std", any(unix, windows)))] - pub(crate) fn set_in_handler(&mut self, v: bool) -> bool { - let old = self.in_handler; - self.in_handler = v; - old + pub(crate) fn signal_handler_enter(&mut self) -> (bool, usize) { + self.signal_handler_depth += 1; + ( + self.signal_handler_depth >= Self::SIGNAL_HANDLER_MAX_DEPTH, + self.signal_handler_depth, + ) + } + + #[cfg(all(feature = "std", any(unix, windows)))] + pub(crate) fn signal_handler_exit(&mut self) { + self.signal_handler_depth -= 1; } /// if data is valid, safely report a crash and return true. @@ -500,7 +513,8 @@ pub static mut GLOBAL_STATE: InProcessExecutorHandlerData = InProcessExecutorHan // The current input for signal handling current_input_ptr: ptr::null(), - in_handler: false, + #[cfg(feature = "std")] + signal_handler_depth: 0, // The crash handler fn #[cfg(feature = "std")] @@ -560,11 +574,3 @@ pub unsafe fn inprocess_get_executor<'a, E>() -> Option<&'a mut E> { pub unsafe fn inprocess_get_input<'a, I>() -> Option<&'a I> { unsafe { (GLOBAL_STATE.current_input_ptr as *const I).as_ref() } } - -/// Returns if we are executing in a crash/timeout handler -#[must_use] -pub fn inprocess_in_handler() -> bool { - // # Safety - // Safe because the state is set up and the handler is a single bool. Worst case we read an old value. - unsafe { GLOBAL_STATE.in_handler } -} diff --git a/libafl/src/executors/hooks/mod.rs b/libafl/src/executors/hooks/mod.rs index 187704bca6..c592a36b23 100644 --- a/libafl/src/executors/hooks/mod.rs +++ b/libafl/src/executors/hooks/mod.rs @@ -2,7 +2,7 @@ //! These will be executed right before and after the executor's harness run. /// windows crash/timeout handler and asan death callback -#[cfg(windows)] +#[cfg(all(windows, feature = "std"))] pub mod windows; /// *nix crash handler diff --git a/libafl/src/executors/hooks/unix.rs b/libafl/src/executors/hooks/unix.rs index c8ff701cc5..41f01b94d1 100644 --- a/libafl/src/executors/hooks/unix.rs +++ b/libafl/src/executors/hooks/unix.rs @@ -5,7 +5,10 @@ pub mod unix_signal_handler { use core::mem::transmute; use std::{io::Write, panic}; - use libafl_bolts::os::unix_signals::{Signal, SignalHandler, ucontext_t}; + use libafl_bolts::os::{ + SIGNAL_RECURSION_EXIT, + unix_signals::{Signal, SignalHandler, ucontext_t}, + }; use libc::siginfo_t; use crate::{ @@ -50,11 +53,13 @@ pub mod unix_signal_handler { ) { unsafe { let data = &raw mut GLOBAL_STATE; - let in_handler = (*data).set_in_handler(true); + let (max_depth_reached, signal_depth) = (*data).signal_handler_enter(); - if in_handler { - log::error!("We crashed inside a crash handler, but this should never happen!"); - libc::exit(56); + if max_depth_reached { + log::error!( + "The in process signal handler has been triggered {signal_depth} times recursively, which is not expected. Exiting with error code {SIGNAL_RECURSION_EXIT}..." + ); + libc::exit(SIGNAL_RECURSION_EXIT); } match signal { @@ -67,11 +72,11 @@ pub mod unix_signal_handler { _ => { if !(*data).crash_handler.is_null() { let func: HandlerFuncPtr = transmute((*data).crash_handler); - (func)(signal, info, context, data); + func(signal, info, context, data); } } } - (*data).set_in_handler(in_handler); + (*data).signal_handler_exit(); } } @@ -95,11 +100,13 @@ pub mod unix_signal_handler { panic::set_hook(Box::new(move |panic_info| unsafe { old_hook(panic_info); let data = &raw mut GLOBAL_STATE; - let in_handler = (*data).set_in_handler(true); + let (max_depth_reached, signal_depth) = (*data).signal_handler_enter(); - if in_handler { - log::error!("We crashed inside a crash panic hook, but this should never happen!"); - libc::exit(56); + if max_depth_reached { + log::error!( + "The in process signal handler has been triggered {signal_depth} times recursively, which is not expected. Exiting with error code {SIGNAL_RECURSION_EXIT}..." + ); + libc::exit(SIGNAL_RECURSION_EXIT); } if (*data).is_valid() { @@ -121,7 +128,8 @@ pub mod unix_signal_handler { libc::_exit(128 + 6); // SIGABRT exit code } - (*data).set_in_handler(in_handler); + + (*data).signal_handler_exit(); })); } diff --git a/libafl/src/executors/hooks/windows.rs b/libafl/src/executors/hooks/windows.rs index 78fc20b37a..9fcf8b869e 100644 --- a/libafl/src/executors/hooks/windows.rs +++ b/libafl/src/executors/hooks/windows.rs @@ -1,9 +1,9 @@ /// In-Process crash handling for `Windows` -#[cfg(all(windows, feature = "std"))] pub mod windows_asan_handler { use alloc::string::String; use core::sync::atomic::{Ordering, compiler_fence}; + use libafl_bolts::os::SIGNAL_RECURSION_EXIT; use windows::Win32::System::Threading::{ CRITICAL_SECTION, EnterCriticalSection, ExitProcess, LeaveCriticalSection, }; @@ -35,13 +35,13 @@ pub mod windows_asan_handler { { unsafe { let data = &raw mut GLOBAL_STATE; - let in_handler = (*data).set_in_handler(true); + let (max_depth_reached, _signal_depth) = (*data).signal_handler_enter(); - if in_handler { + if max_depth_reached { log::error!( "We crashed inside a asan death handler, but this should never happen!" ); - ExitProcess(56); + ExitProcess(SIGNAL_RECURSION_EXIT as u32); } // Have we set a timer_before? @@ -109,7 +109,6 @@ pub mod windows_asan_handler { } } -#[cfg(all(windows, feature = "std"))] /// The module to take care of windows crash or timeouts pub mod windows_exception_handler { #[cfg(feature = "std")] @@ -126,9 +125,12 @@ pub mod windows_exception_handler { #[cfg(feature = "std")] use std::panic; - use libafl_bolts::os::windows_exceptions::{ - CRASH_EXCEPTIONS, EXCEPTION_HANDLERS_SIZE, EXCEPTION_POINTERS, ExceptionCode, - ExceptionHandler, + use libafl_bolts::os::{ + SIGNAL_RECURSION_EXIT, + windows_exceptions::{ + CRASH_EXCEPTIONS, EXCEPTION_HANDLERS_SIZE, EXCEPTION_POINTERS, ExceptionCode, + ExceptionHandler, + }, }; use windows::Win32::System::Threading::{ CRITICAL_SECTION, EnterCriticalSection, ExitProcess, LeaveCriticalSection, @@ -168,18 +170,18 @@ pub mod windows_exception_handler { ) { unsafe { let data = &raw mut GLOBAL_STATE; - let in_handler = (*data).set_in_handler(true); + let (max_depth_reached, _signal_depth) = (*data).signal_handler_enter(); - if in_handler { + if max_depth_reached { log::error!("We crashed inside a crash handler, but this should never happen!"); - ExitProcess(56); + ExitProcess(SIGNAL_RECURSION_EXIT as u32); } if !(*data).crash_handler.is_null() { let func: HandlerFuncPtr = transmute((*data).crash_handler); (func)(exception_pointers, data); } - (*data).set_in_handler(in_handler); + (*data).signal_handler_exit(); } } @@ -208,11 +210,11 @@ pub mod windows_exception_handler { let old_hook = panic::take_hook(); panic::set_hook(Box::new(move |panic_info| unsafe { let data = &raw mut GLOBAL_STATE; - let in_handler = (*data).set_in_handler(true); + let (max_depth_reached, _signal_depth) = (*data).signal_handler_enter(); - if in_handler { + if max_depth_reached { log::error!("We crashed inside a crash handler, but this should never happen!"); - ExitProcess(56); + ExitProcess(SIGNAL_RECURSION_EXIT as u32); } // Have we set a timer_before? @@ -252,7 +254,7 @@ pub mod windows_exception_handler { ExitProcess(1); } old_hook(panic_info); - (*data).set_in_handler(in_handler); + (*data).signal_handler_exit(); })); } diff --git a/libafl_bolts/src/os/mod.rs b/libafl_bolts/src/os/mod.rs index f15e33d01b..1f118ff174 100644 --- a/libafl_bolts/src/os/mod.rs +++ b/libafl_bolts/src/os/mod.rs @@ -48,6 +48,9 @@ pub struct ChildHandle { pub pid: pid_t, } +/// The special exit code when the target signal handler is crashing recursively +pub const SIGNAL_RECURSION_EXIT: i32 = 101; + #[cfg(unix)] impl ChildHandle { /// Block until the child exited and the status code becomes available diff --git a/libafl_qemu/src/command/mod.rs b/libafl_qemu/src/command/mod.rs index e17ded0c40..341c652241 100644 --- a/libafl_qemu/src/command/mod.rs +++ b/libafl_qemu/src/command/mod.rs @@ -25,7 +25,7 @@ use crate::{ VersionCommandParser, }, get_exit_arch_regs, - modules::{EmulatorModuleTuple, utils::filters::HasAddressFilterTuples}, + modules::{EmulatorModuleTuple, utils::filters::HasStdFiltersTuple}, sync_exit::ExitArgs, }; @@ -96,7 +96,7 @@ macro_rules! define_std_command_manager { impl CommandManager for $name where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: HasTargetBytes + Unpin, S: Unpin, SM: IsSnapshotManager, @@ -125,7 +125,7 @@ macro_rules! define_std_command_manager { impl IsCommand, StdEmulatorDriver, ET, I, S, SM> for [<$name Commands>] where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: HasTargetBytes + Unpin, S: Unpin, SM: IsSnapshotManager, @@ -383,7 +383,7 @@ pub struct StartCommand { impl IsCommand, StdEmulatorDriver, ET, I, S, SM> for StartCommand where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: HasTargetBytes + Unpin, S: Unpin, SM: IsSnapshotManager, @@ -544,7 +544,7 @@ pub struct PageAllowCommand { #[cfg(feature = "systemmode")] impl IsCommand for PageAllowCommand where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: Unpin, S: Unpin, { @@ -572,7 +572,7 @@ pub struct AddressAllowCommand { } impl IsCommand for AddressAllowCommand where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: Unpin, S: Unpin, { @@ -589,7 +589,7 @@ where ) -> Result>, EmulatorDriverError> { emu.modules_mut() .modules_mut() - .allow_address_range_all(self.address_range.clone()); + .allow_address_range_all(&self.address_range); Ok(None) } } diff --git a/libafl_qemu/src/command/nyx.rs b/libafl_qemu/src/command/nyx.rs index 6b0260097f..e854c811af 100644 --- a/libafl_qemu/src/command/nyx.rs +++ b/libafl_qemu/src/command/nyx.rs @@ -34,7 +34,7 @@ use crate::{ }, }, get_exit_arch_regs, - modules::{EmulatorModuleTuple, utils::filters::HasAddressFilterTuples}, + modules::{EmulatorModuleTuple, utils::filters::HasStdFiltersTuple}, sync_exit::ExitArgs, }; @@ -99,7 +99,7 @@ macro_rules! define_nyx_command_manager { impl CommandManager for $name where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: HasTargetBytes + Unpin, S: Unpin, SM: IsSnapshotManager, @@ -134,7 +134,7 @@ macro_rules! define_nyx_command_manager { impl IsCommand, NyxEmulatorDriver, ET, I, S, SM> for [<$name Commands>] where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: HasTargetBytes + Unpin, S: Unpin, SM: IsSnapshotManager, @@ -296,7 +296,7 @@ pub struct NextPayloadCommand; impl IsCommand, NyxEmulatorDriver, ET, I, S, SM> for NextPayloadCommand where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: HasTargetBytes + Unpin, S: Unpin, SM: IsSnapshotManager, @@ -360,7 +360,7 @@ pub struct SubmitCR3Command; impl IsCommand, NyxEmulatorDriver, ET, I, S, SM> for SubmitCR3Command where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: HasTargetBytes + Unpin, S: Unpin, SM: IsSnapshotManager, @@ -408,7 +408,7 @@ impl RangeSubmitCommand { impl IsCommand, NyxEmulatorDriver, ET, I, S, SM> for RangeSubmitCommand where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: HasTargetBytes + Unpin, S: Unpin, SM: IsSnapshotManager, @@ -440,7 +440,7 @@ where emu.modules_mut() .modules_mut() - .allow_address_range_all(self.allowed_range.clone()); + .allow_address_range_all(&self.allowed_range); Ok(None) } } diff --git a/libafl_qemu/src/command/parser/mod.rs b/libafl_qemu/src/command/parser/mod.rs index a7ac95f061..182306399d 100644 --- a/libafl_qemu/src/command/parser/mod.rs +++ b/libafl_qemu/src/command/parser/mod.rs @@ -12,7 +12,7 @@ use crate::{ LoadCommand, LqprintfCommand, NativeExitKind, SaveCommand, StartCommand, StdCommandManager, TestCommand, VersionCommand, bindings, }, - modules::{EmulatorModuleTuple, utils::filters::HasAddressFilterTuples}, + modules::{EmulatorModuleTuple, utils::filters::HasStdFiltersTuple}, sync_exit::ExitArgs, }; @@ -92,7 +92,7 @@ pub struct StartPhysCommandParser; impl NativeCommandParser, StdEmulatorDriver, ET, I, S, SM> for StartPhysCommandParser where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: HasTargetBytes + Unpin, S: Unpin, SM: IsSnapshotManager, @@ -121,7 +121,7 @@ pub struct StartVirtCommandParser; impl NativeCommandParser, StdEmulatorDriver, ET, I, S, SM> for StartVirtCommandParser where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: HasTargetBytes + Unpin, S: Unpin, SM: IsSnapshotManager, @@ -242,7 +242,7 @@ pub struct VaddrFilterAllowRangeCommandParser; impl NativeCommandParser for VaddrFilterAllowRangeCommandParser where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: Unpin, S: Unpin, { diff --git a/libafl_qemu/src/command/parser/nyx.rs b/libafl_qemu/src/command/parser/nyx.rs index 423f2daec8..b6ff91cb14 100644 --- a/libafl_qemu/src/command/parser/nyx.rs +++ b/libafl_qemu/src/command/parser/nyx.rs @@ -17,7 +17,7 @@ use crate::{ }, parser::NativeCommandParser, }, - modules::{EmulatorModuleTuple, utils::filters::HasAddressFilterTuples}, + modules::{EmulatorModuleTuple, utils::filters::HasStdFiltersTuple}, sync_exit::ExitArgs, }; @@ -81,7 +81,7 @@ pub struct SubmitCR3CommandParser; impl NativeCommandParser, NyxEmulatorDriver, ET, I, S, SM> for SubmitCR3CommandParser where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: HasTargetBytes + Unpin, S: Unpin, SM: IsSnapshotManager, @@ -101,7 +101,7 @@ pub struct RangeSubmitCommandParser; impl NativeCommandParser, NyxEmulatorDriver, ET, I, S, SM> for RangeSubmitCommandParser where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: HasTargetBytes + Unpin, S: Unpin, SM: IsSnapshotManager, @@ -189,7 +189,7 @@ pub struct NextPayloadCommandParser; impl NativeCommandParser, NyxEmulatorDriver, ET, I, S, SM> for NextPayloadCommandParser where - ET: EmulatorModuleTuple + HasAddressFilterTuples, + ET: EmulatorModuleTuple + HasStdFiltersTuple, I: HasTargetBytes + Unpin, S: Unpin, SM: IsSnapshotManager, diff --git a/libafl_qemu/src/modules/calls.rs b/libafl_qemu/src/modules/calls.rs index 49e84fb31f..faad58073d 100644 --- a/libafl_qemu/src/modules/calls.rs +++ b/libafl_qemu/src/modules/calls.rs @@ -12,7 +12,7 @@ use thread_local::ThreadLocal; use super::utils::filters::HasAddressFilter; #[cfg(feature = "systemmode")] -use crate::modules::utils::filters::{NOP_PAGE_FILTER, NopPageFilter}; +use crate::modules::utils::filters::{HasPageFilter, NOP_PAGE_FILTER, NopPageFilter}; use crate::{ Qemu, capstone, modules::{ @@ -361,14 +361,18 @@ where iaddr += insn.bytes().len() as GuestAddr; #[cfg(feature = "usermode")] - code = unsafe { std::slice::from_raw_parts(qemu.g2h(iaddr), 512) }; + { + code = unsafe { std::slice::from_raw_parts(qemu.g2h(iaddr), 512) }; + } #[cfg(feature = "systemmode")] - if let Err(err) = qemu.read_mem(pc, code) { - // TODO handle faults - log::error!( - "gen_block_calls error 2: Failed to read mem at pc {pc:#x}: {err:?}" - ); - return None; + { + if let Err(err) = qemu.read_mem(pc, code) { + // TODO handle faults + log::error!( + "gen_block_calls error 2: Failed to read mem at pc {pc:#x}: {err:?}" + ); + return None; + } } } } @@ -459,24 +463,29 @@ impl HasAddressFilter for CallTracerModule where T: CallTraceCollectorTuple, { - type ModuleAddressFilter = StdAddressFilter; - #[cfg(feature = "systemmode")] - type ModulePageFilter = NopPageFilter; - fn address_filter(&self) -> &Self::ModuleAddressFilter { + type AddressFilter = StdAddressFilter; + + fn address_filter(&self) -> &Self::AddressFilter { &self.filter } - fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + fn address_filter_mut(&mut self) -> &mut Self::AddressFilter { &mut self.filter } +} - #[cfg(feature = "systemmode")] - fn page_filter(&self) -> &Self::ModulePageFilter { +#[cfg(feature = "systemmode")] +impl HasPageFilter for CallTracerModule +where + T: CallTraceCollectorTuple, +{ + type PageFilter = NopPageFilter; + + fn page_filter(&self) -> &Self::PageFilter { &NopPageFilter } - #[cfg(feature = "systemmode")] - fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { + fn page_filter_mut(&mut self) -> &mut Self::PageFilter { unsafe { (&raw mut NOP_PAGE_FILTER).as_mut().unwrap().get_mut() } } } diff --git a/libafl_qemu/src/modules/cmplog.rs b/libafl_qemu/src/modules/cmplog.rs index 4fee3e5525..0572036d59 100644 --- a/libafl_qemu/src/modules/cmplog.rs +++ b/libafl_qemu/src/modules/cmplog.rs @@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "usermode")] use crate::capstone; #[cfg(feature = "systemmode")] -use crate::modules::utils::filters::{NOP_PAGE_FILTER, NopPageFilter}; +use crate::modules::utils::filters::{HasPageFilter, NOP_PAGE_FILTER, NopPageFilter}; use crate::{ Qemu, emu::EmulatorModules, @@ -95,25 +95,26 @@ where } impl HasAddressFilter for CmpLogModule { - type ModuleAddressFilter = StdAddressFilter; - #[cfg(feature = "systemmode")] - type ModulePageFilter = NopPageFilter; + type AddressFilter = StdAddressFilter; - fn address_filter(&self) -> &Self::ModuleAddressFilter { + fn address_filter(&self) -> &Self::AddressFilter { &self.address_filter } - fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + fn address_filter_mut(&mut self) -> &mut Self::AddressFilter { &mut self.address_filter } +} - #[cfg(feature = "systemmode")] - fn page_filter(&self) -> &Self::ModulePageFilter { +#[cfg(feature = "systemmode")] +impl HasPageFilter for CmpLogModule { + type PageFilter = NopPageFilter; + + fn page_filter(&self) -> &Self::PageFilter { &NopPageFilter } - #[cfg(feature = "systemmode")] - fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { + fn page_filter_mut(&mut self) -> &mut Self::PageFilter { unsafe { (&raw mut NOP_PAGE_FILTER).as_mut().unwrap().get_mut() } } } @@ -167,25 +168,26 @@ where } impl HasAddressFilter for CmpLogChildModule { - type ModuleAddressFilter = StdAddressFilter; - #[cfg(feature = "systemmode")] - type ModulePageFilter = NopPageFilter; + type AddressFilter = StdAddressFilter; - fn address_filter(&self) -> &Self::ModuleAddressFilter { + fn address_filter(&self) -> &Self::AddressFilter { &self.address_filter } - fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + fn address_filter_mut(&mut self) -> &mut Self::AddressFilter { &mut self.address_filter } +} - #[cfg(feature = "systemmode")] - fn page_filter(&self) -> &Self::ModulePageFilter { +#[cfg(feature = "systemmode")] +impl HasPageFilter for CmpLogChildModule { + type PageFilter = NopPageFilter; + + fn page_filter(&self) -> &Self::PageFilter { &NopPageFilter } - #[cfg(feature = "systemmode")] - fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { + fn page_filter_mut(&mut self) -> &mut Self::PageFilter { unsafe { (&raw mut NOP_PAGE_FILTER).as_mut().unwrap().get_mut() } } } @@ -345,16 +347,18 @@ impl CmpLogRoutinesModule { #[allow(unused_mut)] // cfg dependent let mut code = { #[cfg(feature = "usermode")] - unsafe { - std::slice::from_raw_parts(qemu.g2h(pc), 512); + { + unsafe { std::slice::from_raw_parts(qemu.g2h(pc), 512) } } #[cfg(feature = "systemmode")] - &mut [0; 512] + { + &mut [0; 512] + } }; #[cfg(feature = "systemmode")] - unsafe { - qemu.read_mem(pc, code) - }; // TODO handle faults + { + unsafe { qemu.read_mem(pc, code) }; // TODO handle faults + } let mut iaddr = pc; @@ -389,11 +393,15 @@ impl CmpLogRoutinesModule { iaddr += insn.bytes().len() as GuestAddr; #[cfg(feature = "usermode")] - code = unsafe { std::slice::from_raw_parts(qemu.g2h(iaddr), 512) }; + { + code = unsafe { std::slice::from_raw_parts(qemu.g2h(iaddr), 512) }; + } #[cfg(feature = "systemmode")] - unsafe { - qemu.read_mem(pc, code); - } // TODO handle faults + { + unsafe { + qemu.read_mem(pc, code); + } // TODO handle faults + } } } @@ -425,15 +433,15 @@ where #[cfg(feature = "usermode")] impl HasAddressFilter for CmpLogRoutinesModule { - type ModuleAddressFilter = StdAddressFilter; + type AddressFilter = StdAddressFilter; #[cfg(feature = "systemmode")] type ModulePageFilter = NopPageFilter; - fn address_filter(&self) -> &Self::ModuleAddressFilter { + fn address_filter(&self) -> &Self::AddressFilter { &self.address_filter } - fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + fn address_filter_mut(&mut self) -> &mut Self::AddressFilter { &mut self.address_filter } diff --git a/libafl_qemu/src/modules/drcov.rs b/libafl_qemu/src/modules/drcov.rs index 492846a61a..9b48428f83 100644 --- a/libafl_qemu/src/modules/drcov.rs +++ b/libafl_qemu/src/modules/drcov.rs @@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize}; use super::utils::filters::HasAddressFilter; #[cfg(feature = "systemmode")] -use crate::modules::utils::filters::{NOP_PAGE_FILTER, NopPageFilter}; +use crate::modules::utils::filters::{HasPageFilter, NOP_PAGE_FILTER, NopPageFilter}; use crate::{ Qemu, emu::EmulatorModules, @@ -522,25 +522,26 @@ impl HasAddressFilter for DrCovModule where F: AddressFilter, { - type ModuleAddressFilter = F; - #[cfg(feature = "systemmode")] - type ModulePageFilter = NopPageFilter; + type AddressFilter = F; - fn address_filter(&self) -> &Self::ModuleAddressFilter { + fn address_filter(&self) -> &Self::AddressFilter { &self.filter } - fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + fn address_filter_mut(&mut self) -> &mut Self::AddressFilter { &mut self.filter } +} - #[cfg(feature = "systemmode")] - fn page_filter(&self) -> &Self::ModulePageFilter { +#[cfg(feature = "systemmode")] +impl HasPageFilter for DrCovModule { + type PageFilter = NopPageFilter; + + fn page_filter(&self) -> &Self::PageFilter { &NopPageFilter } - #[cfg(feature = "systemmode")] - fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { + fn page_filter_mut(&mut self) -> &mut Self::PageFilter { unsafe { (&raw mut NOP_PAGE_FILTER).as_mut().unwrap().get_mut() } } } diff --git a/libafl_qemu/src/modules/edges/mod.rs b/libafl_qemu/src/modules/edges/mod.rs index dbd28e7361..b7f571f5c0 100644 --- a/libafl_qemu/src/modules/edges/mod.rs +++ b/libafl_qemu/src/modules/edges/mod.rs @@ -35,6 +35,8 @@ pub use child::{ use libafl::observers::ConstLenMapObserver; use super::utils::filters::HasAddressFilter; +#[cfg(feature = "systemmode")] +use super::utils::filters::HasPageFilter; /// Standard edge coverage module, adapted to most use cases pub type StdEdgeCoverageModule = StdEdgeCoverageFullModule; @@ -366,27 +368,31 @@ impl HasAddressFilte for EdgeCoverageModule where AF: AddressFilter, - PF: PageFilter, { - type ModuleAddressFilter = AF; + type AddressFilter = AF; - #[cfg(feature = "systemmode")] - type ModulePageFilter = PF; - fn address_filter(&self) -> &Self::ModuleAddressFilter { + fn address_filter(&self) -> &Self::AddressFilter { &self.address_filter } - fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + fn address_filter_mut(&mut self) -> &mut Self::AddressFilter { &mut self.address_filter } +} - #[cfg(feature = "systemmode")] - fn page_filter(&self) -> &Self::ModulePageFilter { +#[cfg(feature = "systemmode")] +impl HasPageFilter + for EdgeCoverageModule +where + PF: PageFilter, +{ + type PageFilter = PF; + + fn page_filter(&self) -> &Self::PageFilter { &self.page_filter } - #[cfg(feature = "systemmode")] - fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { + fn page_filter_mut(&mut self) -> &mut Self::PageFilter { &mut self.page_filter } } diff --git a/libafl_qemu/src/modules/usermode/asan.rs b/libafl_qemu/src/modules/usermode/asan.rs index 1998ae78c8..13007e2870 100644 --- a/libafl_qemu/src/modules/usermode/asan.rs +++ b/libafl_qemu/src/modules/usermode/asan.rs @@ -1118,12 +1118,12 @@ where } impl HasAddressFilter for AsanModule { - type ModuleAddressFilter = StdAddressFilter; - fn address_filter(&self) -> &Self::ModuleAddressFilter { + type AddressFilter = StdAddressFilter; + fn address_filter(&self) -> &Self::AddressFilter { &self.filter } - fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + fn address_filter_mut(&mut self) -> &mut Self::AddressFilter { &mut self.filter } } diff --git a/libafl_qemu/src/modules/usermode/asan_guest.rs b/libafl_qemu/src/modules/usermode/asan_guest.rs index 6de295ecb4..3a45a86a59 100644 --- a/libafl_qemu/src/modules/usermode/asan_guest.rs +++ b/libafl_qemu/src/modules/usermode/asan_guest.rs @@ -342,13 +342,13 @@ impl HasAddressFilter for AsanGuestModule where F: AddressFilter, { - type ModuleAddressFilter = F; + type AddressFilter = F; - fn address_filter(&self) -> &Self::ModuleAddressFilter { + fn address_filter(&self) -> &Self::AddressFilter { &self.filter } - fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + fn address_filter_mut(&mut self) -> &mut Self::AddressFilter { &mut self.filter } } diff --git a/libafl_qemu/src/modules/usermode/injections.rs b/libafl_qemu/src/modules/usermode/injections.rs index 3827f8289d..0f43e6f929 100644 --- a/libafl_qemu/src/modules/usermode/injections.rs +++ b/libafl_qemu/src/modules/usermode/injections.rs @@ -346,13 +346,13 @@ where } impl HasAddressFilter for InjectionModule { - type ModuleAddressFilter = NopAddressFilter; + type AddressFilter = NopAddressFilter; - fn address_filter(&self) -> &Self::ModuleAddressFilter { + fn address_filter(&self) -> &Self::AddressFilter { &NopAddressFilter } - fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + fn address_filter_mut(&mut self) -> &mut Self::AddressFilter { unsafe { (&raw mut NOP_ADDRESS_FILTER).as_mut().unwrap().get_mut() } } } diff --git a/libafl_qemu/src/modules/usermode/snapshot.rs b/libafl_qemu/src/modules/usermode/snapshot.rs index 2e3c1aca67..df16498fc3 100644 --- a/libafl_qemu/src/modules/usermode/snapshot.rs +++ b/libafl_qemu/src/modules/usermode/snapshot.rs @@ -775,12 +775,12 @@ where } impl HasAddressFilter for SnapshotModule { - type ModuleAddressFilter = NopAddressFilter; - fn address_filter(&self) -> &Self::ModuleAddressFilter { + type AddressFilter = NopAddressFilter; + fn address_filter(&self) -> &Self::AddressFilter { &NopAddressFilter } - fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + fn address_filter_mut(&mut self) -> &mut Self::AddressFilter { unsafe { (&raw mut NOP_ADDRESS_FILTER).as_mut().unwrap().get_mut() } } } diff --git a/libafl_qemu/src/modules/utils/filters.rs b/libafl_qemu/src/modules/utils/filters.rs index f1d0c19f34..76cce54b49 100644 --- a/libafl_qemu/src/modules/utils/filters.rs +++ b/libafl_qemu/src/modules/utils/filters.rs @@ -31,7 +31,7 @@ impl AddressFilter for FilterList where T: AddressFilter, { - fn register(&mut self, address_range: Range) { + fn register(&mut self, address_range: &Range) { match self { FilterList::AllowList(allow_list) => allow_list.register(address_range), FilterList::DenyList(deny_list) => deny_list.register(address_range), @@ -69,62 +69,133 @@ where } } +#[cfg(feature = "usermode")] +pub trait HasStdFilters: HasAddressFilter {} + +#[cfg(feature = "systemmode")] +pub trait HasStdFilters: HasAddressFilter + HasPageFilter {} + +#[cfg(feature = "usermode")] +pub trait HasStdFiltersTuple: HasAddressFilterTuple {} + +#[cfg(feature = "systemmode")] +pub trait HasStdFiltersTuple: HasAddressFilterTuple + HasPageFilterTuple {} + /// Offers accessors to modules' address filters. pub trait HasAddressFilter { - type ModuleAddressFilter: AddressFilter; - #[cfg(feature = "systemmode")] - type ModulePageFilter: PageFilter; - fn address_filter(&self) -> &Self::ModuleAddressFilter; + type AddressFilter: AddressFilter; - fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter; - - fn update_address_filter(&mut self, qemu: Qemu, filter: Self::ModuleAddressFilter) { + fn address_filter(&self) -> &Self::AddressFilter; + fn address_filter_mut(&mut self) -> &mut Self::AddressFilter; + fn update_address_filter(&mut self, qemu: Qemu, filter: Self::AddressFilter) { *self.address_filter_mut() = filter; // Necessary because some hooks filter during TB generation. qemu.flush_jit(); } + fn allow_address_range(&mut self, address_range: &Range) { + self.address_filter_mut().register(address_range); + } - #[cfg(feature = "systemmode")] - fn page_filter(&self) -> &Self::ModulePageFilter; - #[cfg(feature = "systemmode")] - fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter; - #[cfg(feature = "systemmode")] - fn update_page_filter(&mut self, qemu: Qemu, filter: Self::ModulePageFilter) { + fn allowed_address(&self, address: &GuestAddr) -> bool { + self.address_filter().allowed(address) + } +} + +pub trait HasAddressFilterTuple { + fn allow_address_range_all(&mut self, address_range: &Range); + + fn allowed_address_all(&self, address: &GuestAddr) -> bool; +} + +impl HasAddressFilterTuple for () { + fn allow_address_range_all(&mut self, _address_range: &Range) {} + + fn allowed_address_all(&self, _address: &GuestAddr) -> bool { + true + } +} + +impl HasAddressFilterTuple for (Head, Tail) +where + Head: HasAddressFilter, + Tail: HasAddressFilterTuple, +{ + fn allow_address_range_all(&mut self, address_range: &Range) { + self.0.allow_address_range(address_range); + self.1.allow_address_range_all(address_range); + } + + fn allowed_address_all(&self, address: &GuestAddr) -> bool { + self.0.allowed_address(address) && self.1.allowed_address_all(address) + } +} + +#[cfg(feature = "usermode")] +impl HasStdFilters for M where M: HasAddressFilter {} + +#[cfg(feature = "systemmode")] +impl HasStdFilters for M where M: HasAddressFilter + HasPageFilter {} + +impl HasStdFiltersTuple for () {} + +impl HasStdFiltersTuple for (Head, Tail) +where + Head: HasStdFilters, + Tail: HasStdFiltersTuple, +{ +} + +/// Offers accessors to modules' page filters. +#[cfg(feature = "systemmode")] +pub trait HasPageFilter { + type PageFilter: PageFilter; + + fn page_filter(&self) -> &Self::PageFilter; + fn page_filter_mut(&mut self) -> &mut Self::PageFilter; + fn update_page_filter(&mut self, qemu: Qemu, filter: Self::PageFilter) { *self.page_filter_mut() = filter; // Necessary because some hooks filter during TB generation. qemu.flush_jit(); } -} - -pub trait HasAddressFilterTuples { - fn allow_address_range_all(&mut self, address_range: Range); - - #[cfg(feature = "systemmode")] - fn allow_page_id_all(&mut self, page_id: GuestPhysAddr); -} - -impl HasAddressFilterTuples for () { - fn allow_address_range_all(&mut self, _address_range: Range) {} - - #[cfg(feature = "systemmode")] - fn allow_page_id_all(&mut self, _page_id: GuestPhysAddr) {} -} - -impl HasAddressFilterTuples for (Head, Tail) -where - Head: HasAddressFilter, - Tail: HasAddressFilterTuples, -{ - fn allow_address_range_all(&mut self, address_range: Range) { - self.0.address_filter_mut().register(address_range.clone()); - self.1.allow_address_range_all(address_range); + fn allow_page_id(&mut self, page_id: GuestPhysAddr) { + self.page_filter_mut().register(page_id); } - #[cfg(feature = "systemmode")] + fn allowed_page_id(&self, page_id: &GuestPhysAddr) -> bool { + self.page_filter().allowed(page_id) + } +} + +#[cfg(feature = "systemmode")] +pub trait HasPageFilterTuple { + fn allow_page_id_all(&mut self, page_id: GuestPhysAddr); + + fn allowed_page_id_all(&self, page_id: &GuestPhysAddr) -> bool; +} + +#[cfg(feature = "systemmode")] +impl HasPageFilterTuple for () { + fn allow_page_id_all(&mut self, _page_id: GuestPhysAddr) {} + + fn allowed_page_id_all(&self, _page_id: &GuestPhysAddr) -> bool { + true + } +} + +#[cfg(feature = "systemmode")] +impl HasPageFilterTuple for (Head, Tail) +where + Head: HasPageFilter, + Tail: HasPageFilterTuple, +{ fn allow_page_id_all(&mut self, page_id: GuestPhysAddr) { - self.0.page_filter_mut().register(page_id); + self.0.allow_page_id(page_id); self.1.allow_page_id_all(page_id); } + + fn allowed_page_id_all(&self, page_id: &GuestPhysAddr) -> bool { + self.0.allowed_page_id(page_id) && self.1.allowed_page_id_all(page_id) + } } /// An address filter list. @@ -172,8 +243,8 @@ impl AddressFilterVec { } impl AddressFilter for AddressFilterVec { - fn register(&mut self, address_range: Range) { - self.registered_addresses.push(address_range); + fn register(&mut self, address_range: &Range) { + self.registered_addresses.push(address_range.clone()); if let Some(qemu) = Qemu::get() { qemu.flush_jit(); @@ -196,7 +267,7 @@ impl AddressFilter for AddressFilterVec { } impl AddressFilter for StdAddressFilter { - fn register(&mut self, address_range: Range) { + fn register(&mut self, address_range: &Range) { self.0.register(address_range); } @@ -279,7 +350,7 @@ impl PageFilter for StdPageFilter { } pub trait AddressFilter: 'static + Debug { - fn register(&mut self, address_range: Range); + fn register(&mut self, address_range: &Range); fn allowed(&self, address: &GuestAddr) -> bool; } @@ -287,7 +358,7 @@ pub trait AddressFilter: 'static + Debug { #[derive(Debug)] pub struct NopAddressFilter; impl AddressFilter for NopAddressFilter { - fn register(&mut self, _address: Range) {} + fn register(&mut self, _address: &Range) {} fn allowed(&self, _address: &GuestAddr) -> bool { true @@ -319,15 +390,12 @@ pub(crate) static mut NOP_PAGE_FILTER: UnsafeCell = UnsafeCell::n #[cfg(all(feature = "systemmode", test))] mod tests { - use libafl::{HasMetadata, inputs::NopInput, state::NopState}; use libafl_bolts::tuples::tuple_list; - use crate::modules::{ - EmulatorModule, - utils::filters::{ - AddressFilter, NopAddressFilter, NopPageFilter, PageFilter, StdAddressFilter, - StdPageFilter, - }, + use crate::modules::utils::filters::{ + AddressFilter, HasAddressFilter, HasAddressFilterTuple, HasPageFilter, HasPageFilterTuple, + HasStdFilters, NopAddressFilter, NopPageFilter, PageFilter, StdAddressFilter, + StdPageFilter, }; #[derive(Clone, Debug)] @@ -336,42 +404,47 @@ mod tests { page_filter: PF, } - impl EmulatorModule for DummyModule + impl HasAddressFilter for DummyModule where - AF: AddressFilter + 'static, - PF: PageFilter + 'static, - I: Unpin, - S: Unpin + HasMetadata, + AF: AddressFilter, { - type ModuleAddressFilter = AF; - type ModulePageFilter = PF; + type AddressFilter = AF; - fn address_filter(&self) -> &Self::ModuleAddressFilter { + fn address_filter(&self) -> &Self::AddressFilter { &self.address_filter } - fn address_filter_mut(&mut self) -> &mut Self::ModuleAddressFilter { + fn address_filter_mut(&mut self) -> &mut Self::AddressFilter { &mut self.address_filter } + } - fn page_filter(&self) -> &Self::ModulePageFilter { + impl HasPageFilter for DummyModule + where + PF: PageFilter, + { + type PageFilter = PF; + + fn page_filter(&self) -> &Self::PageFilter { &self.page_filter } - fn page_filter_mut(&mut self) -> &mut Self::ModulePageFilter { + fn page_filter_mut(&mut self) -> &mut Self::PageFilter { &mut self.page_filter } } - fn gen_module( - af: AF, - pf: PF, - ) -> impl EmulatorModule + impl HasStdFilters for DummyModule + where + AF: AddressFilter, + PF: PageFilter, + { + } + + fn gen_module(af: AF, pf: PF) -> impl HasStdFilters where AF: AddressFilter, PF: PageFilter, - I: Unpin, - S: HasMetadata + Unpin, { DummyModule { address_filter: af, @@ -399,82 +472,79 @@ mod tests { #[test] fn test_filter_nop() { - let module = gen_module::>( - NopAddressFilter, - NopPageFilter, - ); - let mut modules = tuple_list!(module); + let mut module = + gen_module::(NopAddressFilter, NopPageFilter); - modules.allow_address_range_all(0x100..0x200); - modules.allow_address_range_all(0x300..0x400); + module.allow_address_range(&(0x100..0x200)); + module.allow_address_range(&(0x300..0x400)); - modules.allow_page_id_all(0xaaaa); - modules.allow_page_id_all(0xbbbb); + module.allow_page_id(0xaaaa); + module.allow_page_id(0xbbbb); - assert!(modules.0.address_filter().allowed(&0xff)); - assert!(modules.0.address_filter().allowed(&0x200)); - assert!(modules.0.address_filter().allowed(&0x201)); - assert!(modules.0.address_filter().allowed(&0x300)); + assert!(module.allowed_address(&0xff)); + assert!(module.allowed_address(&0x200)); + assert!(module.allowed_address(&0x201)); + assert!(module.allowed_address(&0x300)); - assert!(modules.0.page_filter().allowed(&0xaaaa)); - assert!(modules.0.page_filter().allowed(&0xbbbb)); - assert!(modules.0.page_filter().allowed(&0xcccc)); + assert!(module.allowed_page_id(&0xaaaa)); + assert!(module.allowed_page_id(&0xbbbb)); + assert!(module.allowed_page_id(&0xcccc)); } #[test] fn test_filters_simple() { - let module = gen_module::>( + let module = gen_module::( StdAddressFilter::default(), StdPageFilter::default(), ); let mut modules = tuple_list!(module); - assert!(modules.0.address_filter().allowed(&0x000)); - assert!(modules.0.address_filter().allowed(&0x100)); - assert!(modules.0.address_filter().allowed(&0x200)); - assert!(modules.0.address_filter().allowed(&0xffffffff)); + assert!(modules.allowed_address_all(&0x000)); + assert!(modules.allowed_address_all(&0x100)); + assert!(modules.allowed_address_all(&0x200)); + assert!(modules.allowed_address_all(&0xffffffff)); - assert!(modules.0.page_filter().allowed(&0xabcd)); + assert!(modules.allowed_page_id_all(&0xabcd)); - modules.allow_address_range_all(0x100..0x200); - modules.allow_address_range_all(0x300..0x400); + modules.allow_address_range_all(&(0x100..0x200)); + modules.allow_address_range_all(&(0x300..0x400)); modules.allow_page_id_all(0xaaaa); modules.allow_page_id_all(0xbbbb); - assert!(modules.0.address_filter().allowed(&0x100)); - assert!(modules.0.address_filter().allowed(&0x101)); - assert!(modules.0.address_filter().allowed(&0x1ff)); - assert!(modules.0.address_filter().allowed(&0x301)); + assert!(modules.allowed_address_all(&0x100)); + assert!(modules.allowed_address_all(&0x101)); + assert!(modules.allowed_address_all(&0x1ff)); + assert!(modules.allowed_address_all(&0x301)); - assert!(!modules.0.address_filter().allowed(&0xff)); - assert!(!modules.0.address_filter().allowed(&0x200)); - assert!(!modules.0.address_filter().allowed(&0x201)); + assert!(!modules.allowed_address_all(&0xff)); + assert!(!modules.allowed_address_all(&0x200)); + assert!(!modules.allowed_address_all(&0x201)); - assert!(modules.0.page_filter().allowed(&0xaaaa)); - assert!(modules.0.page_filter().allowed(&0xbbbb)); + assert!(modules.allowed_page_id_all(&0xaaaa)); + assert!(modules.allowed_page_id_all(&0xbbbb)); - assert!(!modules.0.page_filter().allowed(&0xcccc)); + assert!(!modules.allowed_page_id_all(&0xcccc)); } #[test] fn test_filters_multiple() { - let module1 = gen_module::>( + let module1 = gen_module::( StdAddressFilter::default(), StdPageFilter::default(), ); - let module2 = gen_module::>( + let module2 = gen_module::( StdAddressFilter::default(), StdPageFilter::default(), ); - let module3 = gen_module::>( + let module3 = gen_module::( StdAddressFilter::default(), StdPageFilter::default(), ); let mut modules = tuple_list!(module1, module2, module3); - modules.allow_address_range_all(0x100..0x200); - modules.allow_address_range_all(0x300..0x400); + modules.allow_address_range_all(&(0x100..0x200)); + modules.allow_address_range_all(&(0x300..0x400)); modules.allow_page_id_all(0xaaaa); modules.allow_page_id_all(0xbbbb);