prepare system state observer+feedback

This commit is contained in:
Alwin Berger 2022-02-13 20:19:50 +01:00
parent 819f759be9
commit c3f398a315
2 changed files with 148 additions and 20 deletions

View File

@ -1,5 +1,6 @@
//! 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::{DumpMapFeedback,DummyFeedback},
@ -328,7 +329,7 @@ fn fuzz(
QemuSysSnapshotHelper::new(),
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 state,
&mut mgr,

View File

@ -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;
use hashbrown::HashMap;
@ -5,27 +12,36 @@ use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, stat
use serde::{Deserialize, Serialize};
use libafl_qemu::{
emu,
emu::Emulator,
executor::QemuExecutor,
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)]
pub struct QemuSystemStateMetadata {
pub rtos_states: Vec<(freertos::TCB_t,HashMap<u32,freertos::rtos_struct>)>,
}
impl QemuSystemStateMetadata {
#[must_use]
pub fn new() -> Self {
Self {
rtos_states: Vec::new(),
}
Self {}
}
}
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)]
pub struct QemuSystemStateHelper {
filter: QemuInstrumentationFilter,
@ -65,6 +81,8 @@ where
OT: ObserversTuple<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>);
}
}
@ -84,26 +102,135 @@ where
if !h.must_instrument(pc) {
return;
}
if state.metadata().get::<QemuSystemStateMetadata>().is_none() {
state.add_metadata(QemuSystemStateMetadata::new());
}
let meta = state
.metadata_mut()
.get_mut::<QemuSystemStateMetadata>()
.unwrap();
let current_clock = emulator.get_ticks();
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);
println!("{:?}",current_tcb);
println!("{}", std::str::from_utf8(&current_tcb.pcTaskName).unwrap());
let mut result_tup : (freertos::TCB_t,HashMap<u32,freertos::rtos_struct>) = (current_tcb, HashMap::with_capacity(5));
let mut result_tup : SysState = (current_clock,current_tcb, HashMap::with_capacity(5));
for i in 0..4 {
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 a : freertos::rtos_struct = List_struct(ready_list);
result_tup.1.insert(target,a);
// println!("{:?}",ready_list);
// println!("Prio: {} Number: {} first {:x}",i,ready_list.uxNumberOfItems, ready_list.pxIndex);
result_tup.2.insert(target,a);
}
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 {}
}
meta.rtos_states.push(result_tup);
}