fix interrupt input, graph output

This commit is contained in:
Alwin Berger 2022-05-01 22:07:37 +02:00
parent 0b638d9020
commit 01e40ded1d
4 changed files with 56 additions and 31 deletions

View File

@ -1,5 +1,8 @@
//! A singlethreaded QEMU fuzzer that can auto-restart. //! A singlethreaded QEMU fuzzer that can auto-restart.
use libafl::bolts::tuples::MatchName;
use libafl::state::HasFeedbackStates;
use wcet_qemu_sys::sysstate::graph::SysGraphMetadata;
use wcet_qemu_sys::sysstate::helpers::INTR_OFFSET; use wcet_qemu_sys::sysstate::helpers::INTR_OFFSET;
use wcet_qemu_sys::sysstate::graph::RandGraphSnippetMutator; use wcet_qemu_sys::sysstate::graph::RandGraphSnippetMutator;
use wcet_qemu_sys::sysstate::graph::GraphMaximizerCorpusScheduler; use wcet_qemu_sys::sysstate::graph::GraphMaximizerCorpusScheduler;
@ -29,6 +32,8 @@ use std::{
path::PathBuf, path::PathBuf,
process, process,
}; };
use petgraph::prelude::DiGraph;
use petgraph::dot::{Dot, Config};
use libafl::{ use libafl::{
bolts::{ bolts::{
@ -292,7 +297,7 @@ fn fuzz(
"-kernel", kernel.to_str().unwrap(), "-kernel", kernel.to_str().unwrap(),
"-serial", "stdio", "-nographic", "-serial", "stdio", "-nographic",
"-snapshot", "-drive", format!("if=none,format=qcow2,file={}",snapshot.to_string_lossy()).as_str(), "-snapshot", "-drive", format!("if=none,format=qcow2,file={}",snapshot.to_string_lossy()).as_str(),
"-icount", "shift=auto,align=off,sleep=off", "-icount", "shift=3,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();
@ -416,11 +421,12 @@ fn fuzz(
let mut buf = target.as_slice(); let mut buf = target.as_slice();
let mut len = buf.len(); let mut len = buf.len();
let mut int_tick : Option<u32> = None; let mut int_tick : Option<u32> = None;
if len > 4 { if len > 2 {
let mut t : [u8; 4] = [0,0,0,0]; // 4 extra bytes determine the tick to execute an interrupt let mut t : [u8; 4] = [0,0,0,0]; // 4 extra bytes determine the tick to execute an interrupt
t.copy_from_slice(&buf[0..4]); t[0]=buf[0];
t[1]=buf[1];
int_tick = Some(u32::from_le_bytes(t)); int_tick = Some(u32::from_le_bytes(t));
buf = &buf[4..]; buf = &buf[2..];
len = buf.len(); len = buf.len();
} }
if len >= 32 { if len >= 32 {
@ -429,7 +435,7 @@ fn fuzz(
} }
unsafe { unsafe {
libafl_int_offset = int_tick.unwrap_or(0); libafl_int_offset = 347780+int_tick.unwrap_or(0);
// INTR_OFFSET = int_tick; // INTR_OFFSET = int_tick;
emu.write_mem(test_length_ptr,&(len as u32).to_le_bytes()); emu.write_mem(test_length_ptr,&(len as u32).to_le_bytes());
emu.write_mem(input_addr,buf); emu.write_mem(input_addr,buf);
@ -506,9 +512,27 @@ fn fuzz(
dup2(null_fd, io::stderr().as_raw_fd())?; dup2(null_fd, io::stderr().as_raw_fd())?;
} }
// fuzzer
// .fuzz_for_solution(&mut stages, &mut executor, &mut state, &mut mgr)
// .expect("Error in the fuzzing loop");
fuzzer fuzzer
.fuzz_for_solution(&mut stages, &mut executor, &mut state, &mut mgr) .fuzz_loop_for(&mut stages, &mut executor, &mut state, &mut mgr, 20)
.expect("Error in the fuzzing loop"); .expect("Error in the fuzzing loop");
let feedbackstate = state
.feedback_states()
.match_name::<SysGraphFeedbackState>("SysMap")
.unwrap();
let newgraph = feedbackstate.graph.map(
|_, n| n.get_taskname(),
|_, e| e,
);
// println!("{:?}",feedbackstate.graph);
// println!("{:?}",Dot::with_config(&feedbackstate.graph, &[Config::EdgeNoLabel]));
let tempg = format!("{:?}",Dot::with_config(&newgraph, &[Config::EdgeNoLabel]));
fs::write("./graph.dot",tempg).expect("Graph can not be written");
// Never reached // Never reached
Ok(()) Ok(())

View File

@ -216,7 +216,7 @@ fn fuzz(
"-kernel", kernel.to_str().unwrap(), "-kernel", kernel.to_str().unwrap(),
"-serial", "stdio", "-nographic", "-serial", "stdio", "-nographic",
"-snapshot", "-drive", format!("if=none,format=qcow2,file={}",snapshot.to_string_lossy()).as_str(), "-snapshot", "-drive", format!("if=none,format=qcow2,file={}",snapshot.to_string_lossy()).as_str(),
"-icount", "shift=auto,align=off,sleep=off", "-icount", "shift=3,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);
@ -339,11 +339,12 @@ fn fuzz(
let mut buf = target.as_slice(); let mut buf = target.as_slice();
let mut len = buf.len(); let mut len = buf.len();
let mut int_tick : Option<u32> = None; let mut int_tick : Option<u32> = None;
if len > 4 { if len > 2 {
let mut t : [u8; 4] = [0,0,0,0]; // 4 extra bytes determine the tick to execute an interrupt let mut t : [u8; 4] = [0,0,0,0]; // 4 extra bytes determine the tick to execute an interrupt
t.copy_from_slice(&buf[0..4]); t[0]=buf[0];
t[1]=buf[1];
int_tick = Some(u32::from_le_bytes(t)); int_tick = Some(u32::from_le_bytes(t));
buf = &buf[4..]; buf = &buf[2..];
len = buf.len(); len = buf.len();
} }
if len >= 32 { if len >= 32 {
@ -352,7 +353,7 @@ fn fuzz(
} }
unsafe { unsafe {
libafl_int_offset = int_tick.unwrap_or(0); libafl_int_offset = 347780+int_tick.unwrap_or(0);
// INTR_OFFSET = int_tick; // INTR_OFFSET = int_tick;
emu.write_mem(test_length_ptr,&(len as u32).to_le_bytes()); emu.write_mem(test_length_ptr,&(len as u32).to_le_bytes());
emu.write_mem(input_addr,buf); emu.write_mem(input_addr,buf);

View File

@ -64,7 +64,7 @@ impl VariantTuple {
} }
#[derive(Serialize, Deserialize, Clone, Debug, Default)] #[derive(Serialize, Deserialize, Clone, Debug, Default)]
struct SysGraphNode pub struct SysGraphNode
{ {
base: RefinedFreeRTOSSystemState, base: RefinedFreeRTOSSystemState,
variants: Vec<VariantTuple>, variants: Vec<VariantTuple>,
@ -101,6 +101,9 @@ impl SysGraphNode {
} }
return interesting; return interesting;
} }
pub fn get_taskname(&self) -> &str {
&self.base.current_task.task_name
}
} }
impl PartialEq for SysGraphNode { impl PartialEq for SysGraphNode {
fn eq(&self, other: &SysGraphNode) -> bool { fn eq(&self, other: &SysGraphNode) -> bool {
@ -148,16 +151,22 @@ pub type GraphMaximizerCorpusScheduler<CS, I, S> =
#[derive(Serialize, Deserialize, Clone, Debug, Default)] #[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct SysGraphFeedbackState pub struct SysGraphFeedbackState
{ {
graph: DiGraph<SysGraphNode, ()>, pub graph: DiGraph<SysGraphNode, ()>,
entrypoint: NodeIndex, entrypoint: NodeIndex,
exit: NodeIndex,
name: String, name: String,
} }
impl SysGraphFeedbackState impl SysGraphFeedbackState
{ {
pub fn new() -> Self { pub fn new() -> Self {
let mut graph = DiGraph::<SysGraphNode, ()>::new(); let mut graph = DiGraph::<SysGraphNode, ()>::new();
let ind = graph.add_node(SysGraphNode::default()); let mut entry = SysGraphNode::default();
Self {graph: graph, entrypoint: ind, name: String::from("SysMap")} entry.base.current_task.task_name="Start".to_string();
let mut exit = SysGraphNode::default();
exit.base.current_task.task_name="End".to_string();
let entry = graph.add_node(entry);
let exit = graph.add_node(exit);
Self {graph: graph, entrypoint: entry, exit: exit, name: String::from("SysMap")}
} }
fn insert(&mut self, list: Vec<RefinedFreeRTOSSystemState>, input: &Vec<u8>) { fn insert(&mut self, list: Vec<RefinedFreeRTOSSystemState>, input: &Vec<u8>) {
let mut current_index = self.entrypoint; let mut current_index = self.entrypoint;
@ -205,6 +214,7 @@ impl SysGraphFeedbackState
} }
trace.push(current_index); trace.push(current_index);
} }
self.graph.update_edge(current_index, self.exit, ()); // every path ends in the exit noded
return (novel, trace); return (novel, trace);
} }
} }
@ -219,7 +229,12 @@ impl FeedbackState for SysGraphFeedbackState
{ {
fn reset(&mut self) -> Result<(), Error> { fn reset(&mut self) -> Result<(), Error> {
self.graph.clear(); self.graph.clear();
self.entrypoint = self.graph.add_node(SysGraphNode::default()); let mut entry = SysGraphNode::default();
entry.base.current_task.task_name="Start".to_string();
let mut exit = SysGraphNode::default();
exit.base.current_task.task_name="End".to_string();
self.entrypoint = self.graph.add_node(entry);
self.exit = self.graph.add_node(exit);
Ok(()) Ok(())
} }
} }

View File

@ -90,21 +90,6 @@ where
I: Input, I: Input,
QT: QemuHelperTuple<I, S>, QT: QemuHelperTuple<I, S>,
{ {
unsafe {
match INTR_OFFSET {
None => (),
Some(off) => {
if emulator.get_ticks() > off {
if !INTR_DONE {
libafl_qemu::emu::libafl_send_irq(0);
INTR_DONE = true;
}
} else {
INTR_DONE = false;
}
},
}
}
let h = helpers.match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel"); let h = helpers.match_first_type::<QemuSystemStateHelper>().expect("QemuSystemHelper not found in helper tupel");
if !h.must_instrument(pc) { if !h.must_instrument(pc) {
return; return;