Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QEMU generic memory iterator #2148

Merged
merged 15 commits into from
May 7, 2024
37 changes: 9 additions & 28 deletions fuzzers/qemu_systemmode/src/fuzzer_breakpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{env, path::PathBuf, process};

use libafl::{
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
events::{launcher::Launcher, EventConfig, CTRL_C_EXIT},
events::{launcher::Launcher, EventConfig},
executors::ExitKind,
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
Expand All @@ -29,13 +29,13 @@ use libafl_bolts::{
};
use libafl_qemu::{
breakpoint::Breakpoint,
command::{Command, EmulatorMemoryChunk, EndCommand, StartCommand},
command::{Command, EndCommand, StartCommand},
edges::{edges_map_mut_ptr, QemuEdgeCoverageHelper, EDGES_MAP_SIZE_IN_USE, MAX_EDGES_FOUND},
elf::EasyElf,
emu::Emulator,
executor::{stateful::StatefulQemuExecutor, QemuExecutorState},
EmuExitReasonError, FastSnapshotManager, GuestPhysAddr, GuestReg, HandlerError, HandlerResult,
QemuHooks, StdEmuExitHandler,
EmulatorMemoryChunk, FastSnapshotManager, GuestPhysAddr, GuestReg, QemuHooks,
StdEmulatorExitHandler,
};

// use libafl_qemu::QemuSnapshotBuilder; // for normal qemu snapshot
Expand Down Expand Up @@ -93,7 +93,7 @@ pub fn fuzz() {
let emu_snapshot_manager = FastSnapshotManager::new(false);

// Choose Exit Handler
let emu_exit_handler = StdEmuExitHandler::new(emu_snapshot_manager);
let emu_exit_handler = StdEmulatorExitHandler::new(emu_snapshot_manager);

// Create emulator
let emu = Emulator::new(&args, &env, emu_exit_handler).unwrap();
Expand Down Expand Up @@ -126,29 +126,10 @@ pub fn fuzz() {
// The wrapped harness function, calling out to the LLVM-style harness
let mut harness =
|input: &BytesInput, qemu_executor_state: &mut QemuExecutorState<_, _>| unsafe {
match emu.run(input, qemu_executor_state) {
Ok(handler_result) => match handler_result {
HandlerResult::UnhandledExit(unhandled_exit) => {
panic!("Unhandled exit: {}", unhandled_exit)
}
HandlerResult::EndOfRun(exit_kind) => return exit_kind,
HandlerResult::Interrupted => {
std::process::exit(CTRL_C_EXIT);
}
},
Err(handler_error) => match handler_error {
HandlerError::QemuExitReasonError(emu_exit_reason_error) => {
match emu_exit_reason_error {
EmuExitReasonError::UnknownKind => panic!("unknown kind"),
EmuExitReasonError::UnexpectedExit => return ExitKind::Crash,
_ => {
panic!("Emu Exit unhandled error: {:?}", emu_exit_reason_error)
}
}
}
_ => panic!("Unhandled error: {:?}", handler_error),
},
}
emu.run(input, qemu_executor_state)
.unwrap()
.try_into()
.unwrap()
};

// Create an observation channel using the coverage map
Expand Down
5 changes: 2 additions & 3 deletions fuzzers/qemu_systemmode/src/fuzzer_classic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ use libafl_bolts::{
use libafl_qemu::{
edges::{edges_map_mut_ptr, QemuEdgeCoverageHelper, EDGES_MAP_SIZE_IN_USE, MAX_EDGES_FOUND},
elf::EasyElf,
emu::Qemu,
QemuExecutor, QemuExitReason, QemuExitReasonError, QemuHooks, QemuShutdownCause, Regs,
Qemu, QemuExecutor, QemuExitError, QemuExitReason, QemuHooks, QemuShutdownCause, Regs,
};
use libafl_qemu_sys::GuestPhysAddr;

Expand Down Expand Up @@ -128,7 +127,7 @@ pub fn fuzz() {
Ok(QemuExitReason::End(QemuShutdownCause::HostSignal(
Signal::SigInterrupt,
))) => process::exit(CTRL_C_EXIT),
Err(QemuExitReasonError::UnexpectedExit) => return ExitKind::Crash,
Err(QemuExitError::UnexpectedExit) => return ExitKind::Crash,
_ => panic!("Unexpected QEMU exit."),
}

Expand Down
38 changes: 8 additions & 30 deletions fuzzers/qemu_systemmode/src/fuzzer_sync_exit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ use std::{env, path::PathBuf, process};

use libafl::{
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
events::{launcher::Launcher, EventConfig, CTRL_C_EXIT},
executors::ExitKind,
events::{launcher::Launcher, EventConfig},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
Expand All @@ -31,8 +30,7 @@ use libafl_qemu::{
edges::{edges_map_mut_ptr, QemuEdgeCoverageHelper, EDGES_MAP_SIZE_IN_USE, MAX_EDGES_FOUND},
emu::Emulator,
executor::{stateful::StatefulQemuExecutor, QemuExecutorState},
EmuExitReasonError, FastSnapshotManager, HandlerError, HandlerResult, QemuHooks,
StdEmuExitHandler,
FastSnapshotManager, QemuHooks, StdEmulatorExitHandler,
};

// use libafl_qemu::QemuSnapshotBuilder; for normal qemu snapshot
Expand All @@ -56,8 +54,8 @@ pub fn fuzz() {
let env: Vec<(String, String)> = env::vars().collect();
// let emu_snapshot_manager = QemuSnapshotBuilder::new(true);
let emu_snapshot_manager = FastSnapshotManager::new(false); // Create a snapshot manager (normal or fast for now).
let emu_exit_handler: StdEmuExitHandler<FastSnapshotManager> =
StdEmuExitHandler::new(emu_snapshot_manager); // Create an exit handler: it is the entity taking the decision of what should be done when QEMU returns.
let emu_exit_handler: StdEmulatorExitHandler<FastSnapshotManager> =
StdEmulatorExitHandler::new(emu_snapshot_manager); // Create an exit handler: it is the entity taking the decision of what should be done when QEMU returns.
let emu = Emulator::new(&args, &env, emu_exit_handler).unwrap(); // Create the emulator

let devices = emu.list_devices();
Expand All @@ -66,30 +64,10 @@ pub fn fuzz() {
// The wrapped harness function, calling out to the LLVM-style harness
let mut harness =
|input: &BytesInput, qemu_executor_state: &mut QemuExecutorState<_, _>| unsafe {
match emu.run(input, qemu_executor_state) {
Ok(handler_result) => match handler_result {
HandlerResult::UnhandledExit(unhandled_exit) => {
panic!("Unhandled exit: {}", unhandled_exit)
}
HandlerResult::EndOfRun(exit_kind) => exit_kind,
HandlerResult::Interrupted => {
println!("Interrupted.");
std::process::exit(CTRL_C_EXIT);
}
},
Err(handler_error) => match handler_error {
HandlerError::QemuExitReasonError(emu_exit_reason_error) => {
match emu_exit_reason_error {
EmuExitReasonError::UnknownKind => panic!("unknown kind"),
EmuExitReasonError::UnexpectedExit => ExitKind::Crash,
_ => {
panic!("Emu Exit unhandled error: {:?}", emu_exit_reason_error)
}
}
}
_ => panic!("Unhandled error: {:?}", handler_error),
},
}
emu.run(input, qemu_executor_state)
.unwrap()
.try_into()
.unwrap()
};

// Create an observation channel using the coverage map
Expand Down
3 changes: 2 additions & 1 deletion libafl/src/events/llmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use libafl_bolts::{
use libafl_bolts::{llmp::LlmpConnection, shmem::StdShMemProvider, staterestore::StateRestorer};
use libafl_bolts::{
llmp::{self, LlmpClient, LlmpClientDescription, Tag},
os::CTRL_C_EXIT,
shmem::ShMemProvider,
tuples::tuple_list,
ClientId,
Expand Down Expand Up @@ -1581,7 +1582,7 @@ where

compiler_fence(Ordering::SeqCst);

if child_status == crate::events::CTRL_C_EXIT || staterestorer.wants_to_exit() {
if child_status == CTRL_C_EXIT || staterestorer.wants_to_exit() {
// if ctrl-c is pressed, we end up in this branch
if let Err(err) = mgr.detach_from_broker(self.broker_port) {
log::error!("Failed to detach from broker: {err}");
Expand Down
9 changes: 1 addition & 8 deletions libafl/src/events/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub use launcher::*;
use libafl_bolts::os::unix_signals::{siginfo_t, ucontext_t, Handler, Signal};
#[cfg(feature = "adaptive_serialization")]
use libafl_bolts::tuples::{Handle, MatchNameRef};
use libafl_bolts::{current_time, ClientId};
use libafl_bolts::{current_time, os::CTRL_C_EXIT, ClientId};
use serde::{Deserialize, Serialize};
#[cfg(feature = "std")]
use uuid::Uuid;
Expand All @@ -55,13 +55,6 @@ use crate::{
state::HasScalabilityMonitor,
};

/// The special exit code when the target exited throught ctrl-c
#[cfg(unix)]
pub const CTRL_C_EXIT: i32 = 100;
/// The special exit code when the target exited throught ctrl-c
#[cfg(windows)]
pub const CTRL_C_EXIT: i32 = -1073741510;

/// Check if ctrl-c is sent with this struct
#[cfg(all(unix, feature = "std"))]
pub static mut EVENTMGR_SIGHANDLER_STATE: ShutdownSignalData = ShutdownSignalData {};
Expand Down
4 changes: 2 additions & 2 deletions libafl/src/events/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use libafl_bolts::os::startable_self;
use libafl_bolts::os::unix_signals::setup_signal_handler;
#[cfg(all(feature = "std", feature = "fork", unix))]
use libafl_bolts::os::{fork, ForkResult};
use libafl_bolts::ClientId;
use libafl_bolts::{os::CTRL_C_EXIT, ClientId};
#[cfg(feature = "std")]
use libafl_bolts::{shmem::ShMemProvider, staterestore::StateRestorer};
#[cfg(feature = "std")]
Expand Down Expand Up @@ -520,7 +520,7 @@ where

compiler_fence(Ordering::SeqCst);

if child_status == crate::events::CTRL_C_EXIT || staterestorer.wants_to_exit() {
if child_status == CTRL_C_EXIT || staterestorer.wants_to_exit() {
return Err(Error::shutting_down());
}

Expand Down
5 changes: 4 additions & 1 deletion libafl_bolts/src/os/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub mod unix_shmem_server;

#[cfg(unix)]
pub mod unix_signals;
#[cfg(unix)]
pub use unix_signals::CTRL_C_EXIT;

#[cfg(all(unix, feature = "std"))]
pub mod pipes;
Expand All @@ -28,9 +30,10 @@ use std::{fs::File, os::fd::AsRawFd, sync::OnceLock};
#[cfg(all(windows, feature = "std"))]
#[allow(missing_docs, overflowing_literals)]
pub mod windows_exceptions;

#[cfg(unix)]
use libc::pid_t;
#[cfg(all(windows, feature = "std"))]
pub use windows_exceptions::CTRL_C_EXIT;

/// A file that we keep open, pointing to /dev/null
#[cfg(all(feature = "std", unix))]
Expand Down
16 changes: 16 additions & 0 deletions libafl_bolts/src/os/unix_signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ pub use libc::c_ulong;
#[cfg(feature = "std")]
use nix::errno::{errno, Errno};

/// The special exit code when the target exited through ctrl-c
pub const CTRL_C_EXIT: i32 = 100;

/// ARMv7-specific representation of a saved context
#[cfg(target_arch = "arm")]
#[derive(Debug)]
Expand Down Expand Up @@ -302,6 +305,19 @@ pub enum Signal {
SigTrap = SIGTRAP,
}

#[cfg(feature = "std")]
impl Signal {
/// Handle an incoming signal
pub fn handle(&self) {
match self {
Signal::SigInterrupt | Signal::SigQuit | Signal::SigTerm => {
std::process::exit(CTRL_C_EXIT)
}
_ => {}
}
}
}

impl TryFrom<&str> for Signal {
type Error = Error;

Expand Down
3 changes: 3 additions & 0 deletions libafl_bolts/src/os/windows_exceptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ pub use windows::Win32::{

use crate::Error;

/// The special exit code when the target exited through ctrl-c
pub const CTRL_C_EXIT: i32 = -1073741510;

// For VEH
const EXCEPTION_CONTINUE_EXECUTION: c_long = -1;

Expand Down
1 change: 1 addition & 0 deletions libafl_qemu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ enum-map = "2.7"
serde_yaml = { version = "0.8", optional = true } # For parsing the injections yaml file
toml = { version = "0.4.2", optional = true } # For parsing the injections toml file
pyo3 = { version = "0.18", optional = true }
bytes-utils = "0.1"
# Document all features of this crate (for `cargo doc`)
document-features = { version = "0.2", optional = true }

Expand Down
1 change: 1 addition & 0 deletions libafl_qemu/libafl_qemu_build/src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ const WRAPPER_HEADER: &str = r#"
#include "libafl/exit.h"
#include "libafl/hook.h"
#include "libafl/jit.h"
#include "libafl/utils.h"

"#;

Expand Down
2 changes: 1 addition & 1 deletion libafl_qemu/libafl_qemu_build/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::cargo_add_rpath;

const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge";
const QEMU_DIRNAME: &str = "qemu-libafl-bridge";
const QEMU_REVISION: &str = "538e6b02c36838e0de469b39dd03fef05678444f";
const QEMU_REVISION: &str = "9f3e2399ee9b106dfbb8c3afcdfdf30e235fc88f";

#[allow(clippy::module_name_repetitions)]
pub struct BuildResult {
Expand Down
27 changes: 13 additions & 14 deletions libafl_qemu/libafl_qemu_sys/src/x86_64_stub_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12055,8 +12055,7 @@ extern "C" {
}
pub const libafl_exit_reason_kind_INTERNAL: libafl_exit_reason_kind = libafl_exit_reason_kind(0);
pub const libafl_exit_reason_kind_BREAKPOINT: libafl_exit_reason_kind = libafl_exit_reason_kind(1);
pub const libafl_exit_reason_kind_SYNC_BACKDOOR: libafl_exit_reason_kind =
libafl_exit_reason_kind(2);
pub const libafl_exit_reason_kind_SYNC_EXIT: libafl_exit_reason_kind = libafl_exit_reason_kind(2);
impl ::std::ops::BitOr<libafl_exit_reason_kind> for libafl_exit_reason_kind {
type Output = Self;
#[inline]
Expand Down Expand Up @@ -12119,21 +12118,18 @@ fn bindgen_test_layout_libafl_exit_reason_breakpoint() {
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct libafl_exit_reason_sync_backdoor {}
pub struct libafl_exit_reason_sync_exit {}
#[test]
fn bindgen_test_layout_libafl_exit_reason_sync_backdoor() {
fn bindgen_test_layout_libafl_exit_reason_sync_exit() {
assert_eq!(
::std::mem::size_of::<libafl_exit_reason_sync_backdoor>(),
::std::mem::size_of::<libafl_exit_reason_sync_exit>(),
0usize,
concat!("Size of: ", stringify!(libafl_exit_reason_sync_backdoor))
concat!("Size of: ", stringify!(libafl_exit_reason_sync_exit))
);
assert_eq!(
::std::mem::align_of::<libafl_exit_reason_sync_backdoor>(),
::std::mem::align_of::<libafl_exit_reason_sync_exit>(),
1usize,
concat!(
"Alignment of ",
stringify!(libafl_exit_reason_sync_backdoor)
)
concat!("Alignment of ", stringify!(libafl_exit_reason_sync_exit))
);
}
#[repr(C)]
Expand Down Expand Up @@ -12200,7 +12196,7 @@ pub struct libafl_exit_reason {
pub union libafl_exit_reason__bindgen_ty_1 {
pub internal: libafl_exit_reason_internal,
pub breakpoint: libafl_exit_reason_breakpoint,
pub backdoor: libafl_exit_reason_sync_backdoor,
pub sync_exit: libafl_exit_reason_sync_exit,
}
#[test]
fn bindgen_test_layout_libafl_exit_reason__bindgen_ty_1() {
Expand Down Expand Up @@ -12241,13 +12237,13 @@ fn bindgen_test_layout_libafl_exit_reason__bindgen_ty_1() {
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).backdoor) as usize - ptr as usize },
unsafe { ::std::ptr::addr_of!((*ptr).sync_exit) as usize - ptr as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(libafl_exit_reason__bindgen_ty_1),
"::",
stringify!(backdoor)
stringify!(sync_exit)
)
);
}
Expand Down Expand Up @@ -13890,6 +13886,9 @@ extern "C" {
extern "C" {
pub fn libafl_jit_trace_block_single(data: u64, id: u64) -> usize;
}
extern "C" {
pub fn libafl_qemu_host_page_size() -> usize;
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct kvm_dirty_gfn {
Expand Down
Loading
Loading