add snapshot path, debug prints

This commit is contained in:
Alwin Berger 2022-02-09 22:17:27 +01:00
parent 9369eae37b
commit 99bd30c233
8 changed files with 51 additions and 41 deletions

View File

@ -3,3 +3,4 @@
demo demo
*.ron *.ron
*.bsp *.bsp
tmp*

View File

@ -7,7 +7,6 @@ edition = "2021"
[features] [features]
default = ["std"] default = ["std"]
std = [] std = []
showmap = []
[profile.release] [profile.release]
debug = true debug = true

View File

@ -0,0 +1,4 @@
mkdir -p tmp/test_in tmp/test_out
[ ! -f tmp/test_in/test ] && echo " !test" > tmp/test_in/test
[ ! -f tmp/dummy.qcow2 ] && qemu-img create -f qcow2 tmp/dummy.qcow2 32M
LD_LIBRARY_PATH=target/debug target/debug/fuzzer --libafl-snapshot tmp/dummy.qcow2 --libafl-out tmp/test_out --libafl-in tmp/test_in --libafl-kernel $@

View File

@ -0,0 +1,4 @@
mkdir -p tmp/test_in tmp/test_out
[ ! -f tmp/test_in/test ] && echo " !test" > tmp/test_in/test
[ ! -f tmp/dummy.qcow2 ] && qemu-img create -f qcow2 tmp/dummy.qcow2 32M
LD_LIBRARY_PATH=target/debug target/debug/showmap --libafl-snapshot tmp/dummy.qcow2 --libafl-out tmp/test_out --libafl-in tmp/test_in --libafl-kernel $@

View File

@ -1,11 +1,6 @@
//! A singlethreaded QEMU fuzzer that can auto-restart. //! A singlethreaded QEMU fuzzer that can auto-restart.
use libafl::mutators::ByteFlipMutator;
use libafl::mutators::BitFlipMutator;
use wcet_qemu_sys::worst::LenTimeMaximizerCorpusScheduler;
use libafl::corpus::MinimizerCorpusScheduler;
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl::events::SimpleEventManager;
use clap::{App, Arg}; use clap::{App, Arg};
use core::{cell::RefCell, time::Duration}; use core::{cell::RefCell, time::Duration};
#[cfg(unix)] #[cfg(unix)]
@ -28,7 +23,7 @@ use libafl::{
tuples::{tuple_list, Merge}, tuples::{tuple_list, Merge},
}, },
corpus::{ corpus::{
Corpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, PowerQueueCorpusScheduler, Corpus, OnDiskCorpus, PowerQueueCorpusScheduler,
}, },
executors::{ExitKind, ShadowExecutor, TimeoutExecutor}, executors::{ExitKind, ShadowExecutor, TimeoutExecutor},
feedback_or, feedback_or,
@ -40,13 +35,14 @@ use libafl::{
scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations,
StdMOptMutator, StdScheduledMutator, Tokens, StdMOptMutator, StdScheduledMutator, Tokens,
}, },
observers::{TimeObserver, VariableMapObserver}, observers::{VariableMapObserver},
stages::{ stages::{
calibrate::CalibrationStage, calibrate::CalibrationStage,
power::{PowerMutationalStage, PowerSchedule}, power::{PowerMutationalStage, PowerSchedule},
ShadowTracingStage, StdMutationalStage, ShadowTracingStage, StdMutationalStage,
}, },
state::{HasCorpus, HasMetadata, StdState}, state::{HasCorpus, HasMetadata, StdState},
events::SimpleEventManager,
Error, Error,
}; };
use libafl_qemu::{ use libafl_qemu::{
@ -65,7 +61,7 @@ use libafl_qemu::{
clock::ClockFeedback, clock::ClockFeedback,
clock::QemuClockIncreaseFeedback clock::QemuClockIncreaseFeedback
}; };
use wcet_qemu_sys::worst::{HitFeedback,HitcountsMapObserver,HitImprovingFeedback}; use wcet_qemu_sys::worst::{HitFeedback,HitcountsMapObserver,HitImprovingFeedback,LenTimeMaximizerCorpusScheduler};
/// The fuzzer main /// The fuzzer main
@ -121,6 +117,13 @@ pub fn main() {
.long("libafl-edges") .long("libafl-edges")
.takes_value(true), .takes_value(true),
) )
.arg(
Arg::new("snapshot")
.help("The qcow2 file used for snapshots")
.long("libafl-snapshot")
.required(true)
.takes_value(true),
)
.try_get_matches_from(filter_qemu_args()) .try_get_matches_from(filter_qemu_args())
{ {
Ok(res) => res, Ok(res) => res,
@ -178,7 +181,9 @@ pub fn main() {
None => None None => None
}; };
fuzz(out_dir, crashes, in_dir, tokens, logfile, timeout, kernel, edges) let snapshot = PathBuf::from(res.value_of("snapshot").unwrap().to_string());
fuzz(out_dir, crashes, in_dir, tokens, logfile, timeout, kernel, edges, snapshot)
.expect("An error occurred while fuzzing"); .expect("An error occurred while fuzzing");
} }
@ -205,6 +210,7 @@ fn fuzz(
timeout: Duration, timeout: Duration,
kernel: PathBuf, kernel: PathBuf,
dump_edges: Option<PathBuf>, dump_edges: Option<PathBuf>,
snapshot: PathBuf,
) -> Result<(), Error> { ) -> Result<(), Error> {
env::remove_var("LD_LIBRARY_PATH"); env::remove_var("LD_LIBRARY_PATH");
@ -217,7 +223,7 @@ fn fuzz(
"--semihosting-config", "enable=on,target=native", "--semihosting-config", "enable=on,target=native",
"-kernel", kernel.to_str().unwrap(), "-kernel", kernel.to_str().unwrap(),
"-serial", "stdio", "-nographic", "-serial", "stdio", "-nographic",
"-snapshot", "-drive", "if=none,format=qcow2,file=dummy.qcow2", "-snapshot", "-drive", format!("if=none,format=qcow2,file={}",snapshot.to_string_lossy()).as_str(),
"-icount", "shift=auto,align=off,sleep=off", "-icount", "shift=auto,align=off,sleep=off",
"-S" "-S"
].iter().map(|x| x.to_string()).collect(); ].iter().map(|x| x.to_string()).collect();
@ -373,10 +379,8 @@ fn fuzz(
unsafe { unsafe {
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);
// println!("{:#?}",edges_copy);
emu.run(); emu.run();
// println!("{:#?}",edges_copy);
} }
ExitKind::Ok ExitKind::Ok

