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 <tokazerkje@outlook.com>
This commit is contained in:
parent
191bc6d12d
commit
e864bc28b1
4
.github/workflows/build_and_test.yml
vendored
4
.github/workflows/build_and_test.yml
vendored
@ -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
|
||||
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -79,3 +79,9 @@ fuzzer_libpng*
|
||||
|
||||
# Sometimes this happens
|
||||
rustc-ice-*
|
||||
|
||||
# perf files
|
||||
*.mm_profdata
|
||||
|
||||
# backup files
|
||||
*.bak
|
||||
|
@ -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<C, ET, I, S>(
|
||||
QemuInitError,
|
||||
>
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + 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)
|
||||
|
@ -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<C, ET, I, S>(
|
||||
QemuInitError,
|
||||
>
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + 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)
|
||||
|
@ -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)]
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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<C, ET, I, S, SM> CommandManager<C, StdEmulatorDriver, ET, I, S, SM> for $name<S>
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: HasTargetBytes + Unpin,
|
||||
S: Unpin,
|
||||
SM: IsSnapshotManager,
|
||||
@ -125,7 +125,7 @@ macro_rules! define_std_command_manager {
|
||||
|
||||
impl<C, ET, I, S, SM> IsCommand<C, $name<S>, StdEmulatorDriver, ET, I, S, SM> for [<$name Commands>]
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: HasTargetBytes + Unpin,
|
||||
S: Unpin,
|
||||
SM: IsSnapshotManager,
|
||||
@ -383,7 +383,7 @@ pub struct StartCommand {
|
||||
impl<C, ET, I, S, SM> IsCommand<C, StdCommandManager<S>, StdEmulatorDriver, ET, I, S, SM>
|
||||
for StartCommand
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: HasTargetBytes + Unpin,
|
||||
S: Unpin,
|
||||
SM: IsSnapshotManager,
|
||||
@ -544,7 +544,7 @@ pub struct PageAllowCommand {
|
||||
#[cfg(feature = "systemmode")]
|
||||
impl<C, CM, ED, ET, I, S, SM> IsCommand<C, CM, ED, ET, I, S, SM> for PageAllowCommand
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: Unpin,
|
||||
S: Unpin,
|
||||
{
|
||||
@ -572,7 +572,7 @@ pub struct AddressAllowCommand {
|
||||
}
|
||||
impl<C, CM, ED, ET, I, S, SM> IsCommand<C, CM, ED, ET, I, S, SM> for AddressAllowCommand
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: Unpin,
|
||||
S: Unpin,
|
||||
{
|
||||
@ -589,7 +589,7 @@ where
|
||||
) -> Result<Option<EmulatorDriverResult<C>>, EmulatorDriverError> {
|
||||
emu.modules_mut()
|
||||
.modules_mut()
|
||||
.allow_address_range_all(self.address_range.clone());
|
||||
.allow_address_range_all(&self.address_range);
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
@ -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<C, ET, I, S, SM> CommandManager<C, NyxEmulatorDriver, ET, I, S, SM> for $name<S>
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: HasTargetBytes + Unpin,
|
||||
S: Unpin,
|
||||
SM: IsSnapshotManager,
|
||||
@ -134,7 +134,7 @@ macro_rules! define_nyx_command_manager {
|
||||
|
||||
impl<C, ET, I, S, SM> IsCommand<C, $name<S>, NyxEmulatorDriver, ET, I, S, SM> for [<$name Commands>]
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: HasTargetBytes + Unpin,
|
||||
S: Unpin,
|
||||
SM: IsSnapshotManager,
|
||||
@ -296,7 +296,7 @@ pub struct NextPayloadCommand;
|
||||
impl<C, ET, I, S, SM> IsCommand<C, NyxCommandManager<S>, NyxEmulatorDriver, ET, I, S, SM>
|
||||
for NextPayloadCommand
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: HasTargetBytes + Unpin,
|
||||
S: Unpin,
|
||||
SM: IsSnapshotManager,
|
||||
@ -360,7 +360,7 @@ pub struct SubmitCR3Command;
|
||||
impl<C, ET, I, S, SM> IsCommand<C, NyxCommandManager<S>, NyxEmulatorDriver, ET, I, S, SM>
|
||||
for SubmitCR3Command
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: HasTargetBytes + Unpin,
|
||||
S: Unpin,
|
||||
SM: IsSnapshotManager,
|
||||
@ -408,7 +408,7 @@ impl RangeSubmitCommand {
|
||||
impl<C, ET, I, S, SM> IsCommand<C, NyxCommandManager<S>, NyxEmulatorDriver, ET, I, S, SM>
|
||||
for RangeSubmitCommand
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + 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)
|
||||
}
|
||||
}
|
||||
|
@ -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<C, ET, I, S, SM> NativeCommandParser<C, StdCommandManager<S>, StdEmulatorDriver, ET, I, S, SM>
|
||||
for StartPhysCommandParser
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: HasTargetBytes + Unpin,
|
||||
S: Unpin,
|
||||
SM: IsSnapshotManager,
|
||||
@ -121,7 +121,7 @@ pub struct StartVirtCommandParser;
|
||||
impl<C, ET, I, S, SM> NativeCommandParser<C, StdCommandManager<S>, StdEmulatorDriver, ET, I, S, SM>
|
||||
for StartVirtCommandParser
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: HasTargetBytes + Unpin,
|
||||
S: Unpin,
|
||||
SM: IsSnapshotManager,
|
||||
@ -242,7 +242,7 @@ pub struct VaddrFilterAllowRangeCommandParser;
|
||||
impl<C, CM, ED, ET, I, S, SM> NativeCommandParser<C, CM, ED, ET, I, S, SM>
|
||||
for VaddrFilterAllowRangeCommandParser
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: Unpin,
|
||||
S: Unpin,
|
||||
{
|
||||
|
@ -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<C, ET, I, S, SM> NativeCommandParser<C, NyxCommandManager<S>, NyxEmulatorDriver, ET, I, S, SM>
|
||||
for SubmitCR3CommandParser
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: HasTargetBytes + Unpin,
|
||||
S: Unpin,
|
||||
SM: IsSnapshotManager,
|
||||
@ -101,7 +101,7 @@ pub struct RangeSubmitCommandParser;
|
||||
impl<C, ET, I, S, SM> NativeCommandParser<C, NyxCommandManager<S>, NyxEmulatorDriver, ET, I, S, SM>
|
||||
for RangeSubmitCommandParser
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: HasTargetBytes + Unpin,
|
||||
S: Unpin,
|
||||
SM: IsSnapshotManager,
|
||||
@ -189,7 +189,7 @@ pub struct NextPayloadCommandParser;
|
||||
impl<C, ET, I, S, SM> NativeCommandParser<C, NyxCommandManager<S>, NyxEmulatorDriver, ET, I, S, SM>
|
||||
for NextPayloadCommandParser
|
||||
where
|
||||
ET: EmulatorModuleTuple<I, S> + HasAddressFilterTuples,
|
||||
ET: EmulatorModuleTuple<I, S> + HasStdFiltersTuple,
|
||||
I: HasTargetBytes + Unpin,
|
||||
S: Unpin,
|
||||
SM: IsSnapshotManager,
|
||||
|
@ -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<T> HasAddressFilter for CallTracerModule<T>
|
||||
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<T> HasPageFilter for CallTracerModule<T>
|
||||
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() }
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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<F> HasAddressFilter for DrCovModule<F>
|
||||
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<F> HasPageFilter for DrCovModule<F> {
|
||||
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() }
|
||||
}
|
||||
}
|
||||
|
@ -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<AF, PF, V, const IS_CONST_MAP: bool, const MAP_SIZE: usize> HasAddressFilte
|
||||
for EdgeCoverageModule<AF, PF, V, IS_CONST_MAP, MAP_SIZE>
|
||||
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<AF, PF, V, const IS_CONST_MAP: bool, const MAP_SIZE: usize> HasPageFilter
|
||||
for EdgeCoverageModule<AF, PF, V, IS_CONST_MAP, MAP_SIZE>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -342,13 +342,13 @@ impl<F> HasAddressFilter for AsanGuestModule<F>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -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() }
|
||||
}
|
||||
}
|
||||
|
@ -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() }
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ impl<T> AddressFilter for FilterList<T>
|
||||
where
|
||||
T: AddressFilter,
|
||||
{
|
||||
fn register(&mut self, address_range: Range<GuestAddr>) {
|
||||
fn register(&mut self, address_range: &Range<GuestAddr>) {
|
||||
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<GuestAddr>) {
|
||||
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<GuestAddr>);
|
||||
|
||||
fn allowed_address_all(&self, address: &GuestAddr) -> bool;
|
||||
}
|
||||
|
||||
impl HasAddressFilterTuple for () {
|
||||
fn allow_address_range_all(&mut self, _address_range: &Range<GuestAddr>) {}
|
||||
|
||||
fn allowed_address_all(&self, _address: &GuestAddr) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<Head, Tail> HasAddressFilterTuple for (Head, Tail)
|
||||
where
|
||||
Head: HasAddressFilter,
|
||||
Tail: HasAddressFilterTuple,
|
||||
{
|
||||
fn allow_address_range_all(&mut self, address_range: &Range<GuestAddr>) {
|
||||
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<M> HasStdFilters for M where M: HasAddressFilter {}
|
||||
|
||||
#[cfg(feature = "systemmode")]
|
||||
impl<M> HasStdFilters for M where M: HasAddressFilter + HasPageFilter {}
|
||||
|
||||
impl HasStdFiltersTuple for () {}
|
||||
|
||||
impl<Head, Tail> 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<GuestAddr>);
|
||||
|
||||
#[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<GuestAddr>) {}
|
||||
|
||||
#[cfg(feature = "systemmode")]
|
||||
fn allow_page_id_all(&mut self, _page_id: GuestPhysAddr) {}
|
||||
}
|
||||
|
||||
impl<Head, Tail> HasAddressFilterTuples for (Head, Tail)
|
||||
where
|
||||
Head: HasAddressFilter,
|
||||
Tail: HasAddressFilterTuples,
|
||||
{
|
||||
fn allow_address_range_all(&mut self, address_range: Range<GuestAddr>) {
|
||||
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<Head, Tail> 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<GuestAddr>) {
|
||||
self.registered_addresses.push(address_range);
|
||||
fn register(&mut self, address_range: &Range<GuestAddr>) {
|
||||
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<GuestAddr>) {
|
||||
fn register(&mut self, address_range: &Range<GuestAddr>) {
|
||||
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<GuestAddr>);
|
||||
fn register(&mut self, address_range: &Range<GuestAddr>);
|
||||
|
||||
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<GuestAddr>) {}
|
||||
fn register(&mut self, _address: &Range<GuestAddr>) {}
|
||||
|
||||
fn allowed(&self, _address: &GuestAddr) -> bool {
|
||||
true
|
||||
@ -319,15 +390,12 @@ pub(crate) static mut NOP_PAGE_FILTER: UnsafeCell<NopPageFilter> = 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<I, S, AF, PF> EmulatorModule<I, S> for DummyModule<AF, PF>
|
||||
impl<AF, PF> HasAddressFilter for DummyModule<AF, PF>
|
||||
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<AF, PF> HasPageFilter for DummyModule<AF, PF>
|
||||
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, PF, I, S>(
|
||||
af: AF,
|
||||
pf: PF,
|
||||
) -> impl EmulatorModule<I, S, ModuleAddressFilter = AF, ModulePageFilter = PF>
|
||||
impl<AF, PF> HasStdFilters for DummyModule<AF, PF>
|
||||
where
|
||||
AF: AddressFilter,
|
||||
PF: PageFilter,
|
||||
{
|
||||
}
|
||||
|
||||
fn gen_module<AF, PF>(af: AF, pf: PF) -> impl HasStdFilters<AddressFilter = AF, PageFilter = PF>
|
||||
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, NopState<NopInput>>(
|
||||
NopAddressFilter,
|
||||
NopPageFilter,
|
||||
);
|
||||
let mut modules = tuple_list!(module);
|
||||
let mut module =
|
||||
gen_module::<NopAddressFilter, NopPageFilter>(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::<StdAddressFilter, StdPageFilter, NopState<NopInput>>(
|
||||
let module = gen_module::<StdAddressFilter, StdPageFilter>(
|
||||
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::<StdAddressFilter, StdPageFilter, NopState<NopInput>>(
|
||||
let module1 = gen_module::<StdAddressFilter, StdPageFilter>(
|
||||
StdAddressFilter::default(),
|
||||
StdPageFilter::default(),
|
||||
);
|
||||
let module2 = gen_module::<StdAddressFilter, StdPageFilter, NopState<NopInput>>(
|
||||
let module2 = gen_module::<StdAddressFilter, StdPageFilter>(
|
||||
StdAddressFilter::default(),
|
||||
StdPageFilter::default(),
|
||||
);
|
||||
let module3 = gen_module::<StdAddressFilter, StdPageFilter, NopState<NopInput>>(
|
||||
let module3 = gen_module::<StdAddressFilter, StdPageFilter>(
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user