centralise target symbols
This commit is contained in:
parent
a13dca6f39
commit
79d3f89254
@ -3,7 +3,7 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
// Argument parsing ================================================================================
|
// Argument parsing ================================================================================
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser,Debug)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
pub struct Cli {
|
pub struct Cli {
|
||||||
/// Kernel Image
|
/// Kernel Image
|
||||||
@ -41,7 +41,7 @@ pub struct Cli {
|
|||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
pub command: Commands,
|
pub command: Commands,
|
||||||
}
|
}
|
||||||
#[derive(Subcommand,Clone)]
|
#[derive(Subcommand,Clone,Debug)]
|
||||||
pub enum Commands {
|
pub enum Commands {
|
||||||
/// run a single input
|
/// run a single input
|
||||||
Showmap {
|
Showmap {
|
||||||
|
97
fuzzers/FRET/src/config.rs
Normal file
97
fuzzers/FRET/src/config.rs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
use hashbrown::HashMap;
|
||||||
|
use libafl_qemu::{elf::EasyElf, GuestAddr};
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
use crate::systemstate::helpers::{load_symbol, try_load_symbol};
|
||||||
|
|
||||||
|
pub fn get_target_symbols(elf: &EasyElf) -> HashMap<&'static str, GuestAddr> {
|
||||||
|
let mut addrs = HashMap::new();
|
||||||
|
|
||||||
|
addrs.insert(
|
||||||
|
"__APP_CODE_START__",
|
||||||
|
load_symbol(&elf, "__APP_CODE_START__", false),
|
||||||
|
);
|
||||||
|
addrs.insert(
|
||||||
|
"__APP_CODE_END__",
|
||||||
|
load_symbol(&elf, "__APP_CODE_END__", false),
|
||||||
|
);
|
||||||
|
addrs.insert(
|
||||||
|
"__API_CODE_START__",
|
||||||
|
load_symbol(&elf, "__API_CODE_START__", false),
|
||||||
|
);
|
||||||
|
addrs.insert(
|
||||||
|
"__API_CODE_END__",
|
||||||
|
load_symbol(&elf, "__API_CODE_END__", false),
|
||||||
|
);
|
||||||
|
addrs.insert(
|
||||||
|
"trigger_job_done",
|
||||||
|
load_symbol(&elf, "trigger_job_done", false),
|
||||||
|
);
|
||||||
|
|
||||||
|
crate::systemstate::target_os::freertos::config::add_target_symbols(elf, &mut addrs);
|
||||||
|
|
||||||
|
// the main address where the fuzzer starts
|
||||||
|
// if this is set for freeRTOS it has an influence on where the data will have to be written,
|
||||||
|
// since the startup routine copies the data segemnt to it's virtual address
|
||||||
|
let main_addr = elf.resolve_symbol(
|
||||||
|
&env::var("FUZZ_MAIN").unwrap_or_else(|_| "FUZZ_MAIN".to_owned()),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
if let Some(main_addr) = main_addr {
|
||||||
|
addrs.insert("FUZZ_MAIN", main_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
let input_addr = load_symbol(
|
||||||
|
&elf,
|
||||||
|
&env::var("FUZZ_INPUT").unwrap_or_else(|_| "FUZZ_INPUT".to_owned()),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
addrs.insert("FUZZ_INPUT", input_addr);
|
||||||
|
|
||||||
|
let input_length_ptr = try_load_symbol(
|
||||||
|
&elf,
|
||||||
|
&env::var("FUZZ_LENGTH").unwrap_or_else(|_| "FUZZ_LENGTH".to_owned()),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
if let Some(input_length_ptr) = input_length_ptr {
|
||||||
|
addrs.insert("FUZZ_LENGTH", input_length_ptr);
|
||||||
|
}
|
||||||
|
let input_counter_ptr = try_load_symbol(
|
||||||
|
&elf,
|
||||||
|
&env::var("FUZZ_POINTER").unwrap_or_else(|_| "FUZZ_POINTER".to_owned()),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
if let Some(input_counter_ptr) = input_counter_ptr {
|
||||||
|
addrs.insert("FUZZ_POINTER", input_counter_ptr);
|
||||||
|
}
|
||||||
|
addrs.insert(
|
||||||
|
"BREAKPOINT",
|
||||||
|
elf.resolve_symbol(
|
||||||
|
&env::var("BREAKPOINT").unwrap_or_else(|_| "BREAKPOINT".to_owned()),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.expect("Symbol or env BREAKPOINT not found"),
|
||||||
|
);
|
||||||
|
|
||||||
|
addrs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_target_ranges(
|
||||||
|
elf: &EasyElf,
|
||||||
|
symbols: &HashMap<&'static str, GuestAddr>,
|
||||||
|
) -> HashMap<&'static str, std::ops::Range<GuestAddr>> {
|
||||||
|
let mut ranges = HashMap::new();
|
||||||
|
|
||||||
|
ranges.insert(
|
||||||
|
"APP_CODE",
|
||||||
|
symbols["__APP_CODE_START__"]..symbols["__APP_CODE_END__"],
|
||||||
|
);
|
||||||
|
ranges.insert(
|
||||||
|
"API_CODE",
|
||||||
|
symbols["__API_CODE_START__"]..symbols["__API_CODE_END__"],
|
||||||
|
);
|
||||||
|
|
||||||
|
crate::systemstate::target_os::freertos::config::add_target_ranges(elf, symbols, &mut ranges);
|
||||||
|
|
||||||
|
ranges
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
//! A fuzzer using qemu in systemmode for binary-only coverage of kernels
|
//! A fuzzer using qemu in systemmode for binary-only coverage of kernels
|
||||||
//!
|
//!
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use std::{env, path::PathBuf, process::{self, abort}, io::{Read, Write}, fs::{self, OpenOptions}, cmp::{min, max}, mem::transmute_copy, collections::btree_map::Range, ptr::addr_of_mut, ffi::OsStr};
|
use std::{env, path::PathBuf, process::{self, abort}, io::{Read, Write}, fs::{self, OpenOptions}, cmp::{min, max}, mem::transmute_copy, ptr::addr_of_mut, ffi::OsStr};
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
core_affinity::Cores, ownedref::OwnedMutSlice, rands::StdRand, shmem::{ShMemProvider, StdShMemProvider}, tuples::tuple_list, AsSlice, SimpleStderrLogger
|
core_affinity::Cores, ownedref::OwnedMutSlice, rands::StdRand, shmem::{ShMemProvider, StdShMemProvider}, tuples::tuple_list, AsSlice, SimpleStderrLogger
|
||||||
@ -14,7 +14,7 @@ elf::EasyElf, emu::Emulator, modules::{edges::{self}, FilterList}, GuestAddr, Gu
|
|||||||
};
|
};
|
||||||
use rand::{SeedableRng, StdRng, Rng};
|
use rand::{SeedableRng, StdRng, Rng};
|
||||||
use crate::{
|
use crate::{
|
||||||
systemstate::{self, feedbacks::{DumpSystraceFeedback, SystraceErrorFeedback}, helpers::{get_function_range, load_symbol, try_load_symbol}, mutational::{input_bytes_to_interrupt_times, InterruptShiftStage, STGSnippetStage}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, GraphMaximizerCorpusScheduler, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}, target_os::freertos::{qemu_module::FreeRTOSSystemStateHelper, FreeRTOSSystem}}, time::{
|
config::{get_target_ranges, get_target_symbols}, systemstate::{self, feedbacks::{DumpSystraceFeedback, SystraceErrorFeedback}, helpers::{get_function_range, load_symbol, try_load_symbol}, mutational::{input_bytes_to_interrupt_times, InterruptShiftStage, STGSnippetStage}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, GraphMaximizerCorpusScheduler, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}, target_os::freertos::{config::get_range_groups, qemu_module::FreeRTOSSystemStateHelper, FreeRTOSSystem}}, time::{
|
||||||
clock::{ClockTimeFeedback, IcHist, QemuClockIncreaseFeedback, QemuClockObserver, FUZZ_START_TIMESTAMP, QEMU_ICOUNT_SHIFT, QEMU_ISNS_PER_USEC}, qemustate::QemuStateRestoreHelper, worst::{AlwaysTrueFeedback, ExecTimeIncFeedback, RateLimitedMonitor, TimeMaximizerCorpusScheduler, TimeProbMassScheduler, TimeStateMaximizerCorpusScheduler}
|
clock::{ClockTimeFeedback, IcHist, QemuClockIncreaseFeedback, QemuClockObserver, FUZZ_START_TIMESTAMP, QEMU_ICOUNT_SHIFT, QEMU_ISNS_PER_USEC}, qemustate::QemuStateRestoreHelper, worst::{AlwaysTrueFeedback, ExecTimeIncFeedback, RateLimitedMonitor, TimeMaximizerCorpusScheduler, TimeProbMassScheduler, TimeStateMaximizerCorpusScheduler}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -30,6 +30,7 @@ use clap::Parser;
|
|||||||
use log;
|
use log;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use crate::templates;
|
use crate::templates;
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
// Constants ================================================================================
|
// Constants ================================================================================
|
||||||
|
|
||||||
@ -40,30 +41,27 @@ pub const FIRST_INT : u32 = 200000;
|
|||||||
pub const MAX_NUM_INTERRUPT: usize = 128;
|
pub const MAX_NUM_INTERRUPT: usize = 128;
|
||||||
pub const NUM_INTERRUPT_SOURCES: usize = 6; // Keep in sync with qemu-libafl-bridge/hw/timer/armv7m_systick.c:319 and FreeRTOS/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/init/startup.c:216
|
pub const NUM_INTERRUPT_SOURCES: usize = 6; // Keep in sync with qemu-libafl-bridge/hw/timer/armv7m_systick.c:319 and FreeRTOS/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/init/startup.c:216
|
||||||
pub const DO_NUM_INTERRUPT: usize = 128;
|
pub const DO_NUM_INTERRUPT: usize = 128;
|
||||||
pub static mut MAX_INPUT_SIZE: usize = 32;
|
pub static mut MAX_INPUT_SIZE: usize = 1024;
|
||||||
|
|
||||||
pub fn get_all_fn_symbol_ranges(elf: &EasyElf, api_range: std::ops::Range<GuestAddr>) -> HashMap<String,std::ops::Range<GuestAddr>> {
|
pub fn get_all_fn_symbol_ranges(elf: &EasyElf, range: std::ops::Range<GuestAddr>) -> HashMap<String,std::ops::Range<GuestAddr>> {
|
||||||
let mut api_addreses : HashMap<String,std::ops::Range<GuestAddr>> = HashMap::new();
|
let mut ret : HashMap<String,std::ops::Range<GuestAddr>> = HashMap::new();
|
||||||
|
|
||||||
let gob = elf.goblin();
|
let gob = elf.goblin();
|
||||||
|
|
||||||
let mut funcs : Vec<_> = gob.syms.iter().filter(|x| x.is_function() && api_range.contains(&x.st_value.try_into().unwrap())).collect();
|
let mut funcs : Vec<_> = gob.syms.iter().filter(|x| x.is_function() && range.contains(&x.st_value.try_into().unwrap())).collect();
|
||||||
funcs.sort_unstable_by(|x,y| x.st_value.cmp(&y.st_value));
|
funcs.sort_unstable_by(|x,y| x.st_value.cmp(&y.st_value));
|
||||||
|
|
||||||
for sym in &funcs {
|
for sym in &funcs {
|
||||||
let sym_name = gob.strtab.get_at(sym.st_name);
|
let sym_name = gob.strtab.get_at(sym.st_name);
|
||||||
if let Some(sym_name) = sym_name {
|
if let Some(sym_name) = sym_name {
|
||||||
// if ISR_SYMBOLS.contains(&sym_name) {continue;}; // skip select symbols, which correspond to ISR-safe system calls
|
// if ISR_SYMBOLS.contains(&sym_name) {continue;}; // skip select symbols, which correspond to ISR-safe system calls
|
||||||
if let Some(r) = get_function_range(elf, sym_name) {
|
if let Some(r) = get_function_range(elf, sym_name) {
|
||||||
api_addreses.insert(sym_name.to_string(), r);
|
ret.insert(sym_name.to_string(), r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for i in api_addreses.iter() {
|
|
||||||
println!("{} {:#x}..{:#x}", i.0, i.1.start, i.1.end);
|
|
||||||
}
|
|
||||||
|
|
||||||
return api_addreses;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
@ -160,6 +158,7 @@ pub fn fuzz() {
|
|||||||
log::set_max_level(log::LevelFilter::Info);
|
log::set_max_level(log::LevelFilter::Info);
|
||||||
SimpleStderrLogger::set_logger().unwrap();
|
SimpleStderrLogger::set_logger().unwrap();
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
dbg!(&cli);
|
||||||
set_env_from_config(&cli.kernel, &cli.config);
|
set_env_from_config(&cli.kernel, &cli.config);
|
||||||
let interrupt_config = crate::cli::get_interrupt_config(&cli.kernel, &cli.config);
|
let interrupt_config = crate::cli::get_interrupt_config(&cli.kernel, &cli.config);
|
||||||
unsafe {FUZZ_START_TIMESTAMP = SystemTime::now();}
|
unsafe {FUZZ_START_TIMESTAMP = SystemTime::now();}
|
||||||
@ -181,52 +180,10 @@ let elf = EasyElf::from_file(
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// the main address where the fuzzer starts
|
let TARGET_SYMBOLS: HashMap<&'static str, GuestAddr> = get_target_symbols(&elf);
|
||||||
// if this is set for freeRTOS it has an influence on where the data will have to be written,
|
let TARGET_RANGES: HashMap<&'static str, Range<GuestAddr>> = get_target_ranges(&elf, &TARGET_SYMBOLS);
|
||||||
// since the startup routine copies the data segemnt to it's virtual address
|
let TARGET_GROUPS: HashMap<&'static str, HashMap<String, Range<GuestAddr>>> = get_range_groups(&elf, &TARGET_SYMBOLS, &TARGET_RANGES);
|
||||||
let main_addr = elf
|
|
||||||
.resolve_symbol(&env::var("FUZZ_MAIN").unwrap_or_else(|_| "FUZZ_MAIN".to_owned()), 0);
|
|
||||||
if let Some(main_addr) = main_addr {
|
|
||||||
println!("main address = {:#x}", main_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
let input_addr = load_symbol(&elf, &env::var("FUZZ_INPUT").unwrap_or_else(|_| "FUZZ_INPUT".to_owned()), true);
|
|
||||||
println!("FUZZ_INPUT @ {:#x}", input_addr);
|
|
||||||
|
|
||||||
let input_length_ptr = try_load_symbol(&elf, &env::var("FUZZ_LENGTH").unwrap_or_else(|_| "FUZZ_LENGTH".to_owned()), true);
|
|
||||||
let input_counter_ptr = try_load_symbol(&elf, &env::var("FUZZ_POINTER").unwrap_or_else(|_| "FUZZ_POINTER".to_owned()), true);
|
|
||||||
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
let curr_tcb_pointer = load_symbol(&elf, "pxCurrentTCB", false); // loads to the address specified in elf, without respecting program headers
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
println!("TCB pointer at {:#x}", curr_tcb_pointer);
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
let task_queue_addr = load_symbol(&elf, "pxReadyTasksLists", false);
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
let task_delay_addr = load_symbol(&elf, "pxDelayedTaskList", false);
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
let task_delay_overflow_addr = load_symbol(&elf, "pxOverflowDelayedTaskList", false);
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
let scheduler_lock = load_symbol(&elf, "uxSchedulerSuspended", false);
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
let scheduler_running = load_symbol(&elf, "xSchedulerRunning", false);
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
let critical_section = load_symbol(&elf, "uxCriticalNesting", false);
|
|
||||||
let app_start = load_symbol(&elf, "__APP_CODE_START__", false);
|
|
||||||
let app_end = load_symbol(&elf, "__APP_CODE_END__", false);
|
|
||||||
let app_range = app_start..app_end;
|
|
||||||
let api_start = load_symbol(&elf, "__API_CODE_START__", false);
|
|
||||||
let api_end = load_symbol(&elf, "__API_CODE_END__", false);
|
|
||||||
let api_range = api_start..api_end;
|
|
||||||
let job_done_addr = load_symbol(&elf, "trigger_job_done", false);
|
|
||||||
|
|
||||||
let breakpoint = elf
|
|
||||||
.resolve_symbol(
|
|
||||||
&env::var("BREAKPOINT").unwrap_or_else(|_| "BREAKPOINT".to_owned()),
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
.expect("Symbol or env BREAKPOINT not found");
|
|
||||||
println!("Breakpoint address = {:#x}", breakpoint);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
libafl_num_interrupts = [0; NUM_INTERRUPT_SOURCES];
|
libafl_num_interrupts = [0; NUM_INTERRUPT_SOURCES];
|
||||||
}
|
}
|
||||||
@ -240,37 +197,9 @@ if let Ok(seed) = env::var("SEED_RANDOM") {
|
|||||||
unsafe {RNG_SEED = str::parse::<u64>(&seed).expect("SEED_RANDOM must be an integer.");}
|
unsafe {RNG_SEED = str::parse::<u64>(&seed).expect("SEED_RANDOM must be an integer.");}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("API functions:");
|
|
||||||
let mut api_ranges = get_all_fn_symbol_ranges(&elf, api_range);
|
|
||||||
println!("APP functions:");
|
|
||||||
let app_fn_ranges = get_all_fn_symbol_ranges(&elf, app_range.clone());
|
|
||||||
|
|
||||||
let mut isr_ranges : HashMap<String,std::ops::Range<GuestAddr>> = systemstate::target_os::freertos::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone())))).collect();
|
let denylist: Vec<_> = TARGET_GROUPS["ISR_FN"].values().map(|x| x.clone()).collect();
|
||||||
systemstate::target_os::freertos::ISR_SYMBOLS.iter().for_each(|x| {let _ =(app_fn_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone()))).map(|y| isr_ranges.insert(y.0,y.1));}); // add used defined isr
|
|
||||||
let denylist : Vec<_> =isr_ranges.values().map(|x| x.clone()).collect();
|
|
||||||
let denylist = FilterList::DenyList(denylist); // do not count isr jumps, which are useless
|
let denylist = FilterList::DenyList(denylist); // do not count isr jumps, which are useless
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
let mut isr_addreses : HashMap<GuestAddr, String> = systemstate::target_os::freertos::ISR_SYMBOLS.iter().filter_map(|x| (api_ranges.remove(&x.to_string()).map(|y| (y.start,x.to_string())))).collect();
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
systemstate::target_os::freertos::ISR_SYMBOLS.iter().for_each(|x| {let _ =(app_fn_ranges.get(&x.to_string()).map(|y| (x.to_string(),y.clone()))).map(|y| isr_addreses.insert(y.1.start, y.0));}); // add used defined isr
|
|
||||||
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
for i in systemstate::target_os::freertos::ISR_SYMBOLS {
|
|
||||||
if isr_ranges.get(&i.to_string()).is_none() {
|
|
||||||
if let Some(fr) = get_function_range(&elf, i) {
|
|
||||||
isr_addreses.insert(fr.start, i.to_string());
|
|
||||||
isr_ranges.insert(i.to_string(), fr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
let api_addreses : HashMap<GuestAddr, String> = api_ranges.iter().map(|(k,v)| (v.start,k.clone())).collect();
|
|
||||||
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
let api_ranges : Vec<_> = api_ranges.into_iter().collect();
|
|
||||||
#[cfg(feature = "observe_systemstate")]
|
|
||||||
let isr_ranges : Vec<_> = isr_ranges.into_iter().collect();
|
|
||||||
|
|
||||||
/// Setup the interrupt inputs. Noop if interrupts are not fuzzed
|
/// Setup the interrupt inputs. Noop if interrupts are not fuzzed
|
||||||
fn setup_interrupt_inputs(mut input : MultipartInput<BytesInput>, interrupt_config : &Vec<(usize,u32)>, mut random: Option<&mut StdRng>) -> MultipartInput<BytesInput> {
|
fn setup_interrupt_inputs(mut input : MultipartInput<BytesInput>, interrupt_config : &Vec<(usize,u32)>, mut random: Option<&mut StdRng>) -> MultipartInput<BytesInput> {
|
||||||
@ -321,7 +250,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
let env: Vec<(String, String)> = env::vars().collect();
|
let env: Vec<(String, String)> = env::vars().collect();
|
||||||
let qemu = Qemu::init(&args).expect("Emulator creation failed");
|
let qemu = Qemu::init(&args).expect("Emulator creation failed");
|
||||||
|
|
||||||
if let Some(main_addr) = main_addr {
|
if let Some(&main_addr) = TARGET_SYMBOLS.get("FUZZ_MAIN") {
|
||||||
qemu.set_breakpoint(main_addr);
|
qemu.set_breakpoint(main_addr);
|
||||||
unsafe {
|
unsafe {
|
||||||
match qemu.run() {
|
match qemu.run() {
|
||||||
@ -332,7 +261,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
qemu.remove_breakpoint(main_addr);
|
qemu.remove_breakpoint(main_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu.set_breakpoint(breakpoint); // BREAKPOINT
|
qemu.set_breakpoint(TARGET_SYMBOLS["BREAKPOINT"]); // BREAKPOINT
|
||||||
|
|
||||||
let devices = qemu.list_devices();
|
let devices = qemu.list_devices();
|
||||||
println!("Devices = {devices:?}");
|
println!("Devices = {devices:?}");
|
||||||
@ -342,6 +271,10 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
#[cfg(not(feature = "snapshot_fast"))]
|
#[cfg(not(feature = "snapshot_fast"))]
|
||||||
let initial_snap = None;
|
let initial_snap = None;
|
||||||
|
|
||||||
|
let harness_input_addr = TARGET_SYMBOLS["FUZZ_INPUT"];
|
||||||
|
let harness_input_length_ptr = TARGET_SYMBOLS.get("FUZZ_LENGTH").copied();
|
||||||
|
let harness_breakpoint = TARGET_SYMBOLS["BREAKPOINT"];
|
||||||
|
|
||||||
// The wrapped harness function, calling out to the LLVM-style harness
|
// The wrapped harness function, calling out to the LLVM-style harness
|
||||||
let mut harness = |emulator: &mut Emulator<_, _, _, _, _>, state: &mut _, input: &MultipartInput<BytesInput>| {
|
let mut harness = |emulator: &mut Emulator<_, _, _, _, _>, state: &mut _, input: &MultipartInput<BytesInput>| {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -367,8 +300,8 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Note: I could not find a difference between write_mem and write_phys_mem for my usecase
|
// Note: I could not find a difference between write_mem and write_phys_mem for my usecase
|
||||||
qemu.write_mem(input_addr, bytes);
|
qemu.write_mem(harness_input_addr, bytes);
|
||||||
if let Some(s) = input_length_ptr {
|
if let Some(s) = harness_input_length_ptr {
|
||||||
qemu.write_mem(s, &len.to_le_bytes());
|
qemu.write_mem(s, &len.to_le_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +312,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
.map(|i| qemu.cpu_from_index(i))
|
.map(|i| qemu.cpu_from_index(i))
|
||||||
.map(|cpu| -> Result<u32, _> { cpu.read_reg(Regs::Pc) });
|
.map(|cpu| -> Result<u32, _> { cpu.read_reg(Regs::Pc) });
|
||||||
match pcs
|
match pcs
|
||||||
.find(|pc| (breakpoint..breakpoint + 5).contains(pc.as_ref().unwrap_or(&0)))
|
.find(|pc| (harness_breakpoint..harness_breakpoint + 5).contains(pc.as_ref().unwrap_or(&0)))
|
||||||
{
|
{
|
||||||
Some(_) => ExitKind::Ok,
|
Some(_) => ExitKind::Ok,
|
||||||
Option::None => ExitKind::Crash,
|
Option::None => ExitKind::Crash,
|
||||||
@ -491,7 +424,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
|
|
||||||
let qhelpers = tuple_list!();
|
let qhelpers = tuple_list!();
|
||||||
#[cfg(feature = "observe_systemstate")]
|
#[cfg(feature = "observe_systemstate")]
|
||||||
let qhelpers = (FreeRTOSSystemStateHelper::new(api_addreses,api_ranges,isr_addreses,isr_ranges,input_addr..(input_addr+unsafe { MAX_INPUT_SIZE } as u32),curr_tcb_pointer,task_queue_addr,task_delay_addr,task_delay_overflow_addr,scheduler_lock,scheduler_running, critical_section,input_counter_ptr,app_range.clone(), job_done_addr), qhelpers);
|
let qhelpers = (FreeRTOSSystemStateHelper::new(&TARGET_SYMBOLS,&TARGET_RANGES,&TARGET_GROUPS), qhelpers);
|
||||||
#[cfg(feature = "observe_edges")]
|
#[cfg(feature = "observe_edges")]
|
||||||
let qhelpers = (QemuEdgeCoverageHelper::new(denylist, QemuFilterList::None), qhelpers);
|
let qhelpers = (QemuEdgeCoverageHelper::new(denylist, QemuFilterList::None), qhelpers);
|
||||||
let qhelpers = (QemuStateRestoreHelper::with_fast(initial_snap), qhelpers);
|
let qhelpers = (QemuStateRestoreHelper::with_fast(initial_snap), qhelpers);
|
||||||
@ -526,7 +459,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
let stages = (systemstate::report::SchedulerStatsStage::default(),());
|
let stages = (systemstate::report::SchedulerStatsStage::default(),());
|
||||||
let stages = (StdMutationalStage::new(mutator), stages);
|
let stages = (StdMutationalStage::new(mutator), stages);
|
||||||
#[cfg(feature = "mutate_stg")]
|
#[cfg(feature = "mutate_stg")]
|
||||||
let mut stages = (STGSnippetStage::<_,_,_,FreeRTOSSystem>::new(input_addr), stages);
|
let mut stages = (STGSnippetStage::<_,_,_,FreeRTOSSystem>::new(TARGET_SYMBOLS["FUZZ_INPUT"]), stages);
|
||||||
#[cfg(feature = "fuzz_int")]
|
#[cfg(feature = "fuzz_int")]
|
||||||
let mut stages = (InterruptShiftStage::<_,_,_,FreeRTOSSystem>::new(&interrupt_config), stages);
|
let mut stages = (InterruptShiftStage::<_,_,_,FreeRTOSSystem>::new(&interrupt_config), stages);
|
||||||
|
|
||||||
@ -662,14 +595,14 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
|||||||
let env: Vec<(String, String)> = env::vars().collect();
|
let env: Vec<(String, String)> = env::vars().collect();
|
||||||
let emu = Qemu::init(&args).expect("Emu creation failed");
|
let emu = Qemu::init(&args).expect("Emu creation failed");
|
||||||
|
|
||||||
if let Some(main_addr) = main_addr {
|
if let Some(&main_addr) = TARGET_SYMBOLS.get("FUZZ_MAIN") {
|
||||||
emu.set_breakpoint(main_addr); // BREAKPOINT
|
emu.set_breakpoint(main_addr); // BREAKPOINT
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
emu.run();
|
emu.run();
|
||||||
|
|
||||||
let mut buf = [0u8].repeat(MAX_INPUT_SIZE);
|
let mut buf = [0u8].repeat(MAX_INPUT_SIZE);
|
||||||
emu.read_mem(input_addr, buf.as_mut_slice());
|
emu.read_mem(TARGET_SYMBOLS["FUZZ_INPUT"], buf.as_mut_slice());
|
||||||
|
|
||||||
let dir = env::var("SEED_DIR").map_or("./corpus".to_string(), |x| x);
|
let dir = env::var("SEED_DIR").map_or("./corpus".to_string(), |x| x);
|
||||||
let filename = if input_dump == "" {"input"} else {&input_dump};
|
let filename = if input_dump == "" {"input"} else {&input_dump};
|
||||||
|
@ -8,3 +8,5 @@ pub mod systemstate;
|
|||||||
mod cli;
|
mod cli;
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub mod templates;
|
pub mod templates;
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
mod config;
|
@ -9,6 +9,8 @@ mod systemstate;
|
|||||||
mod cli;
|
mod cli;
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
mod templates;
|
mod templates;
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
mod config;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
@ -596,6 +596,7 @@ where
|
|||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
Option::None => {
|
Option::None => {
|
||||||
let n=STGFeedbackState::<SYS>::default();
|
let n=STGFeedbackState::<SYS>::default();
|
||||||
|
unsafe{libafl_bolts::prelude::RegistryBuilder::register::<STGFeedbackState<SYS>>()};
|
||||||
state.named_metadata_map_mut().insert("stgfeedbackstate",n);
|
state.named_metadata_map_mut().insert("stgfeedbackstate",n);
|
||||||
state.named_metadata_map_mut().get_mut::<STGFeedbackState<SYS>>("stgfeedbackstate").unwrap()
|
state.named_metadata_map_mut().get_mut::<STGFeedbackState<SYS>>("stgfeedbackstate").unwrap()
|
||||||
}
|
}
|
||||||
|
125
fuzzers/FRET/src/systemstate/target_os/freertos/config.rs
Normal file
125
fuzzers/FRET/src/systemstate/target_os/freertos/config.rs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
use hashbrown::HashMap;
|
||||||
|
use libafl_qemu::{elf::EasyElf, GuestAddr};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
fuzzer::get_all_fn_symbol_ranges,
|
||||||
|
systemstate::{self, helpers::{get_function_range, load_symbol}, target_os::freertos::ISR_SYMBOLS},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn add_target_symbols(elf: &EasyElf, addrs: &mut HashMap<&'static str, GuestAddr>) {
|
||||||
|
// required for system state observation
|
||||||
|
addrs.insert("pxCurrentTCB", load_symbol(&elf, "pxCurrentTCB", false)); // loads to the address specified in elf, without respecting program headers
|
||||||
|
addrs.insert(
|
||||||
|
"pxReadyTasksLists",
|
||||||
|
load_symbol(&elf, "pxReadyTasksLists", false),
|
||||||
|
);
|
||||||
|
addrs.insert(
|
||||||
|
"pxDelayedTaskList",
|
||||||
|
load_symbol(&elf, "pxDelayedTaskList", false),
|
||||||
|
);
|
||||||
|
addrs.insert(
|
||||||
|
"pxOverflowDelayedTaskList",
|
||||||
|
load_symbol(&elf, "pxOverflowDelayedTaskList", false),
|
||||||
|
);
|
||||||
|
addrs.insert(
|
||||||
|
"uxSchedulerSuspended",
|
||||||
|
load_symbol(&elf, "uxSchedulerSuspended", false),
|
||||||
|
);
|
||||||
|
addrs.insert(
|
||||||
|
"xSchedulerRunning",
|
||||||
|
load_symbol(&elf, "xSchedulerRunning", false),
|
||||||
|
);
|
||||||
|
addrs.insert(
|
||||||
|
"uxCriticalNesting",
|
||||||
|
load_symbol(&elf, "uxCriticalNesting", false),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_target_ranges(
|
||||||
|
elf: &EasyElf,
|
||||||
|
symbols: &HashMap<&'static str, GuestAddr>,
|
||||||
|
ranges: &mut HashMap<&'static str, std::ops::Range<GuestAddr>>,
|
||||||
|
) {
|
||||||
|
let api_range = ranges.get("API_CODE").unwrap();
|
||||||
|
let app_range = ranges.get("APP_CODE").unwrap();
|
||||||
|
|
||||||
|
let mut api_fn_ranges = get_all_fn_symbol_ranges(&elf, api_range.clone());
|
||||||
|
let mut app_fn_ranges = get_all_fn_symbol_ranges(&elf, app_range.clone());
|
||||||
|
|
||||||
|
// Regular ISR functions, remove from API functions
|
||||||
|
let mut isr_fn_ranges: HashMap<String, std::ops::Range<GuestAddr>> = ISR_SYMBOLS
|
||||||
|
.iter()
|
||||||
|
.filter_map(|x| {
|
||||||
|
api_fn_ranges
|
||||||
|
.remove(&x.to_string())
|
||||||
|
.map(|y| (x.to_string(), y.clone()))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
// User-defined ISR functions, remove from APP functions
|
||||||
|
ISR_SYMBOLS.iter().for_each(|x| {
|
||||||
|
let _ = (app_fn_ranges
|
||||||
|
.remove(&x.to_string())
|
||||||
|
.map(|y| (x.to_string(), y.clone())))
|
||||||
|
.map(|z| isr_fn_ranges.insert(z.0, z.1));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add the rest of the ISR function, if not already found
|
||||||
|
for i in ISR_SYMBOLS {
|
||||||
|
if isr_fn_ranges.get(&i.to_string()).is_none() {
|
||||||
|
if let Some(fr) = get_function_range(&elf, i) {
|
||||||
|
isr_fn_ranges.insert(i.to_string(), fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut groups = HashMap::new();
|
||||||
|
|
||||||
|
groups.insert("API_FN", api_fn_ranges);
|
||||||
|
groups.insert("APP_FN", app_fn_ranges);
|
||||||
|
groups.insert("ISR_FN", isr_fn_ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_range_groups(
|
||||||
|
elf: &EasyElf,
|
||||||
|
_addrs: &HashMap<&'static str, GuestAddr>,
|
||||||
|
ranges: &HashMap<&'static str, std::ops::Range<GuestAddr>>,
|
||||||
|
) -> HashMap<&'static str, hashbrown::HashMap<String, std::ops::Range<u32>>> {
|
||||||
|
let api_range = ranges.get("API_CODE").unwrap();
|
||||||
|
let app_range = ranges.get("APP_CODE").unwrap();
|
||||||
|
|
||||||
|
let mut api_fn_ranges = get_all_fn_symbol_ranges(&elf, api_range.clone());
|
||||||
|
let mut app_fn_ranges = get_all_fn_symbol_ranges(&elf, app_range.clone());
|
||||||
|
|
||||||
|
// Regular ISR functions, remove from API functions
|
||||||
|
let mut isr_fn_ranges: HashMap<String, std::ops::Range<GuestAddr>> = ISR_SYMBOLS
|
||||||
|
.iter()
|
||||||
|
.filter_map(|x| {
|
||||||
|
api_fn_ranges
|
||||||
|
.remove(&x.to_string())
|
||||||
|
.map(|y| (x.to_string(), y.clone()))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
// User-defined ISR functions, remove from APP functions
|
||||||
|
ISR_SYMBOLS.iter().for_each(|x| {
|
||||||
|
let _ = (app_fn_ranges
|
||||||
|
.remove(&x.to_string())
|
||||||
|
.map(|y| (x.to_string(), y.clone())))
|
||||||
|
.map(|z| isr_fn_ranges.insert(z.0, z.1));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add the rest of the ISR function, if not already found
|
||||||
|
for i in ISR_SYMBOLS {
|
||||||
|
if isr_fn_ranges.get(&i.to_string()).is_none() {
|
||||||
|
if let Some(fr) = get_function_range(&elf, i) {
|
||||||
|
isr_fn_ranges.insert(i.to_string(), fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut groups = HashMap::new();
|
||||||
|
|
||||||
|
groups.insert("API_FN", api_fn_ranges);
|
||||||
|
groups.insert("APP_FN", app_fn_ranges);
|
||||||
|
groups.insert("ISR_FN", isr_fn_ranges);
|
||||||
|
return groups;
|
||||||
|
}
|
@ -9,6 +9,7 @@ use crate::{
|
|||||||
|
|
||||||
pub mod bindings;
|
pub mod bindings;
|
||||||
pub mod qemu_module;
|
pub mod qemu_module;
|
||||||
|
pub mod config;
|
||||||
use bindings::*;
|
use bindings::*;
|
||||||
|
|
||||||
use super::QemuLookup;
|
use super::QemuLookup;
|
||||||
@ -61,18 +62,6 @@ impl SystemState for FreeRTOSSystemState {
|
|||||||
fn current_task_mut(&mut self) -> &mut Self::TCB {
|
fn current_task_mut(&mut self) -> &mut Self::TCB {
|
||||||
&mut self.current_task
|
&mut self.current_task
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn get_edge(&self) -> (GuestAddr, GuestAddr) {
|
|
||||||
// (self.edge.0, self.edge.1)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn get_capture_point(&self) -> (CaptureEvent, String) {
|
|
||||||
// self.capture_point.clone()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn get_mem_reads(&self) -> &Vec<(u32, u8)> {
|
|
||||||
// &self.mem_reads
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================================================================= Data structures
|
//============================================================================= Data structures
|
||||||
@ -210,11 +199,11 @@ fn trigger_collection(
|
|||||||
systemstate.capture_point = (CaptureEvent::APIEnd, s.to_string());
|
systemstate.capture_point = (CaptureEvent::APIEnd, s.to_string());
|
||||||
}
|
}
|
||||||
CaptureEvent::ISRStart => {
|
CaptureEvent::ISRStart => {
|
||||||
let s = h.isr_addrs.get(&edge.1).unwrap();
|
let s = h.isr_fn_addrs.get(&edge.1).unwrap();
|
||||||
systemstate.capture_point = (CaptureEvent::ISRStart, s.to_string());
|
systemstate.capture_point = (CaptureEvent::ISRStart, s.to_string());
|
||||||
}
|
}
|
||||||
CaptureEvent::ISREnd => {
|
CaptureEvent::ISREnd => {
|
||||||
let s = h.isr_addrs.get(&edge.0).unwrap();
|
let s = h.isr_fn_addrs.get(&edge.0).unwrap();
|
||||||
systemstate.capture_point = (CaptureEvent::ISREnd, s.to_string());
|
systemstate.capture_point = (CaptureEvent::ISREnd, s.to_string());
|
||||||
}
|
}
|
||||||
CaptureEvent::End => {
|
CaptureEvent::End => {
|
||||||
@ -230,15 +219,6 @@ fn trigger_collection(
|
|||||||
|
|
||||||
systemstate.qemu_tick = get_icount(emulator);
|
systemstate.qemu_tick = get_icount(emulator);
|
||||||
|
|
||||||
let mut buf: [u8; 4] = [0, 0, 0, 0];
|
|
||||||
match h.input_counter {
|
|
||||||
Some(s) => unsafe {
|
|
||||||
emulator.read_mem(s, &mut buf);
|
|
||||||
},
|
|
||||||
Option::None => (),
|
|
||||||
};
|
|
||||||
systemstate.input_counter = GuestAddr::from_le_bytes(buf);
|
|
||||||
|
|
||||||
let curr_tcb_addr: freertos::void_ptr = QemuLookup::lookup(emulator, h.tcb_addr);
|
let curr_tcb_addr: freertos::void_ptr = QemuLookup::lookup(emulator, h.tcb_addr);
|
||||||
if curr_tcb_addr == 0 {
|
if curr_tcb_addr == 0 {
|
||||||
return;
|
return;
|
||||||
|
@ -13,11 +13,13 @@ use libafl_qemu::{
|
|||||||
EmulatorModules, GuestAddr, Hook, MemAccessInfo,
|
EmulatorModules, GuestAddr, Hook, MemAccessInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::systemstate::{
|
use libafl_bolts::tuples::Map;
|
||||||
|
|
||||||
|
use crate::{fuzzer::MAX_INPUT_SIZE, systemstate::{
|
||||||
helpers::{get_icount, in_any_range, read_rec_return_stackframe},
|
helpers::{get_icount, in_any_range, read_rec_return_stackframe},
|
||||||
target_os::{freertos::FreeRTOSStruct::*, *},
|
target_os::{freertos::FreeRTOSStruct::*, *},
|
||||||
AtomicBasicBlock, CaptureEvent, RTOSJob,
|
AtomicBasicBlock, CaptureEvent, RTOSJob,
|
||||||
};
|
}};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
bindings::{self, *},
|
bindings::{self, *},
|
||||||
@ -30,13 +32,17 @@ use super::{
|
|||||||
/// A Qemu Helper with reads FreeRTOS specific structs from Qemu whenever certain syscalls occur, also inject inputs
|
/// A Qemu Helper with reads FreeRTOS specific structs from Qemu whenever certain syscalls occur, also inject inputs
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FreeRTOSSystemStateHelper {
|
pub struct FreeRTOSSystemStateHelper {
|
||||||
|
// Address of the application code
|
||||||
|
pub app_range: Range<GuestAddr>,
|
||||||
// Address of API functions
|
// Address of API functions
|
||||||
pub api_fn_addrs: HashMap<GuestAddr, String>,
|
pub api_fn_addrs: HashMap<GuestAddr, String>,
|
||||||
pub api_fn_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
|
pub api_fn_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
|
||||||
// Address of interrupt routines
|
// Address of interrupt routines
|
||||||
pub isr_addrs: HashMap<GuestAddr, String>,
|
pub isr_fn_addrs: HashMap<GuestAddr, String>,
|
||||||
pub isr_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
|
pub isr_fn_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
|
||||||
|
// Address of input memory
|
||||||
pub input_mem: Range<GuestAddr>,
|
pub input_mem: Range<GuestAddr>,
|
||||||
|
// FreeRTOS specific addresses
|
||||||
pub tcb_addr: GuestAddr,
|
pub tcb_addr: GuestAddr,
|
||||||
pub ready_queues: GuestAddr,
|
pub ready_queues: GuestAddr,
|
||||||
pub delay_queue: GuestAddr,
|
pub delay_queue: GuestAddr,
|
||||||
@ -44,45 +50,48 @@ pub struct FreeRTOSSystemStateHelper {
|
|||||||
pub scheduler_lock_addr: GuestAddr,
|
pub scheduler_lock_addr: GuestAddr,
|
||||||
pub scheduler_running_addr: GuestAddr,
|
pub scheduler_running_addr: GuestAddr,
|
||||||
pub critical_addr: GuestAddr,
|
pub critical_addr: GuestAddr,
|
||||||
pub input_counter: Option<GuestAddr>,
|
|
||||||
pub app_range: Range<GuestAddr>,
|
|
||||||
pub job_done_addrs: GuestAddr,
|
pub job_done_addrs: GuestAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FreeRTOSSystemStateHelper {
|
impl FreeRTOSSystemStateHelper {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
api_fn_addrs: HashMap<GuestAddr, String>,
|
target_symbols: &HashMap<&'static str, GuestAddr>,
|
||||||
api_fn_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
|
target_ranges: &HashMap<&'static str, Range<GuestAddr>>,
|
||||||
isr_addrs: HashMap<GuestAddr, String>,
|
target_groups: &HashMap<&'static str, HashMap<String, Range<GuestAddr>>>,
|
||||||
isr_ranges: Vec<(String, std::ops::Range<GuestAddr>)>,
|
|
||||||
input_mem: Range<GuestAddr>,
|
|
||||||
tcb_addr: GuestAddr,
|
|
||||||
ready_queues: GuestAddr,
|
|
||||||
delay_queue: GuestAddr,
|
|
||||||
delay_queue_overflow: GuestAddr,
|
|
||||||
scheduler_lock_addr: GuestAddr,
|
|
||||||
scheduler_running_addr: GuestAddr,
|
|
||||||
critical_addr: GuestAddr,
|
|
||||||
input_counter: Option<GuestAddr>,
|
|
||||||
app_range: Range<GuestAddr>,
|
|
||||||
job_done_addrs: GuestAddr,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let app_range = target_ranges.get("APP_CODE").unwrap().clone();
|
||||||
|
|
||||||
|
let api_fn_ranges : Vec<_> = target_groups.get("API_FN").unwrap().iter().sorted_by_key(|x|x.1.start).map(|(n,r)| (n.clone(),r.clone())).collect();
|
||||||
|
let api_fn_addrs = api_fn_ranges.iter().map(|(n,r)| (r.start,n.clone())).collect();
|
||||||
|
let isr_fn_ranges : Vec<_> = target_groups.get("ISR_FN").unwrap().iter().sorted_by_key(|x|x.1.start).map(|(n,r)| (n.clone(),r.clone())).collect();
|
||||||
|
let isr_fn_addrs = isr_fn_ranges.iter().map(|(n,r)| (r.start,n.clone())).collect();
|
||||||
|
|
||||||
|
let input_mem = target_symbols.get("FUZZ_INPUT").map(|x| *x..(*x+unsafe{MAX_INPUT_SIZE as GuestAddr})).unwrap();
|
||||||
|
|
||||||
|
let tcb_addr = *target_symbols.get("pxCurrentTCB").unwrap();
|
||||||
|
let ready_queues = *target_symbols.get("pxReadyTasksLists").unwrap();
|
||||||
|
let delay_queue = *target_symbols.get("pxDelayedTaskList").unwrap();
|
||||||
|
let delay_queue_overflow = *target_symbols.get("pxOverflowDelayedTaskList").unwrap();
|
||||||
|
let scheduler_lock_addr = *target_symbols.get("uxSchedulerSuspended").unwrap();
|
||||||
|
let scheduler_running_addr = *target_symbols.get("xSchedulerRunning").unwrap();
|
||||||
|
let critical_addr = *target_symbols.get("uxCriticalNesting").unwrap();
|
||||||
|
let job_done_addrs = *target_symbols.get("trigger_job_done").unwrap();
|
||||||
|
|
||||||
FreeRTOSSystemStateHelper {
|
FreeRTOSSystemStateHelper {
|
||||||
|
app_range,
|
||||||
api_fn_addrs,
|
api_fn_addrs,
|
||||||
api_fn_ranges,
|
api_fn_ranges,
|
||||||
isr_addrs,
|
isr_fn_addrs,
|
||||||
isr_ranges,
|
isr_fn_ranges,
|
||||||
input_mem,
|
input_mem,
|
||||||
tcb_addr: tcb_addr,
|
tcb_addr,
|
||||||
ready_queues: ready_queues,
|
ready_queues,
|
||||||
delay_queue,
|
delay_queue,
|
||||||
delay_queue_overflow,
|
delay_queue_overflow,
|
||||||
scheduler_lock_addr,
|
scheduler_lock_addr,
|
||||||
scheduler_running_addr,
|
scheduler_running_addr,
|
||||||
critical_addr,
|
critical_addr,
|
||||||
input_counter: input_counter,
|
|
||||||
app_range,
|
|
||||||
job_done_addrs,
|
job_done_addrs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,7 +105,7 @@ where
|
|||||||
where
|
where
|
||||||
ET: EmulatorModuleTuple<S>,
|
ET: EmulatorModuleTuple<S>,
|
||||||
{
|
{
|
||||||
for wp in self.isr_addrs.keys() {
|
for wp in self.isr_fn_addrs.keys() {
|
||||||
emulator_modules.instructions(*wp, Hook::Function(exec_isr_hook::<ET, S>), false);
|
emulator_modules.instructions(*wp, Hook::Function(exec_isr_hook::<ET, S>), false);
|
||||||
}
|
}
|
||||||
emulator_modules.jmps(
|
emulator_modules.jmps(
|
||||||
@ -338,7 +347,7 @@ where
|
|||||||
{
|
{
|
||||||
if h.app_range.contains(&src)
|
if h.app_range.contains(&src)
|
||||||
&& !h.app_range.contains(&dest)
|
&& !h.app_range.contains(&dest)
|
||||||
&& in_any_range(&h.isr_ranges, src).is_none()
|
&& in_any_range(&h.isr_fn_ranges, src).is_none()
|
||||||
{
|
{
|
||||||
if let Some(_) = in_any_range(&h.api_fn_ranges, dest) {
|
if let Some(_) = in_any_range(&h.api_fn_ranges, dest) {
|
||||||
// println!("New jmp {:x} {:x}", src, dest);
|
// println!("New jmp {:x} {:x}", src, dest);
|
||||||
@ -353,7 +362,7 @@ where
|
|||||||
// println!("API Return Edge {:#x}", src);
|
// println!("API Return Edge {:#x}", src);
|
||||||
return Some(2);
|
return Some(2);
|
||||||
}
|
}
|
||||||
if let Some(_) = in_any_range(&h.isr_ranges, src) {
|
if let Some(_) = in_any_range(&h.isr_fn_ranges, src) {
|
||||||
// println!("ISR Return Edge {:#x}", src);
|
// println!("ISR Return Edge {:#x}", src);
|
||||||
return Some(3);
|
return Some(3);
|
||||||
}
|
}
|
||||||
@ -385,7 +394,7 @@ pub fn trace_jmp<QT, S>(
|
|||||||
// API return
|
// API return
|
||||||
// Ignore returns to other APIs or ISRs. We only account for the first call depth of API calls from user space.
|
// Ignore returns to other APIs or ISRs. We only account for the first call depth of API calls from user space.
|
||||||
if in_any_range(&h.api_fn_ranges, dest).is_none()
|
if in_any_range(&h.api_fn_ranges, dest).is_none()
|
||||||
&& in_any_range(&h.isr_ranges, dest).is_none()
|
&& in_any_range(&h.isr_fn_ranges, dest).is_none()
|
||||||
{
|
{
|
||||||
let mut edge = (0, 0);
|
let mut edge = (0, 0);
|
||||||
edge.0 = in_any_range(&h.api_fn_ranges, src).unwrap().start;
|
edge.0 = in_any_range(&h.api_fn_ranges, src).unwrap().start;
|
||||||
@ -399,7 +408,7 @@ pub fn trace_jmp<QT, S>(
|
|||||||
dest = read_rec_return_stackframe(&emulator, dest);
|
dest = read_rec_return_stackframe(&emulator, dest);
|
||||||
|
|
||||||
let mut edge = (0, 0);
|
let mut edge = (0, 0);
|
||||||
edge.0 = in_any_range(&h.isr_ranges, src).unwrap().start;
|
edge.0 = in_any_range(&h.isr_fn_ranges, src).unwrap().start;
|
||||||
edge.1 = dest;
|
edge.1 = dest;
|
||||||
|
|
||||||
trigger_collection(&emulator, edge, CaptureEvent::ISREnd, h);
|
trigger_collection(&emulator, edge, CaptureEvent::ISREnd, h);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user