View File

@ -1,16 +1,9 @@
//! A singlethreaded QEMU fuzzer that can auto-restart. //! A singlethreaded QEMU fuzzer that can auto-restart.
use wcet_qemu_sys::worst::DumpMapFeedback; use wcet_qemu_sys::{
use wcet_qemu_sys::worst::DummyFeedback; worst::{DumpMapFeedback,DummyFeedback,HitcountsMapObserver},
use libafl_qemu::QemuInstrumentationFilter; system_trace::QemuSystemStateHelper,
use wcet_qemu_sys::system_trace::QemuSystemStateHelper; };
use libafl_qemu::QemuExecutor;
use libafl::Evaluator;
use libafl::inputs::Input;
use libafl::corpus::InMemoryCorpus;
use libafl::events::SimpleEventManager;
use libafl::stats::SimpleStats;
use wcet_qemu_sys::worst::HitcountsMapObserver;
use clap::{App, Arg}; use clap::{App, Arg};
use std::{ use std::{
env, env,
@ -24,21 +17,26 @@ use libafl::{
rands::StdRand, rands::StdRand,
tuples::{tuple_list}, tuples::{tuple_list},
}, },
corpus::{QueueCorpusScheduler}, corpus::{InMemoryCorpus,QueueCorpusScheduler},
executors::{ExitKind}, executors::{ExitKind},
fuzzer::{StdFuzzer}, fuzzer::{StdFuzzer},
inputs::{BytesInput, HasTargetBytes}, inputs::{Input,BytesInput, HasTargetBytes},
observers::{VariableMapObserver}, observers::{VariableMapObserver},
state::{StdState}, state::{StdState},
Error, Error,
Evaluator,
stats::SimpleStats,
events::SimpleEventManager,
}; };
use libafl_qemu::{ use libafl_qemu::{
edges, edges,
edges::QemuEdgeCoverageHelper, edges::QemuEdgeCoverageHelper,
emu::Emulator, filter_qemu_args, emu::Emulator, filter_qemu_args,
snapshot_sys::QemuSysSnapshotHelper,
elf::EasyElf, elf::EasyElf,
snapshot_sys::QemuSysSnapshotHelper,
clock::{QemuClockObserver}, clock::{QemuClockObserver},
QemuInstrumentationFilter,
QemuExecutor,
}; };
@ -90,6 +88,13 @@ pub fn main() {
.long("libafl-edges") .long("libafl-edges")
.takes_value(true), .takes_value(true),
) )
.arg(
Arg::new("snapshot")
.help("The qcow2 file used for snapshots")
.long("libafl-snapshot")
.required(true)
.takes_value(true),
)
.try_get_matches_from(filter_qemu_args()) .try_get_matches_from(filter_qemu_args())
{ {
Ok(res) => res, Ok(res) => res,
@ -135,8 +140,9 @@ pub fn main() {
None => None None => None
}; };
let snapshot = PathBuf::from(res.value_of("snapshot").unwrap().to_string());
fuzz(in_dir, kernel, edges) fuzz(in_dir, kernel, edges, snapshot)
.expect("An error occurred while fuzzing"); .expect("An error occurred while fuzzing");
} }
@ -158,6 +164,7 @@ fn fuzz(
seed_dir: PathBuf, seed_dir: PathBuf,
kernel: PathBuf, kernel: PathBuf,
dump_edges: Option<PathBuf>, dump_edges: Option<PathBuf>,
snapshot: PathBuf,
) -> Result<(), Error> { ) -> Result<(), Error> {
//=========== Setup emulator //=========== Setup emulator
let mut env: Vec<(String, String)> = env::vars().collect(); let mut env: Vec<(String, String)> = env::vars().collect();
@ -169,7 +176,7 @@ fn fuzz(
"--semihosting-config", "enable=on,target=native", "--semihosting-config", "enable=on,target=native",
"-kernel", kernel.to_str().unwrap(), "-kernel", kernel.to_str().unwrap(),
"-serial", "stdio", "-nographic", "-serial", "stdio", "-nographic",
"-snapshot", "-drive", "if=none,format=qcow2,file=dummy.qcow2", "-snapshot", "-drive", format!("if=none,format=qcow2,file={}",snapshot.to_string_lossy()).as_str(),
"-icount", "shift=auto,align=off,sleep=off", "-icount", "shift=auto,align=off,sleep=off",
"-S" "-S"
].iter().map(|x| x.to_string()).collect(); ].iter().map(|x| x.to_string()).collect();

