diff --git a/fuzzers/wcet_qemu_sys/.gitignore b/fuzzers/wcet_qemu_sys/.gitignore new file mode 100644 index 0000000000..456d0151b4 --- /dev/null +++ b/fuzzers/wcet_qemu_sys/.gitignore @@ -0,0 +1,5 @@ +*.axf +*.qcow2 +demo +*.ron +*.bsp diff --git a/fuzzers/wcet_qemu_sys/src/freertos.rs b/fuzzers/wcet_qemu_sys/src/freertos.rs index 56c0dc4168..f26695011d 100644 --- a/fuzzers/wcet_qemu_sys/src/freertos.rs +++ b/fuzzers/wcet_qemu_sys/src/freertos.rs @@ -1,3 +1,4 @@ +use serde::{Deserialize, Serialize}; // Manual Types use libafl_qemu::Emulator; @@ -20,7 +21,7 @@ pub type StackType_t = u32; pub type UBaseType_t = ::std::os::raw::c_uint; pub type TickType_t = u32; #[repr(C)] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)] pub struct xLIST_ITEM { pub xItemValue: TickType_t, pub pxNext: xLIST_ITEM_ptr, @@ -93,7 +94,7 @@ fn bindgen_test_layout_xLIST_ITEM() { } pub type ListItem_t = xLIST_ITEM; #[repr(C)] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)] pub struct xMINI_LIST_ITEM { pub xItemValue: TickType_t, pub pxNext: xLIST_ITEM_ptr, @@ -144,7 +145,7 @@ fn bindgen_test_layout_xMINI_LIST_ITEM() { } pub type MiniListItem_t = xMINI_LIST_ITEM; #[repr(C)] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, Default)] pub struct xLIST { pub uxNumberOfItems: UBaseType_t, pub pxIndex: ListItem_t_ptr, @@ -194,7 +195,7 @@ fn bindgen_test_layout_xLIST() { ); } pub type List_t = xLIST; -pub type TaskHandle_t = *mut tskTaskControlBlock; +pub type TaskHandle_t = ::std::os::raw::c_uint; pub const eTaskState_eRunning: eTaskState = 0; pub const eTaskState_eReady: eTaskState = 1; pub const eTaskState_eBlocked: eTaskState = 2; @@ -203,7 +204,7 @@ pub const eTaskState_eDeleted: eTaskState = 4; pub const eTaskState_eInvalid: eTaskState = 5; pub type eTaskState = ::std::os::raw::c_uint; #[repr(C)] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] pub struct xTASK_STATUS { pub xHandle: TaskHandle_t, pub pcTaskName: char_ptr, @@ -322,14 +323,14 @@ fn bindgen_test_layout_xTASK_STATUS() { } pub type TaskStatus_t = xTASK_STATUS; #[repr(C)] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)] pub struct tskTaskControlBlock { pub pxTopOfStack: StackType_t_ptr, pub xStateListItem: ListItem_t, pub xEventListItem: ListItem_t, pub uxPriority: UBaseType_t, pub pxStack: StackType_t_ptr, - pub pcTaskName: [::std::os::raw::c_char; 10usize], + pub pcTaskName: [::std::os::raw::c_uchar; 10usize], pub uxBasePriority: UBaseType_t, pub uxMutexesHeld: UBaseType_t, pub ulNotifiedValue: [u32; 1usize], diff --git a/fuzzers/wcet_qemu_sys/src/main.rs b/fuzzers/wcet_qemu_sys/src/main.rs index 0440b6238c..cca2809009 100644 --- a/fuzzers/wcet_qemu_sys/src/main.rs +++ b/fuzzers/wcet_qemu_sys/src/main.rs @@ -3,6 +3,7 @@ pub mod fuzzer; pub mod showmap; pub mod worst; pub mod freertos; +pub mod system_trace; use libafl_qemu::{ edges, edges::QemuEdgeCoverageHelper, diff --git a/fuzzers/wcet_qemu_sys/src/showmap.rs b/fuzzers/wcet_qemu_sys/src/showmap.rs index 6f481ae659..f9f9ef5755 100644 --- a/fuzzers/wcet_qemu_sys/src/showmap.rs +++ b/fuzzers/wcet_qemu_sys/src/showmap.rs @@ -1,5 +1,6 @@ //! A singlethreaded QEMU fuzzer that can auto-restart. +use crate::system_trace::QemuSystemStateHelper; use libafl::feedbacks::CrashFeedback; use std::path::Path; use libafl_qemu::QemuExecutor; @@ -208,6 +209,21 @@ fn fuzz( .expect("Symbol pxReadyTasksLists not found"); // let task_queue_addr = virt2phys(task_queue_addr,&elf.goblin()); println!("Task Queue at {:#x}", task_queue_addr); + let shv = elf + .resolve_symbol("xPortSysTickHandler", 0) + .expect("Symbol xPortSysTickHandler not found"); + let shv = virt2phys(shv,&elf.goblin()); + println!("SysTick at {:#x}", shv); + let shv = elf + .resolve_symbol("vPortSVCHandler", 0) + .expect("Symbol vPortSVCHandler not found"); + let shv = virt2phys(shv,&elf.goblin()); + println!("SVChandle at {:#x}", shv); + let shv = elf + .resolve_symbol("xPortPendSVHandler", 0) + .expect("Symbol xPortPendSVHandler not found"); + let shv = virt2phys(shv,&elf.goblin()); + println!("PendHandle at {:#x}", shv); @@ -274,12 +290,12 @@ fn fuzz( emu.run(); //====== experiment inspecting the current tcb - let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(&emu, curr_tcb_pointer.try_into().unwrap()); - println!("Current TCB addr: {:x}",curr_tcb_addr); - let current_tcb : freertos::TCB_t = freertos::emu_lookup::lookup(&emu,curr_tcb_addr); - println!("Current TCB: {:?}",current_tcb); - let ready_queue : freertos::List_t = freertos::emu_lookup::lookup(&emu,task_queue_addr.try_into().unwrap()); - println!("Ready Queue: {:?}",ready_queue); + // let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(&emu, curr_tcb_pointer.try_into().unwrap()); + // println!("Current TCB addr: {:x}",curr_tcb_addr); + // let current_tcb : freertos::TCB_t = freertos::emu_lookup::lookup(&emu,curr_tcb_addr); + // println!("Current TCB: {:?}",current_tcb); + // let ready_queue : freertos::List_t = freertos::emu_lookup::lookup(&emu,task_queue_addr.try_into().unwrap()); + // println!("Ready Queue: {:?}",ready_queue); } ExitKind::Ok @@ -293,7 +309,8 @@ fn fuzz( QemuEdgeCoverageHelper::new(), // QemuCmpLogHelper::new(), // QemuAsanHelper::new(), - QemuSysSnapshotHelper::new() + QemuSysSnapshotHelper::new(), + QemuSystemStateHelper::new() ), tuple_list!(edges_observer), &mut fuzzer, @@ -305,17 +322,6 @@ fn fuzz( false => seed_dir.clone() }; fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, Input::from_file(&firstinput).expect("Could not load file")).expect("Evaluation failed"); - // fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, Input::from_file(&firstinput).expect("Could not load file")).expect("Evaluation failed"); - // let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations())); - // let mut stages = tuple_list!(StdMutationalStage::new(mutator)); - // if state.corpus().count() < 1 { - // state - // .load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()]) - // .expect("Failed to load initial corpus"); - // println!("We imported {} inputs from disk.", state.corpus().count()); - // } - // fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr) - // .expect("Error in the fuzzing loop"); return Ok(()); } diff --git a/fuzzers/wcet_qemu_sys/src/system_trace.rs b/fuzzers/wcet_qemu_sys/src/system_trace.rs new file mode 100644 index 0000000000..823a6acecf --- /dev/null +++ b/fuzzers/wcet_qemu_sys/src/system_trace.rs @@ -0,0 +1,110 @@ +use crate::freertos; +use hashbrown::HashMap; +use libafl::{executors::ExitKind, inputs::Input, observers::ObserversTuple, state::HasMetadata}; +use serde::{Deserialize, Serialize}; + +use libafl_qemu::{ + emu::Emulator, + executor::QemuExecutor, + helper::{QemuHelper, QemuHelperTuple, QemuInstrumentationFilter}, +}; + +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct QemuSystemStateMetadata { + pub tcbs: Vec, + // pub map: HashMap, + // pub current_id: u64, +} + +impl QemuSystemStateMetadata { + #[must_use] + pub fn new() -> Self { + Self { + tcbs: Vec::new(), + // map: HashMap::new(), + // current_id: 0, + } + } +} + +libafl::impl_serdeany!(QemuSystemStateMetadata); + +#[derive(Debug)] +pub struct QemuSystemStateHelper { + filter: QemuInstrumentationFilter, +} + +impl QemuSystemStateHelper { + #[must_use] + pub fn new() -> Self { + Self { + filter: QemuInstrumentationFilter::None, + } + } + + #[must_use] + pub fn with_instrumentation_filter(filter: QemuInstrumentationFilter) -> Self { + Self { filter } + } + + #[must_use] + pub fn must_instrument(&self, addr: u64) -> bool { + self.filter.allowed(addr) + } +} + +impl Default for QemuSystemStateHelper { + fn default() -> Self { + Self::new() + } +} + +impl QemuHelper for QemuSystemStateHelper +where + I: Input, + S: HasMetadata, +{ + fn init<'a, H, OT, QT>(&self, executor: &QemuExecutor<'a, H, I, OT, QT, S>) + where + H: FnMut(&I) -> ExitKind, + OT: ObserversTuple, + QT: QemuHelperTuple, + { + executor.hook_block_execution(exec_syscall_hook::); + } +} + +pub fn exec_syscall_hook( + emulator: &Emulator, + helpers: &mut QT, + state: &mut S, + pc: u64, +) +where + S: HasMetadata, + I: Input, + QT: QemuHelperTuple, +{ + // if pc == 0x2e8 { //vPortSVCHandler + // if pc == 0x3c4 { //SystemTick + if pc == 0x37c { //xPortPendSVHandler + if let Some(h) = helpers.match_first_type::() { + if !h.must_instrument(pc) { + return; + } + } + if state.metadata().get::().is_none() { + state.add_metadata(QemuSystemStateMetadata::new()); + } + let meta = state + .metadata_mut() + .get_mut::() + .unwrap(); + let curr_tcb_addr : freertos::void_ptr = freertos::emu_lookup::lookup(emulator, 0x20006ff0.try_into().unwrap()); + // println!("Current TCB addr: {:x}",curr_tcb_addr); + let current_tcb : freertos::TCB_t = freertos::emu_lookup::lookup(emulator,curr_tcb_addr); + println!("{}", std::str::from_utf8(¤t_tcb.pcTaskName).unwrap()); + meta.tcbs.push(current_tcb); + let id = meta.tcbs.len(); + } +}