This commit is contained in:
Alwin Berger 2023-12-08 16:07:56 +01:00
parent 6e0b49bf9b
commit 90cae14958
3 changed files with 113 additions and 21 deletions

View File

@ -40,3 +40,5 @@ hashbrown = { version = "0.14.0", features = ["serde"] } # A faster hashmap, no
petgraph = { version="0.6.0", features = ["serde-1"] }
ron = "0.7" # write serialized data - including hashmaps
rand = "0.5"
clap = { version = "4.4.11", features = ["derive"] }
csv = "1.3.0"

View File

@ -2,7 +2,7 @@ import csv
import os
def_flags="--no-default-features --features std,snapshot_restore,singlecore,restarting,run_until_saturation"
remote="timedump_253048_1873f6_all/"
RUNTIME=10
RUNTIME=120
TARGET_REPS_A=2
TARGET_REPS_B=2
NUM_NODES=2
@ -157,19 +157,21 @@ rule run_bench:
bkp=line['return_function']
script="""
mkdir -p $(dirname {output[0]})
export KERNEL=$(pwd)/{input[0]}
export FUZZ_MAIN={fuzz_main}
export FUZZ_INPUT={fuzz_input}
export FUZZ_INPUT_LEN={fuzz_len}
export BREAKPOINT={bkp}
export SEED_RANDOM={wildcards.num}
# export KERNEL=$(pwd)/{input[0]}
# export FUZZ_MAIN={fuzz_main}
# export FUZZ_INPUT={fuzz_input}
# export FUZZ_INPUT_LEN={fuzz_len}
# export BREAKPOINT={bkp}
# export SEED_RANDOM={wildcards.num}
export TIME_DUMP=$(pwd)/{output[0]}
export CASE_DUMP=$(pwd)/{output[0]}.case
export TRACE_DUMP=$(pwd)/{output[0]}.trace
export FUZZ_ITERS={RUNTIME}
# export FUZZ_ITERS={RUNTIME}
export FUZZER=$(pwd)/{input[1]}/debug/fret
set +e
../fuzzer.sh > {output[1]} 2>&1
# ../fuzzer.sh > {output[1]} 2>&1
echo $(pwd)/{input[1]}/debug/fret -k {input[0]} -c ./target_symbols.csv fuzz -t {RUNTIME} -s {wildcards.num}
$(pwd)/{input[1]}/debug/fret -k {input[0]} -c ./target_symbols.csv fuzz -t {RUNTIME} -s {wildcards.num} > {output[1]} 2>&1
exit 0
"""
if wildcards.fuzzer.find('random') >= 0:

View File

