add QemuClockObserver
This commit is contained in:
parent
ba85877ab4
commit
b3b8e81190
@ -219,6 +219,7 @@ fn fuzz(
|
|||||||
"-kernel", kernel.to_str().unwrap(),
|
"-kernel", kernel.to_str().unwrap(),
|
||||||
"-serial", "stdio", "-nographic",
|
"-serial", "stdio", "-nographic",
|
||||||
"-snapshot", "-drive", "if=none,format=qcow2,file=dummy.qcow2",
|
"-snapshot", "-drive", "if=none,format=qcow2,file=dummy.qcow2",
|
||||||
|
"-icount", "shift=auto,align=off,sleep=off",
|
||||||
"-S"
|
"-S"
|
||||||
].iter().map(|x| x.to_string()).collect();
|
].iter().map(|x| x.to_string()).collect();
|
||||||
let env: Vec<(String, String)> = env::vars().collect();
|
let env: Vec<(String, String)> = env::vars().collect();
|
||||||
|
@ -43,6 +43,8 @@ use libafl_qemu::{
|
|||||||
emu::Emulator, filter_qemu_args,
|
emu::Emulator, filter_qemu_args,
|
||||||
snapshot_sys::QemuSysSnapshotHelper,
|
snapshot_sys::QemuSysSnapshotHelper,
|
||||||
elf::EasyElf,
|
elf::EasyElf,
|
||||||
|
clock,
|
||||||
|
clock::{QemuClockObserver,QemuClockIncreaseFeedback},
|
||||||
};
|
};
|
||||||
use crate::freertos;
|
use crate::freertos;
|
||||||
|
|
||||||
@ -177,6 +179,7 @@ fn fuzz(
|
|||||||
"-kernel", kernel.to_str().unwrap(),
|
"-kernel", kernel.to_str().unwrap(),
|
||||||
"-serial", "stdio", "-nographic",
|
"-serial", "stdio", "-nographic",
|
||||||
"-snapshot", "-drive", "if=none,format=qcow2,file=dummy.qcow2",
|
"-snapshot", "-drive", "if=none,format=qcow2,file=dummy.qcow2",
|
||||||
|
"-icount", "shift=auto,align=off,sleep=off",
|
||||||
"-S"
|
"-S"
|
||||||
].iter().map(|x| x.to_string()).collect();
|
].iter().map(|x| x.to_string()).collect();
|
||||||
let emu = Emulator::new(&mut args, &mut env);
|
let emu = Emulator::new(&mut args, &mut env);
|
||||||
@ -248,11 +251,14 @@ fn fuzz(
|
|||||||
let edges_observer =
|
let edges_observer =
|
||||||
HitcountsMapObserver::new(VariableMapObserver::new("edges", edges, edges_counter));
|
HitcountsMapObserver::new(VariableMapObserver::new("edges", edges, edges_counter));
|
||||||
|
|
||||||
|
//========== Observe Execution Cycles
|
||||||
|
let clock_observer = QemuClockObserver::default();
|
||||||
|
|
||||||
//========= Feedback-Function evaluate the Maps. Need to dump it for debugging and check if it reaches targets.
|
//========= Feedback-Function evaluate the Maps. Need to dump it for debugging and check if it reaches targets.
|
||||||
let feedback = DumpMapFeedback::with_dump(dump_edges);
|
let feedback = DumpMapFeedback::with_dump(dump_edges);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
let objective = CrashFeedback::new();
|
let objective = QemuClockIncreaseFeedback::new();
|
||||||
|
|
||||||
// create a State from scratch
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -315,7 +321,7 @@ fn fuzz(
|
|||||||
QemuSysSnapshotHelper::new(),
|
QemuSysSnapshotHelper::new(),
|
||||||
QemuSystemStateHelper::with_instrumentation_filter(system_state_filter,curr_tcb_pointer.try_into().unwrap(),task_queue_addr.try_into().unwrap())
|
QemuSystemStateHelper::with_instrumentation_filter(system_state_filter,curr_tcb_pointer.try_into().unwrap(),task_queue_addr.try_into().unwrap())
|
||||||
),
|
),
|
||||||
tuple_list!(edges_observer),
|
tuple_list!(edges_observer,clock_observer),
|
||||||
&mut fuzzer,
|
&mut fuzzer,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut mgr,
|
&mut mgr,
|
||||||
|
141
libafl_qemu/src/clock.rs
Normal file
141
libafl_qemu/src/clock.rs
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
use hashbrown::{hash_map::Entry, HashMap};
|
||||||
|
use libafl::{
|
||||||
|
bolts::{
|
||||||
|
current_nanos,
|
||||||
|
rands::StdRand,
|
||||||
|
tuples::{tuple_list},
|
||||||
|
},
|
||||||
|
corpus::{QueueCorpusScheduler},
|
||||||
|
executors::{ExitKind},
|
||||||
|
fuzzer::{StdFuzzer},
|
||||||
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
|
observers::{Observer,VariableMapObserver},
|
||||||
|
state::{StdState},
|
||||||
|
Error,
|
||||||
|
observers::ObserversTuple,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{cell::UnsafeCell, cmp::max};
|
||||||
|
use libafl::bolts::tuples::Named;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
emu,
|
||||||
|
emu::Emulator,
|
||||||
|
executor::QemuExecutor,
|
||||||
|
helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter},
|
||||||
|
};
|
||||||
|
use libafl::events::EventFirer;
|
||||||
|
use libafl::state::HasClientPerfMonitor;
|
||||||
|
use libafl::inputs::Input;
|
||||||
|
use libafl::feedbacks::Feedback;
|
||||||
|
|
||||||
|
//========== Observer
|
||||||
|
|
||||||
|
/// A simple observer, just overlooking the runtime of the target.
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct QemuClockObserver {
|
||||||
|
name: String,
|
||||||
|
last_runtime: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QemuClockObserver {
|
||||||
|
/// Creates a new [`QemuClockObserver`] with the given name.
|
||||||
|
#[must_use]
|
||||||
|
pub fn new(name: &'static str) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
last_runtime: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the runtime for the last execution of this target.
|
||||||
|
#[must_use]
|
||||||
|
pub fn last_runtime(&self) -> i64 {
|
||||||
|
self.last_runtime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, S> Observer<I, S> for QemuClockObserver {
|
||||||
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
|
self.last_runtime=0;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn post_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
|
unsafe { self.last_runtime = emu::libafl_get_clock() };
|
||||||
|
println!("Observer Clock: {}",self.last_runtime());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Named for QemuClockObserver {
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for QemuClockObserver {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
name: String::from("clock"),
|
||||||
|
last_runtime: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//========== Observer
|
||||||
|
|
||||||
|
/// A [`Feedback`] rewarding increasing the execution cycles on Qemu.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct QemuClockIncreaseFeedback {
|
||||||
|
maximum: i64
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, S> Feedback<I, S> for QemuClockIncreaseFeedback
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
S: HasClientPerfMonitor,
|
||||||
|
{
|
||||||
|
fn is_interesting<EM, OT>(
|
||||||
|
&mut self,
|
||||||
|
_state: &mut S,
|
||||||
|
_manager: &mut EM,
|
||||||
|
_input: &I,
|
||||||
|
_observers: &OT,
|
||||||
|
_exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I>,
|
||||||
|
OT: ObserversTuple<I, S>,
|
||||||
|
{
|
||||||
|
let observer = _observers.match_name::<QemuClockObserver>("clock")
|
||||||
|
.expect("QemuClockObserver not found");
|
||||||
|
if observer.last_runtime() >= self.maximum {
|
||||||
|
self.maximum = observer.last_runtime();
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Named for QemuClockIncreaseFeedback {
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"QemuClockFeedback"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QemuClockIncreaseFeedback {
|
||||||
|
/// Creates a new [`HitFeedback`]
|
||||||
|
#[must_use]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {maximum: 0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for QemuClockIncreaseFeedback {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
@ -199,6 +199,8 @@ extern "C" {
|
|||||||
fn libafl_snapshot_save(name: *const c_char) -> i32;
|
fn libafl_snapshot_save(name: *const c_char) -> i32;
|
||||||
#[cfg(feature = "systemmode")]
|
#[cfg(feature = "systemmode")]
|
||||||
fn libafl_snapshot_load(name: *const c_char) -> i32;
|
fn libafl_snapshot_load(name: *const c_char) -> i32;
|
||||||
|
#[cfg(feature = "systemmode")]
|
||||||
|
pub fn libafl_get_clock() -> i64;
|
||||||
|
|
||||||
fn strlen(s: *const u8) -> usize;
|
fn strlen(s: *const u8) -> usize;
|
||||||
|
|
||||||
@ -678,6 +680,11 @@ impl Emulator {
|
|||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "systemmode")]
|
||||||
|
pub fn get_ticks(&self) -> i64{
|
||||||
|
return unsafe { libafl_get_clock() };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "python")]
|
#[cfg(feature = "python")]
|
||||||
|
@ -43,6 +43,10 @@ pub use snapshot::QemuSnapshotHelper;
|
|||||||
pub mod snapshot_sys;
|
pub mod snapshot_sys;
|
||||||
#[cfg(all(target_os = "linux",feature = "systemmode"))]
|
#[cfg(all(target_os = "linux",feature = "systemmode"))]
|
||||||
pub use snapshot_sys::QemuSysSnapshotHelper;
|
pub use snapshot_sys::QemuSysSnapshotHelper;
|
||||||
|
#[cfg(all(target_os = "linux",feature = "systemmode"))]
|
||||||
|
pub mod clock;
|
||||||
|
#[cfg(all(target_os = "linux",feature = "systemmode"))]
|
||||||
|
pub use clock::QemuClockObserver;
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub mod asan;
|
pub mod asan;
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user