From bade18eaf3ef14cbc3cfae984d989b73eee3aec1 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sun, 3 Jan 2021 19:55:13 +0100 Subject: [PATCH] working on restore --- afl/src/events/llmp.rs | 7 ++++ fuzzers/libfuzzer_libpng/Cargo.toml | 2 + fuzzers/libfuzzer_libpng/src/mod.rs | 63 +++++++++++++++++------------ 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/afl/src/events/llmp.rs b/afl/src/events/llmp.rs index 206edf8828..dde62945a5 100644 --- a/afl/src/events/llmp.rs +++ b/afl/src/events/llmp.rs @@ -413,6 +413,13 @@ where }) } + /// Completely reset the current sender map. + /// Afterwards, no receiver should read from it at a different location. + /// This is only useful if all connected llmp parties start over, for example after a crash. + pub unsafe fn reset_last_page(&mut self) { + _llmp_page_init(&mut self.out_maps.last_mut().unwrap().shmem, self.id); + } + /// Reattach to a vacant out_map, to with a previous sender stored the information in an env before. #[cfg(feature = "std")] pub fn on_existing_from_env(env_name: &str) -> Result { diff --git a/fuzzers/libfuzzer_libpng/Cargo.toml b/fuzzers/libfuzzer_libpng/Cargo.toml index dc8ed1d228..0af13c750f 100644 --- a/fuzzers/libfuzzer_libpng/Cargo.toml +++ b/fuzzers/libfuzzer_libpng/Cargo.toml @@ -23,6 +23,8 @@ num_cpus = "1.0" [dependencies] clap = "2.32.0" +serde = { version = "1.0", default-features = false, features = ["alloc"] } +postcard = { version = "0.5.1", features = ["alloc"] } afl = { path = "../../afl/" } [[bin]] diff --git a/fuzzers/libfuzzer_libpng/src/mod.rs b/fuzzers/libfuzzer_libpng/src/mod.rs index 12e3cd0def..660ea7c049 100644 --- a/fuzzers/libfuzzer_libpng/src/mod.rs +++ b/fuzzers/libfuzzer_libpng/src/mod.rs @@ -2,6 +2,7 @@ extern crate clap; use clap::{App, Arg}; +use postcard; use std::{env, path::PathBuf, process::Command}; use afl::{ @@ -25,7 +26,8 @@ use afl::{ }; /// The llmp connection from the actual fuzzer to the process supervising it -const ENV_FUZZER_PARENT_SENDER: &str = &"_AFL_ENV_FUZZER_PARENT_SENDER"; +const ENV_FUZZER_SENDER: &str = &"_AFL_ENV_FUZZER_SENDER"; +const ENV_FUZZER_RECEIVER: &str = &"_AFL_ENV_FUZZER_RECEIVER"; /// The llmp (2 way) connection from a fuzzer to the broker (broadcasting all other fuzzer messages) const ENV_FUZZER_BROKER_CLIENT: &str = &"_AFL_ENV_FUZZER_BROKER_CLIENT"; @@ -56,13 +58,12 @@ fn harness(_executor: &dyn Executor, buf: &[u8]) -> ExitKind { /// The actual fuzzer fn fuzz(input: Option>, broker_port: u16) -> Result<(), AflError> { let mut rand = StdRand::new(0); - let mut corpus = InMemoryCorpus::new(); let mut generator = RandPrintablesGenerator::new(32); let stats = SimpleStats::new(|s| println!("{}", s)); let mut mgr; // We start ourself as child process to actually fuzz - if std::env::var(ENV_FUZZER_PARENT_SENDER).is_err() { + if std::env::var(ENV_FUZZER_SENDER).is_err() { // We are either the broker, or the parent of the fuzzing instance mgr = LlmpEventManager::new_on_port_std(broker_port, stats.clone())?; if mgr.is_broker() { @@ -77,12 +78,13 @@ fn fuzz(input: Option>, broker_port: u16) -> Result<(), AflError> { // First, create a channel from the fuzzer (sender) to us (receiver) to report its state for restarts. let sender = LlmpSender::new(0, false)?; - let mut receiver = LlmpReceiver::on_existing_map( + let receiver = LlmpReceiver::on_existing_map( AflShmem::clone_ref(&sender.out_maps.last().unwrap().shmem)?, None, )?; // Store the information to a map. - sender.to_env(ENV_FUZZER_PARENT_SENDER)?; + sender.to_env(ENV_FUZZER_SENDER)?; + receiver.to_env(ENV_FUZZER_RECEIVER)?; loop { dbg!("Spawning next client"); @@ -90,23 +92,38 @@ fn fuzz(input: Option>, broker_port: u16) -> Result<(), AflError> { .current_dir(env::current_dir()?) .args(env::args()) .status()?; - - match receiver.recv_buf()? { - None => panic!("Fuzzer process exited without giving us its result."), - Some((sender, tag, msg)) => { - todo!("Restore this: {}, {}, {:?}", sender, tag, msg); - } - } } } } println!("We're a client, let's fuzz :)"); - // We are the fuzzing instance + // We are the fuzzing instance, first, connect to all channels. + // Mgr to send and receive msgs from/to all other fuzzer instances mgr = LlmpEventManager::existing_client_from_env_std(ENV_FUZZER_BROKER_CLIENT, stats)?; - let channel_sender = LlmpSender::::on_existing_from_env(ENV_FUZZER_PARENT_SENDER)?; + // A sender and a receiver for single communication + let mut receiver = LlmpReceiver::::on_existing_from_env(ENV_FUZZER_RECEIVER)?; + let mut sender = LlmpSender::::on_existing_from_env(ENV_FUZZER_SENDER)?; + // Call LLVMFUzzerInitialize() if present. + unsafe { + if afl_libfuzzer_init() == -1 { + println!("Warning: LLVMFuzzerInitialize failed with -1") + } + } + + // If we're restarting, deserialize the old corpus. + let mut corpus = match receiver.recv_buf()? { + None => { + // Initial execution, read or generate initial inputs + InMemoryCorpus::new() + } + Some((_sender, _tag, msg)) => postcard::from_bytes(msg)?, + }; + // We reset the sender, the next sender and receiver (after crash) will reuse the page from the initial message. + unsafe { sender.reset_last_page() }; + + // TODO: How to restore the observer state? let edges_observer = StdMapObserver::new_from_ptr(&NAME_COV_MAP, unsafe { __lafl_edges_map }, unsafe { __lafl_max_edges_size as usize @@ -118,20 +135,14 @@ fn fuzz(input: Option>, broker_port: u16) -> Result<(), AflError> { let mut engine = Engine::new(executor); - // Call LLVMFUzzerInitialize() if present. - unsafe { - if afl_libfuzzer_init() == -1 { - println!("Warning: LLVMFuzzerInitialize failed with -1") + if corpus.count() < 1 { + match input { + Some(x) => state + .load_initial_inputs(&mut corpus, &mut generator, &mut engine, &mut mgr, &x) + .expect(&format!("Failed to load initial corpus at {:?}", &x)), + None => (), } } - - match input { - Some(x) => state - .load_initial_inputs(&mut corpus, &mut generator, &mut engine, &mut mgr, &x) - .expect(&format!("Failed to load initial corpus at {:?}", &x)), - None => (), - } - if corpus.count() < 1 { println!("Generating random inputs"); state