prepare system state observer+feedback
This commit is contained in:
parent
819f759be9
commit
c3f398a315
@ -1,5 +1,6 @@
|
|||||||
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
||||||
|
|
||||||
|
use wcet_qemu_sys::system_trace::QemuSysStateObserver;
|
||||||
use wcet_qemu_sys::worst::QemuHashMapObserver;
|
use wcet_qemu_sys::worst::QemuHashMapObserver;
|
||||||
use wcet_qemu_sys::{
|
use wcet_qemu_sys::{
|
||||||
worst::{DumpMapFeedback,DummyFeedback},
|
worst::{DumpMapFeedback,DummyFeedback},
|
||||||
@ -328,7 +329,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,clock_observer),
|
tuple_list!(edges_observer,clock_observer,QemuSysStateObserver::new()),
|
||||||
&mut fuzzer,
|
&mut fuzzer,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut mgr,
|
&mut mgr,
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
use libafl::events::EventFirer;
|
||||||
|
use libafl::state::HasClientPerfMonitor;
|
||||||
|
use libafl::feedbacks::Feedback;
|
||||||
|
use libafl::bolts::HasLen;
|
||||||
|
use libafl::bolts::tuples::Named;
|
||||||
|
use libafl::Error;
|
||||||
|
use libafl::observers::Observer;
|
||||||
use crate::freertos::rtos_struct::*;
|
use crate::freertos::rtos_struct::*;
|
||||||
use crate::freertos;
|
use crate::freertos;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
@ -5,27 +12,36 @@ use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, stat
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use libafl_qemu::{
|
use libafl_qemu::{
|
||||||
|
emu,
|
||||||
emu::Emulator,
|
emu::Emulator,
|
||||||
executor::QemuExecutor,
|
executor::QemuExecutor,
|
||||||
helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter},
|
helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//============================= Datatypes
|
||||||
|
|
||||||
|
/// Info Dump from Qemu
|
||||||
|
pub type SysState = (u64,freertos::TCB_t,HashMap<u32,freertos::rtos_struct>);
|
||||||
|
|
||||||
|
/// Refined information about the states an execution transitioned between
|
||||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct QemuSystemStateMetadata {
|
pub struct QemuSystemStateMetadata {
|
||||||
pub rtos_states: Vec<(freertos::TCB_t,HashMap<u32,freertos::rtos_struct>)>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QemuSystemStateMetadata {
|
impl QemuSystemStateMetadata {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {}
|
||||||
rtos_states: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
libafl::impl_serdeany!(QemuSystemStateMetadata);
|
libafl::impl_serdeany!(QemuSystemStateMetadata);
|
||||||
|
|
||||||
|
|
||||||
|
//============================= Qemu Helper
|
||||||
|
static mut CURRENT_SYSSTATE_VEC: Vec<SysState> = vec![];
|
||||||
|
|
||||||
|
/// A Qemu Helper with reads FreeRTOS specific structs from Qemu whenever certain syscalls occur
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct QemuSystemStateHelper {
|
pub struct QemuSystemStateHelper {
|
||||||
filter: QemuInstrumentationFilter,
|
filter: QemuInstrumentationFilter,
|
||||||
@ -65,6 +81,8 @@ where
|
|||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
QT: QemuHelperTuple<I, S>,
|
QT: QemuHelperTuple<I, S>,
|
||||||
{
|
{
|
||||||
|
// emu::Emulator{_private: ()}.set_gen_block_hook(test_gen_hook);
|
||||||
|
executor.hook_block_generation(gen_not_exec_block_hook::<I, QT, S>);
|
||||||
executor.hook_block_execution(exec_syscall_hook::<I, QT, S>);
|
executor.hook_block_execution(exec_syscall_hook::<I, QT, S>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,26 +102,135 @@ where
|
|||||||
if !h.must_instrument(pc) {
|
if !h.must_instrument(pc) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if state.metadata().get::<QemuSystemStateMetadata>().is_none() {
|
let current_clock = emulator.get_ticks();
|
||||||
state.add_metadata(QemuSystemStateMetadata::new());
|
|
||||||
}
|
|
||||||
let meta = state
|
|
||||||
.metadata_mut()
|
|
||||||
.get_mut::<QemuSystemStateMetadata>()
|
|
||||||
.unwrap();
|
|
||||||
let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(emulator, h.tcb_addr);
|
let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(emulator, h.tcb_addr);
|
||||||
// println!("Current TCB addr: {:x}",curr_tcb_addr);
|
|
||||||
let current_tcb : freertos::TCB_t = freertos::emu_lookup::lookup(emulator,curr_tcb_addr);
|
let current_tcb : freertos::TCB_t = freertos::emu_lookup::lookup(emulator,curr_tcb_addr);
|
||||||
println!("{:?}",current_tcb);
|
let mut result_tup : SysState = (current_clock,current_tcb, HashMap::with_capacity(5));
|
||||||
println!("{}", std::str::from_utf8(¤t_tcb.pcTaskName).unwrap());
|
|
||||||
let mut result_tup : (freertos::TCB_t,HashMap<u32,freertos::rtos_struct>) = (current_tcb, HashMap::with_capacity(5));
|
|
||||||
for i in 0..4 {
|
for i in 0..4 {
|
||||||
let target : u32= (std::mem::size_of::<freertos::List_t>()*i).try_into().unwrap();
|
let target : u32= (std::mem::size_of::<freertos::List_t>()*i).try_into().unwrap();
|
||||||
let ready_list : freertos::List_t = freertos::emu_lookup::lookup(emulator, h.ready_queues+target);
|
let ready_list : freertos::List_t = freertos::emu_lookup::lookup(emulator, h.ready_queues+target);
|
||||||
let a : freertos::rtos_struct = List_struct(ready_list);
|
let a : freertos::rtos_struct = List_struct(ready_list);
|
||||||
result_tup.1.insert(target,a);
|
result_tup.2.insert(target,a);
|
||||||
// println!("{:?}",ready_list);
|
|
||||||
// println!("Prio: {} Number: {} first {:x}",i,ready_list.uxNumberOfItems, ready_list.pxIndex);
|
|
||||||
}
|
}
|
||||||
meta.rtos_states.push(result_tup);
|
|
||||||
|
unsafe { CURRENT_SYSSTATE_VEC.push(result_tup); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn test_gen_hook(pc: u64) -> u64 {
|
||||||
|
u32::MAX as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen_not_exec_block_hook<I, QT, S>(
|
||||||
|
_emulator: &Emulator,
|
||||||
|
helpers: &mut QT,
|
||||||
|
_state: &mut S,
|
||||||
|
pc: u64,
|
||||||
|
)
|
||||||
|
-> Option<u64> where
|
||||||
|
S: HasMetadata,
|
||||||
|
I: Input,
|
||||||
|
QT: QemuHelperTuple<I, S>,
|
||||||
|
{
|
||||||
|
let h = helpers.match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel");
|
||||||
|
if !h.must_instrument(pc) {
|
||||||
|
None
|
||||||
|
} else {Some(1)}
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================= Observer
|
||||||
|
|
||||||
|
/// The QemuSysState Observer retrieves the SysState
|
||||||
|
/// that will get updated by the target.
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||||
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
|
pub struct QemuSysStateObserver
|
||||||
|
{
|
||||||
|
last_run: Vec<SysState>,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, S> Observer<I, S> for QemuSysStateObserver
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
|
unsafe {CURRENT_SYSSTATE_VEC.clear(); }
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn post_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
|
unsafe {self.last_run.append(&mut CURRENT_SYSSTATE_VEC);}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Named for QemuSysStateObserver
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
self.name.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HasLen for QemuSysStateObserver
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
self.last_run.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QemuSysStateObserver {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self{last_run: vec![], name: "sysstate".to_string()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================= Feedback
|
||||||
|
|
||||||
|
/// A Feedback reporting interesting System-State Transitions
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct SysStateFeedback
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, S> Feedback<I, S> for SysStateFeedback
|
||||||
|
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::<QemuSysStateObserver>("sysstate")
|
||||||
|
.expect("QemuSysStateObserver not found");
|
||||||
|
// Do Stuff
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Named for SysStateFeedback
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"sysstate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SysStateFeedback
|
||||||
|
{
|
||||||
|
/// Creates a new [`SysStateFeedback`]
|
||||||
|
#[must_use]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user