@ -1,7 +1,7 @@
//! A fuzzer using qemu in systemmode for binary-only coverage of kernels
//!
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};
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 libafl_bolts::{
core_affinity::Cores,
@ -43,6 +43,8 @@ use crate::{
mutational::{MINIMUM_INTER_ARRIVAL_TIME},
};
use std::time::{SystemTime, UNIX_EPOCH};
use clap::{Parser, Subcommand};
use csv::Reader;
pub static mut RNG_SEED: u64 = 1;
@ -82,7 +84,73 @@ extern "C" {
}
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
/// Kernel Image
#[arg(short, long, value_name = "FILE")]
kernel: PathBuf,
/// Sets a custom config file
#[arg(short, long, value_name = "FILE")]
config: PathBuf,
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// run a single input
Showmap {
/// take this input
#[arg(short, long)]
input: PathBuf,
},
/// start fuzzing campaign
Fuzz {
/// disable heuristic
#[arg(short, long)]
random: bool,
/// seed for randomness
#[arg(short, long)]
seed: Option<u64>,
/// runtime in seconds
#[arg(short, long)]
time: Option<u64>,
}
}
fn env_from_config(kernel : &PathBuf, path : &PathBuf) {
let is_csv = path.as_path().extension().map_or(false, |x| x=="csv");
if !is_csv {
let lines = std::fs::read_to_string(path).expect("Config file not found");
let lines = lines.lines().filter(
|x| x.len()>0
);
for l in lines {
let pair = l.split_once('=').expect("Non VAR=VAL line in config");
std::env::set_var(pair.0, pair.1);
}
} else {
let mut reader = csv::Reader::from_path(path).expect("CSV read from config failed");
let p = kernel.as_path();
let stem = p.file_stem().expect("Kernel filename error").to_str().unwrap();
for r in reader.records() {
let rec = r.expect("CSV entry error");
if stem == &rec[0] {
std::env::set_var("FUZZ_MAIN", &rec[1]);
std::env::set_var("FUZZ_INPUT", &rec[2]);
std::env::set_var("FUZZ_INPUT_LEN", &rec[3]);
std::env::set_var("BREAKPOINT", &rec[4]);
break;
}
}
}
}
pub fn fuzz() {
let cli = Cli::parse();
env_from_config(&cli.kernel, &cli.config);
unsafe {FUZZ_START_TIMESTAMP = SystemTime::now();}
let mut starttime = std::time::Instant::now();
if let Ok(s) = env::var("FUZZ_SIZE") {
@ -97,7 +165,7 @@ pub fn fuzz() {
let mut elf_buffer = Vec::new();
let elf = EasyElf::from_file(
env::var("KERNEL").expect("KERNEL env not set"),
&cli.kernel,
&mut elf_buffer,
)
.unwrap();
@ -168,7 +236,27 @@ pub fn fuzz() {
let mut run_client = |state: Option<_>, mut mgr, _core_id| {
// Initialize QEMU
let args: Vec<String> = env::args().collect();
let args: Vec<String> = vec![
"target/debug/fret",
"-icount",
"shift=4,align=off,sleep=off",
"-machine",
"mps2-an385",
"-monitor",
"null",
"-kernel",
&cli.kernel.as_os_str().to_str().expect("kernel path is not a string"),
"-serial",
"null",
"-nographic",
"-S",
"-semihosting",
"--semihosting-config",
"enable=on,target=native",
"-snapshot",
"-drive",
"if=none,format=qcow2,file=dummy.qcow2",
].into_iter().map(String::from).collect();
let env: Vec<(String, String)> = env::vars().collect();
let emu = Emulator::new(&args, &env).expect("Emulator creation failed");
@ -372,8 +460,8 @@ pub fn fuzz() {
#[cfg(not(feature = "fuzz_int"))]
let mut stages = tuple_list!(StdMutationalStage::new(mutator));
if env::var("DO_SHOWMAP").is_ok() {
let s = &env::var("DO_SHOWMAP").unwrap();
if let Commands::Showmap { input } = cli.command {
let s = input.as_os_str();
let show_input = if s=="-" {
let mut buf = Vec::<u8>::new();
std::io::stdin().read_to_end(&mut buf).expect("Could not read Stdin");
@ -398,10 +486,10 @@ pub fn fuzz() {
}
}
}
} else {
if let Ok(_) = env::var("SEED_RANDOM") {
} else if let Commands::Fuzz { random, time, seed } = cli.command {
if let Some(se) = seed {
unsafe {
let mut rng = StdRng::seed_from_u64(RNG_SEED);
let mut rng = StdRng::seed_from_u64(se);
for i in 0..100 {
let inp = BytesInput::new(vec![rng.gen::<u8>(); MAX_INPUT_SIZE]);
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap();
@ -426,15 +514,15 @@ pub fn fuzz() {
println!("We imported {} inputs from disk.", state.corpus().count());
}
match env::var("FUZZ_ITERS") {
Err(_) => {
match time {
None => {
fuzzer
.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)
.unwrap();
},
Ok(t) => {
Some(t) => {
println!("Iterations {}",t);
let num = str::parse::<u64>(&t).expect("FUZZ_ITERS was not a number");
let num = t;
if let Ok(s) = env::var("FUZZ_RANDOM") { unsafe {
if s.contains("watersv2_int") {
println!("V2");