diff --git a/src/agent/onefuzz-agent/src/tasks/fuzz/libfuzzer_fuzz.rs b/src/agent/onefuzz-agent/src/tasks/fuzz/libfuzzer_fuzz.rs index b989bf6ac..13995029d 100644 --- a/src/agent/onefuzz-agent/src/tasks/fuzz/libfuzzer_fuzz.rs +++ b/src/agent/onefuzz-agent/src/tasks/fuzz/libfuzzer_fuzz.rs @@ -96,34 +96,44 @@ impl LibFuzzerFuzzTask { worker_id: u64, stats_sender: Option<&StatsSender>, ) -> Result<()> { + let local_input_dir = tempdir()?; loop { - self.run_fuzzer(worker_id, stats_sender).await?; + self.run_fuzzer(&local_input_dir.path(), worker_id, stats_sender) + .await?; + + let mut entries = tokio::fs::read_dir(local_input_dir.path()).await?; + while let Some(Ok(entry)) = entries.next().await { + let destination_path = self.config.inputs.path.clone().join(entry.file_name()); + tokio::fs::rename(entry.path(), destination_path).await?; + } } } // Fuzz with a libFuzzer until it exits. // // While it runs, parse stderr for progress metrics, and report them. - async fn run_fuzzer(&self, worker_id: u64, stats_sender: Option<&StatsSender>) -> Result<()> { + async fn run_fuzzer( + &self, + local_inputs: impl AsRef, + worker_id: u64, + stats_sender: Option<&StatsSender>, + ) -> Result<()> { let crash_dir = tempdir()?; let run_id = Uuid::new_v4(); info!("starting fuzzer run, run_id = {}", run_id); - let inputs: Vec<_> = { - if let Some(readonly_inputs) = &self.config.readonly_inputs { - readonly_inputs.iter().map(|d| &d.path).collect() - } else { - vec![] - } - }; + let mut inputs = vec![&self.config.inputs.path]; + if let Some(readonly_inputs) = &self.config.readonly_inputs { + readonly_inputs.iter().for_each(|d| inputs.push(&d.path)); + } let fuzzer = LibFuzzer::new( &self.config.target_exe, &self.config.target_options, &self.config.target_env, ); - let mut running = fuzzer.fuzz(crash_dir.path(), &self.config.inputs.path, &inputs)?; + let mut running = fuzzer.fuzz(crash_dir.path(), local_inputs, &inputs)?; let sys_info = task::spawn(report_fuzzer_sys_info(worker_id, run_id, running.id())); diff --git a/src/agent/onefuzz/src/libfuzzer.rs b/src/agent/onefuzz/src/libfuzzer.rs index aa2696c84..66e9e1423 100644 --- a/src/agent/onefuzz/src/libfuzzer.rs +++ b/src/agent/onefuzz/src/libfuzzer.rs @@ -14,6 +14,8 @@ use std::{ }; use tokio::process::{Child, Command}; +const DEFAULT_MAX_TOTAL_SECONDS: i32 = 10 * 60; + pub struct LibFuzzerMergeOutput { pub added_files_count: i32, pub added_feature_count: i32, @@ -70,6 +72,15 @@ impl<'a> LibFuzzer<'a> { cmd.arg(o); } + // check if a max_time is already set + if let None = self + .options + .iter() + .find(|o| o.starts_with("-max_total_time")) + { + cmd.arg(format!("-max_total_time={}", DEFAULT_MAX_TOTAL_SECONDS)); + } + // When writing a new faulting input, the libFuzzer runtime _exactly_ // prepends the value of `-artifact_prefix` to the new file name. To // specify that a new file `crash-` should be written to a