View File

@ -175,8 +175,6 @@ where
EM: EventFirer<I>, EM: EventFirer<I>,
OT: ObserversTuple<I, S>, OT: ObserversTuple<I, S>,
{ {
// TODO Replace with match_name_type when stable
// let observer = _observers.match_name::<HitcountsMapObserver<O>>("edges").expect("SelectedEdgeObserver not found");
let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges") let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges")
.expect("HitcountsMapObserver not found"); .expect("HitcountsMapObserver not found");
if self.target_map.len() == 0 { return Ok(true) }; if self.target_map.len() == 0 { return Ok(true) };
@ -190,8 +188,8 @@ where
} }
let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64); let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64);
let hit_target = mean_sum_of_squares <= self.target_msd; let hit_target = mean_sum_of_squares <= self.target_msd;
// eprintln!("hit target: {} {} {:?}",hit_target,mean_sum_of_squares, _input);
if hit_target { if hit_target {
#[cfg(debug_assertions)] eprintln!("Hit Feedback trigger");
Ok(true) Ok(true)
} else { } else {
Ok(false) Ok(false)
@ -305,8 +303,6 @@ where
EM: EventFirer<I>, EM: EventFirer<I>,
OT: ObserversTuple<I, S>, OT: ObserversTuple<I, S>,
{ {
// TODO Replace with match_name_type when stable
// let observer = _observers.match_name::<HitcountsMapObserver<O>>("edges").expect("SelectedEdgeObserver not found");
let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges") let observer = _observers.match_name::<HitcountsMapObserver<VariableMapObserver<u8>>>("edges")
.expect("HitcountsMapObserver not found"); .expect("HitcountsMapObserver not found");
if self.target_map.len() == 0 { return Ok(true) }; if self.target_map.len() == 0 { return Ok(true) };
@ -320,9 +316,8 @@ where
} }
let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64); let mean_sum_of_squares = (sum_of_square_difference as f64) / (self.target_map.len() as f64);
let hit_target = mean_sum_of_squares < self.best_msd; let hit_target = mean_sum_of_squares < self.best_msd;
// eprintln!("improving: {}",hit_target);
if hit_target { if hit_target {
// println!("Hit Improving: {}",mean_sum_of_squares); #[cfg(debug_assertions)] eprintln!("Hit Improving: {}",mean_sum_of_squares);
self.best_msd = mean_sum_of_squares; self.best_msd = mean_sum_of_squares;
Ok(true) Ok(true)
} else { } else {
@ -383,7 +378,7 @@ where
fs::write(s,ron::to_string(&observer.edgemap).expect("Error serializing hashmap")).expect("Can not dump to file"); fs::write(s,ron::to_string(&observer.edgemap).expect("Error serializing hashmap")).expect("Can not dump to file");
self.dumpfile = None self.dumpfile = None
}, },
None => ()//println!("{:#?}",observer.edgemap), None => println!("{:?}",observer.edgemap),
}; };
Ok(true) Ok(true)
} }
@ -507,7 +502,6 @@ where
I: Input + HasLen, I: Input + HasLen,
{ {
fn compute(entry: &mut Testcase<I>) -> Result<u64, Error> { fn compute(entry: &mut Testcase<I>) -> Result<u64, Error> {
// TODO maybe enforce entry.exec_time().is_some()
let execs_per_hour = (3600.0/entry.exec_time().expect("testcase.exec_time is needed for scheduler").as_secs_f64()) as u64; let execs_per_hour = (3600.0/entry.exec_time().expect("testcase.exec_time is needed for scheduler").as_secs_f64()) as u64;
let execs_times_length_per_hour = execs_per_hour*entry.cached_len()? as u64; let execs_times_length_per_hour = execs_per_hour*entry.cached_len()? as u64;
Ok(execs_times_length_per_hour) Ok(execs_times_length_per_hour)

View File

@ -1,3 +0,0 @@
mkdir -p target/test_in target/test_out
[ ! -f target/test_in/test ] && echo " !test" > target/test_in/test
LD_LIBRARY_PATH=target/debug target/debug/wcet_qemu_sys --libafl-out target/test_out --libafl-in target/test_in --libafl-kernel $@