diff --git a/docs/command-replacements.md b/docs/command-replacements.md index 18203b6dd..776053ba8 100644 --- a/docs/command-replacements.md +++ b/docs/command-replacements.md @@ -15,6 +15,7 @@ The following values are replaced with the specific values at runtime. (available wherever `input` is available) * `{runtime_dir}`: Path to the runtime directory for the task * `{tools_dir}`: Path to the task specific `tools` directory +* `{setup_dir}` : Path to the setup directory ## Example diff --git a/src/agent/onefuzz-agent/src/debug/generic_crash_report.rs b/src/agent/onefuzz-agent/src/debug/generic_crash_report.rs index 016657c13..d10543ade 100644 --- a/src/agent/onefuzz-agent/src/debug/generic_crash_report.rs +++ b/src/agent/onefuzz-agent/src/debug/generic_crash_report.rs @@ -29,6 +29,7 @@ async fn run_impl(input: String, config: Config) -> Result<()> { pub fn run(args: &clap::ArgMatches) -> Result<()> { let target_exe = value_t!(args, "target_exe", PathBuf)?; + let setup_dir = value_t!(args, "setup_dir", PathBuf)?; let input = value_t!(args, "input", String)?; let target_timeout = value_t!(args, "target_timeout", u64).ok(); let check_retry_count = value_t!(args, "check_retry_count", u64)?; @@ -65,6 +66,7 @@ pub fn run(args: &clap::ArgMatches) -> Result<()> { job_id: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap(), task_id: Uuid::parse_str("11111111-1111-1111-1111-111111111111").unwrap(), instance_id: Uuid::parse_str("22222222-2222-2222-2222-222222222222").unwrap(), + setup_dir, }, }; @@ -77,6 +79,11 @@ pub fn run(args: &clap::ArgMatches) -> Result<()> { pub fn args() -> App<'static, 'static> { SubCommand::with_name("generic-crash-report") .about("execute a local-only generic crash report") + .arg( + Arg::with_name("setup_dir") + .takes_value(true) + .required(false), + ) .arg( Arg::with_name("target_exe") .takes_value(true) diff --git a/src/agent/onefuzz-agent/src/debug/libfuzzer_coverage.rs b/src/agent/onefuzz-agent/src/debug/libfuzzer_coverage.rs index 75782aef3..447d19d5b 100644 --- a/src/agent/onefuzz-agent/src/debug/libfuzzer_coverage.rs +++ b/src/agent/onefuzz-agent/src/debug/libfuzzer_coverage.rs @@ -38,6 +38,7 @@ async fn run_impl(input: String, config: Config) -> Result<()> { pub fn run(args: &clap::ArgMatches) -> Result<()> { let target_exe = value_t!(args, "target_exe", PathBuf)?; + let setup_dir = value_t!(args, "setup_dir", PathBuf)?; let input = value_t!(args, "input", String)?; let result_dir = value_t!(args, "result_dir", String)?; let target_options = args.values_of_lossy("target_options").unwrap_or_default(); @@ -69,6 +70,7 @@ pub fn run(args: &clap::ArgMatches) -> Result<()> { job_id: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap(), task_id: Uuid::parse_str("11111111-1111-1111-1111-111111111111").unwrap(), instance_id: Uuid::parse_str("22222222-2222-2222-2222-222222222222").unwrap(), + setup_dir, }, }; @@ -81,6 +83,11 @@ pub fn run(args: &clap::ArgMatches) -> Result<()> { pub fn args() -> App<'static, 'static> { SubCommand::with_name("libfuzzer-coverage") .about("execute a local-only libfuzzer coverage task") + .arg( + Arg::with_name("setup_dir") + .takes_value(true) + .required(false), + ) .arg( Arg::with_name("target_exe") .takes_value(true) diff --git a/src/agent/onefuzz-agent/src/debug/libfuzzer_crash_report.rs b/src/agent/onefuzz-agent/src/debug/libfuzzer_crash_report.rs index 82e92f9f9..204b444db 100644 --- a/src/agent/onefuzz-agent/src/debug/libfuzzer_crash_report.rs +++ b/src/agent/onefuzz-agent/src/debug/libfuzzer_crash_report.rs @@ -30,6 +30,7 @@ async fn run_impl(input: String, config: Config) -> Result<()> { pub fn run(args: &clap::ArgMatches) -> Result<()> { let target_exe = value_t!(args, "target_exe", PathBuf)?; + let setup_dir = value_t!(args, "setup_dir", PathBuf)?; let input = value_t!(args, "input", String)?; let target_options = args.values_of_lossy("target_options").unwrap_or_default(); let mut target_env = HashMap::new(); @@ -65,6 +66,7 @@ pub fn run(args: &clap::ArgMatches) -> Result<()> { job_id: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap(), task_id: Uuid::parse_str("11111111-1111-1111-1111-111111111111").unwrap(), instance_id: Uuid::parse_str("22222222-2222-2222-2222-222222222222").unwrap(), + setup_dir, }, }; @@ -77,6 +79,11 @@ pub fn run(args: &clap::ArgMatches) -> Result<()> { pub fn args() -> App<'static, 'static> { SubCommand::with_name("libfuzzer-crash-report") .about("execute a local-only libfuzzer crash report task") + .arg( + Arg::with_name("setup_dir") + .takes_value(true) + .required(false), + ) .arg( Arg::with_name("target_exe") .takes_value(true) diff --git a/src/agent/onefuzz-agent/src/debug/libfuzzer_fuzz.rs b/src/agent/onefuzz-agent/src/debug/libfuzzer_fuzz.rs index e03fb5958..fdc345ed9 100644 --- a/src/agent/onefuzz-agent/src/debug/libfuzzer_fuzz.rs +++ b/src/agent/onefuzz-agent/src/debug/libfuzzer_fuzz.rs @@ -25,6 +25,7 @@ pub fn run(args: &clap::ArgMatches) -> Result<()> { let crashes_dir = value_t!(args, "crashes_dir", String)?; let inputs_dir = value_t!(args, "inputs_dir", String)?; let target_exe = value_t!(args, "target_exe", PathBuf)?; + let setup_dir = value_t!(args, "setup_dir", PathBuf)?; let target_options = args.values_of_lossy("target_options").unwrap_or_default(); // this happens during setup, not during runtime @@ -71,6 +72,7 @@ pub fn run(args: &clap::ArgMatches) -> Result<()> { job_id: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap(), task_id: Uuid::parse_str("11111111-1111-1111-1111-111111111111").unwrap(), instance_id: Uuid::parse_str("22222222-2222-2222-2222-222222222222").unwrap(), + setup_dir, }, }; @@ -83,6 +85,11 @@ pub fn run(args: &clap::ArgMatches) -> Result<()> { pub fn args() -> App<'static, 'static> { SubCommand::with_name("libfuzzer-fuzz") .about("execute a local-only libfuzzer crash report task") + .arg( + Arg::with_name("setup_dir") + .takes_value(true) + .required(false), + ) .arg( Arg::with_name("target_exe") .takes_value(true) diff --git a/src/agent/onefuzz-agent/src/debug/libfuzzer_merge.rs b/src/agent/onefuzz-agent/src/debug/libfuzzer_merge.rs index cb8e1f5ce..274cb8f8a 100644 --- a/src/agent/onefuzz-agent/src/debug/libfuzzer_merge.rs +++ b/src/agent/onefuzz-agent/src/debug/libfuzzer_merge.rs @@ -16,6 +16,7 @@ use uuid::Uuid; pub fn run(args: &clap::ArgMatches) -> Result<()> { let target_exe = value_t!(args, "target_exe", PathBuf)?; + let setup_dir = value_t!(args, "setup_dir", PathBuf)?; let inputs = value_t!(args, "inputs", String)?; let unique_inputs = value_t!(args, "unique_inputs", String)?; let target_options = args.values_of_lossy("target_options").unwrap_or_default(); @@ -50,6 +51,7 @@ pub fn run(args: &clap::ArgMatches) -> Result<()> { job_id: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap(), task_id: Uuid::parse_str("11111111-1111-1111-1111-111111111111").unwrap(), instance_id: Uuid::parse_str("22222222-2222-2222-2222-222222222222").unwrap(), + setup_dir, }, preserve_existing_outputs: true, }); @@ -66,6 +68,11 @@ pub fn run(args: &clap::ArgMatches) -> Result<()> { pub fn args() -> App<'static, 'static> { SubCommand::with_name("libfuzzer-merge") .about("execute a local-only libfuzzer merge task") + .arg( + Arg::with_name("setup_dir") + .takes_value(true) + .required(false), + ) .arg( Arg::with_name("target_exe") .takes_value(true) diff --git a/src/agent/onefuzz-agent/src/main.rs b/src/agent/onefuzz-agent/src/main.rs index 129651a73..52e101ed6 100644 --- a/src/agent/onefuzz-agent/src/main.rs +++ b/src/agent/onefuzz-agent/src/main.rs @@ -39,6 +39,12 @@ fn main() -> Result<()> { .short("c") .takes_value(true), ) + .arg( + Arg::with_name("setup_dir") + .long("setup_dir") + .short("s") + .takes_value(true), + ) .subcommand(debug::cmd::args()) .subcommand(SubCommand::with_name("licenses").about("display third-party licenses")); @@ -58,7 +64,8 @@ fn main() -> Result<()> { } let config_path: PathBuf = matches.value_of("config").unwrap().parse()?; - let config = Config::from_file(config_path)?; + let setup_dir = matches.value_of("setup_dir"); + let config = Config::from_file(config_path, setup_dir)?; init_telemetry(&config); diff --git a/src/agent/onefuzz-agent/src/tasks/analysis/generic.rs b/src/agent/onefuzz-agent/src/tasks/analysis/generic.rs index 603cdc0ed..6cce9171f 100644 --- a/src/agent/onefuzz-agent/src/tasks/analysis/generic.rs +++ b/src/agent/onefuzz-agent/src/tasks/analysis/generic.rs @@ -121,7 +121,8 @@ pub async fn run_tool(input: impl AsRef, config: &Config) -> Result<()> { .target_options(&config.target_options) .analyzer_exe(&config.analyzer_exe) .analyzer_options(&config.analyzer_options) - .output_dir(&config.analysis.path); + .output_dir(&config.analysis.path) + .setup_dir(&config.common.setup_dir); let analyzer_path = Expand::new() .tools_dir(&config.tools.path) diff --git a/src/agent/onefuzz-agent/src/tasks/config.rs b/src/agent/onefuzz-agent/src/tasks/config.rs index 03e6ace35..02dc90b1d 100644 --- a/src/agent/onefuzz-agent/src/tasks/config.rs +++ b/src/agent/onefuzz-agent/src/tasks/config.rs @@ -10,7 +10,7 @@ use onefuzz::{ }; use reqwest::Url; use serde::{self, Deserialize}; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::sync::Arc; use uuid::Uuid; @@ -33,6 +33,8 @@ pub struct CommonConfig { pub heartbeat_queue: Option, pub telemetry_key: Option, + + pub setup_dir: PathBuf, } impl CommonConfig { @@ -79,9 +81,16 @@ pub enum Config { } impl Config { - pub fn from_file(path: impl AsRef) -> Result { + pub fn from_file(path: impl AsRef, setup_dir: Option>) -> Result { let json = std::fs::read_to_string(path)?; - Ok(serde_json::from_str(&json)?) + let mut json_config: serde_json::Value = serde_json::from_str(&json)?; + // override the setup_dir in the config file with the parameter value if specified + if let Some(setup_dir) = setup_dir { + json_config["setup_dir"] = + serde_json::Value::String(setup_dir.as_ref().to_string_lossy().into()); + } + + Ok(serde_json::from_value(json_config)?) } pub fn common(&self) -> &CommonConfig { diff --git a/src/agent/onefuzz-agent/src/tasks/coverage/libfuzzer_coverage.rs b/src/agent/onefuzz-agent/src/tasks/coverage/libfuzzer_coverage.rs index 19edc58ad..69cf35754 100644 --- a/src/agent/onefuzz-agent/src/tasks/coverage/libfuzzer_coverage.rs +++ b/src/agent/onefuzz-agent/src/tasks/coverage/libfuzzer_coverage.rs @@ -104,6 +104,7 @@ impl CoverageTask { &self.config.target_exe, &self.config.target_options, &self.config.target_env, + &self.config.common.setup_dir, ); target.check_help().await?; } diff --git a/src/agent/onefuzz-agent/src/tasks/fuzz/generator.rs b/src/agent/onefuzz-agent/src/tasks/fuzz/generator.rs index c0c48df24..260525c37 100644 --- a/src/agent/onefuzz-agent/src/tasks/fuzz/generator.rs +++ b/src/agent/onefuzz-agent/src/tasks/fuzz/generator.rs @@ -66,6 +66,7 @@ pub async fn spawn(config: Arc) -> Result<(), Error> { let sync_task = continuous_sync(&config.readonly_inputs, Pull, config.ensemble_sync_delay); let crash_dir_monitor = config.crashes.monitor_results(new_result); let tester = Tester::new( + &config.common.setup_dir, &config.target_exe, &config.target_options, &config.target_env, 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 29ffd8d53..dbb28957b 100644 --- a/src/agent/onefuzz-agent/src/tasks/fuzz/libfuzzer_fuzz.rs +++ b/src/agent/onefuzz-agent/src/tasks/fuzz/libfuzzer_fuzz.rs @@ -72,6 +72,7 @@ impl LibFuzzerFuzzTask { &self.config.target_exe, &self.config.target_options, &self.config.target_env, + &self.config.common.setup_dir, ); target.check_help().await?; } @@ -156,6 +157,7 @@ impl LibFuzzerFuzzTask { &self.config.target_exe, &self.config.target_options, &self.config.target_env, + &self.config.common.setup_dir, ); let mut running = fuzzer.fuzz(crash_dir.path(), local_inputs, &inputs)?; diff --git a/src/agent/onefuzz-agent/src/tasks/fuzz/supervisor.rs b/src/agent/onefuzz-agent/src/tasks/fuzz/supervisor.rs index 99757b766..900ebda11 100644 --- a/src/agent/onefuzz-agent/src/tasks/fuzz/supervisor.rs +++ b/src/agent/onefuzz-agent/src/tasks/fuzz/supervisor.rs @@ -102,6 +102,7 @@ pub async fn spawn(config: SupervisorConfig) -> Result<(), Error> { &config.supervisor_options, &config.supervisor_env, &config.supervisor_input_marker, + &config.common.setup_dir, ) .await?; @@ -156,6 +157,7 @@ async fn start_supervisor( supervisor_options: &[String], supervisor_env: &HashMap, supervisor_input_marker: &Option, + setup_dir: impl AsRef, ) -> Result { let mut cmd = Command::new(supervisor_path.as_ref()); @@ -173,7 +175,8 @@ async fn start_supervisor( .runtime_dir(runtime_dir) .target_exe(target_exe) .target_options(target_options) - .input_corpus(inputs_dir); + .input_corpus(inputs_dir) + .setup_dir(setup_dir); if let Some(input_marker) = supervisor_input_marker { expand.input_marker(input_marker); @@ -276,6 +279,7 @@ mod tests { &supervisor_options, &supervisor_env, &supervisor_input_marker, + None, ) .await .unwrap(); diff --git a/src/agent/onefuzz-agent/src/tasks/merge/generic.rs b/src/agent/onefuzz-agent/src/tasks/merge/generic.rs index 76f226a24..3bc6d3c4a 100644 --- a/src/agent/onefuzz-agent/src/tasks/merge/generic.rs +++ b/src/agent/onefuzz-agent/src/tasks/merge/generic.rs @@ -138,7 +138,8 @@ async fn merge(config: &Config, output_dir: impl AsRef) -> Result<()> { .supervisor_exe(&config.supervisor_exe) .supervisor_options(&config.supervisor_options) .generated_inputs(output_dir) - .target_exe(&config.target_exe); + .target_exe(&config.target_exe) + .setup_dir(&config.common.setup_dir); if config.target_options_merge { supervisor_args.target_options(&config.target_options); diff --git a/src/agent/onefuzz-agent/src/tasks/merge/libfuzzer_merge.rs b/src/agent/onefuzz-agent/src/tasks/merge/libfuzzer_merge.rs index 3ab6aa023..2281921b7 100644 --- a/src/agent/onefuzz-agent/src/tasks/merge/libfuzzer_merge.rs +++ b/src/agent/onefuzz-agent/src/tasks/merge/libfuzzer_merge.rs @@ -52,6 +52,7 @@ pub async fn spawn(config: Arc) -> Result<()> { &config.target_exe, &config.target_options, &config.target_env, + &config.common.setup_dir, ); target.check_help().await?; } @@ -162,6 +163,7 @@ pub async fn merge_inputs( &config.target_exe, &config.target_options, &config.target_env, + &config.common.setup_dir, ); merger.merge(&config.unique_inputs.path, &candidates).await } diff --git a/src/agent/onefuzz-agent/src/tasks/report/generic.rs b/src/agent/onefuzz-agent/src/tasks/report/generic.rs index 64699c70f..34170dfdd 100644 --- a/src/agent/onefuzz-agent/src/tasks/report/generic.rs +++ b/src/agent/onefuzz-agent/src/tasks/report/generic.rs @@ -87,6 +87,7 @@ pub struct GenericReportProcessor<'a> { impl<'a> GenericReportProcessor<'a> { pub fn new(config: &'a Config, heartbeat_client: Option) -> Self { let tester = Tester::new( + &config.common.setup_dir, &config.target_exe, &config.target_options, &config.target_env, diff --git a/src/agent/onefuzz-agent/src/tasks/report/libfuzzer_report.rs b/src/agent/onefuzz-agent/src/tasks/report/libfuzzer_report.rs index 4e88b131f..175f6a3ab 100644 --- a/src/agent/onefuzz-agent/src/tasks/report/libfuzzer_report.rs +++ b/src/agent/onefuzz-agent/src/tasks/report/libfuzzer_report.rs @@ -61,6 +61,7 @@ impl ReportTask { &self.config.target_exe, &self.config.target_options, &self.config.target_env, + &self.config.common.setup_dir, ); target.check_help().await?; } @@ -101,6 +102,7 @@ impl AsanProcessor { &self.config.target_exe, &self.config.target_options, &self.config.target_env, + &self.config.common.setup_dir, ); let task_id = self.config.common.task_id; diff --git a/src/agent/onefuzz-supervisor/src/debug.rs b/src/agent/onefuzz-supervisor/src/debug.rs index 03fb5ecc1..b124b7d21 100644 --- a/src/agent/onefuzz-supervisor/src/debug.rs +++ b/src/agent/onefuzz-supervisor/src/debug.rs @@ -180,8 +180,9 @@ async fn run_worker(mut work_set: WorkSet) -> Result> { let mut events = vec![]; let work_unit = work_set.work_units.pop().unwrap(); + let setup_dir = work_set.setup_dir()?; - let mut worker = Worker::new(work_unit); + let mut worker = Worker::new(&setup_dir, work_unit); while !worker.is_done() { worker = worker.update(&mut events, &mut WorkerRunner).await?; } diff --git a/src/agent/onefuzz-supervisor/src/scheduler.rs b/src/agent/onefuzz-supervisor/src/scheduler.rs index 6b9b86215..4dd1dc2ee 100644 --- a/src/agent/onefuzz-supervisor/src/scheduler.rs +++ b/src/agent/onefuzz-supervisor/src/scheduler.rs @@ -224,9 +224,9 @@ impl State { impl State { pub async fn run(self) -> Result> { let mut workers = vec![]; - + let setup_dir = self.ctx.work_set.setup_dir()?; for work in self.ctx.work_set.work_units { - let worker = Some(Worker::new(work)); + let worker = Some(Worker::new(&setup_dir, work)); workers.push(worker); } diff --git a/src/agent/onefuzz-supervisor/src/setup.rs b/src/agent/onefuzz-supervisor/src/setup.rs index 219a67277..918e58205 100644 --- a/src/agent/onefuzz-supervisor/src/setup.rs +++ b/src/agent/onefuzz-supervisor/src/setup.rs @@ -42,10 +42,7 @@ impl SetupRunner { // Download the setup container. let setup_url = work_set.setup_url.url(); - let setup_dir = work_set.setup_url.container(); - let setup_dir = onefuzz::fs::onefuzz_root()? - .join("blob-containers") - .join(setup_dir); + let setup_dir = work_set.setup_dir()?; // `azcopy sync` requires the local dir to exist. fs::create_dir_all(&setup_dir).await.with_context(|| { diff --git a/src/agent/onefuzz-supervisor/src/work.rs b/src/agent/onefuzz-supervisor/src/work.rs index e66aef540..7ee0a8523 100644 --- a/src/agent/onefuzz-supervisor/src/work.rs +++ b/src/agent/onefuzz-supervisor/src/work.rs @@ -69,6 +69,13 @@ impl WorkSet { Ok(()) } + + pub fn setup_dir(&self) -> Result { + let setup_dir = self.setup_url.container(); + Ok(onefuzz::fs::onefuzz_root()? + .join("blob-containers") + .join(setup_dir)) + } } #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] diff --git a/src/agent/onefuzz-supervisor/src/worker.rs b/src/agent/onefuzz-supervisor/src/worker.rs index a75ae223f..c3e815773 100644 --- a/src/agent/onefuzz-supervisor/src/worker.rs +++ b/src/agent/onefuzz-supervisor/src/worker.rs @@ -1,7 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -use std::process::{Child, Command, Stdio}; +use std::{ + path::{Path, PathBuf}, + process::{Child, Command, Stdio}, +}; use anyhow::{Context as AnyhowContext, Result}; use downcast_rs::Downcast; @@ -31,8 +34,10 @@ pub enum Worker { } impl Worker { - pub fn new(work: WorkUnit) -> Self { - let ctx = Ready; + pub fn new(setup_dir: impl AsRef, work: WorkUnit) -> Self { + let ctx = Ready { + setup_dir: PathBuf::from(setup_dir.as_ref()), + }; let state = State { ctx, work }; state.into() } @@ -79,7 +84,9 @@ impl Worker { } } -pub struct Ready; +pub struct Ready { + setup_dir: PathBuf, +} pub struct Running { child: Box, @@ -108,7 +115,7 @@ impl State { impl State { pub async fn run(self, runner: &mut dyn IWorkerRunner) -> Result> { - let child = runner.run(&self.work).await?; + let child = runner.run(&self.ctx.setup_dir, &self.work).await?; let state = State { ctx: Running { child }, @@ -167,7 +174,7 @@ impl_from_state_for_worker!(Done); #[async_trait] pub trait IWorkerRunner: Downcast { - async fn run(&mut self, work: &WorkUnit) -> Result>; + async fn run(&mut self, setup_dir: &Path, work: &WorkUnit) -> Result>; } impl_downcast!(IWorkerRunner); @@ -184,7 +191,7 @@ pub struct WorkerRunner; #[async_trait] impl IWorkerRunner for WorkerRunner { - async fn run(&mut self, work: &WorkUnit) -> Result> { + async fn run(&mut self, setup_dir: &Path, work: &WorkUnit) -> Result> { let working_dir = work.working_dir()?; verbose!("worker working dir = {}", working_dir.display()); @@ -220,6 +227,8 @@ impl IWorkerRunner for WorkerRunner { cmd.current_dir(&working_dir); cmd.arg("-c"); cmd.arg("config.json"); + cmd.arg("-s"); + cmd.arg(setup_dir); cmd.stderr(Stdio::piped()); cmd.stdout(Stdio::piped()); diff --git a/src/agent/onefuzz-supervisor/src/worker/double.rs b/src/agent/onefuzz-supervisor/src/worker/double.rs index dadc88a8d..8fa6a918a 100644 --- a/src/agent/onefuzz-supervisor/src/worker/double.rs +++ b/src/agent/onefuzz-supervisor/src/worker/double.rs @@ -10,7 +10,7 @@ pub struct WorkerRunnerDouble { #[async_trait] impl IWorkerRunner for WorkerRunnerDouble { - async fn run(&mut self, _work: &WorkUnit) -> Result> { + async fn run(&mut self, _setup_dir: &Path, _work: &WorkUnit) -> Result> { Ok(Box::new(self.child.clone())) } } diff --git a/src/agent/onefuzz-supervisor/src/worker/tests.rs b/src/agent/onefuzz-supervisor/src/worker/tests.rs index fbd0fdd93..f22767095 100644 --- a/src/agent/onefuzz-supervisor/src/worker/tests.rs +++ b/src/agent/onefuzz-supervisor/src/worker/tests.rs @@ -55,7 +55,7 @@ struct RunnerDouble { #[async_trait] impl IWorkerRunner for RunnerDouble { - async fn run(&mut self, _work: &WorkUnit) -> Result> { + async fn run(&mut self, _setup_dir: &Path, _work: &WorkUnit) -> Result> { Ok(Box::new(self.child.clone())) } } @@ -64,7 +64,9 @@ impl IWorkerRunner for RunnerDouble { async fn test_ready_run() { let mut runner = Fixture.runner(Fixture.child_running()); let state = State { - ctx: Ready, + ctx: Ready { + setup_dir: PathBuf::default(), + }, work: Fixture.work(), }; @@ -144,7 +146,9 @@ async fn test_worker_ready_update() { let task_id = Fixture.work().task_id; let state = State { - ctx: Ready, + ctx: Ready { + setup_dir: PathBuf::default(), + }, work: Fixture.work(), }; let worker = Worker::Ready(state); diff --git a/src/agent/onefuzz/src/expand.rs b/src/agent/onefuzz/src/expand.rs index 617a4d5cb..6646858fa 100644 --- a/src/agent/onefuzz/src/expand.rs +++ b/src/agent/onefuzz/src/expand.rs @@ -33,6 +33,7 @@ pub enum PlaceHolder { GeneratorOptions, SupervisorExe, SupervisorOptions, + SetupDir, } impl PlaceHolder { @@ -55,6 +56,7 @@ impl PlaceHolder { Self::GeneratorOptions => "{generator_options}", Self::SupervisorExe => "{supervisor_exe}", Self::SupervisorOptions => "{supervisor_options}", + Self::SetupDir => "{setup_dir}", } .to_string() } @@ -215,6 +217,13 @@ impl<'a> Expand<'a> { self } + pub fn setup_dir(&mut self, arg: impl AsRef) -> &mut Self { + let arg = arg.as_ref(); + let path = String::from(arg.to_string_lossy()); + self.set_value(PlaceHolder::SetupDir, ExpandedValue::Path(path)); + self + } + fn replace_value( &self, fmtstr: &str, diff --git a/src/agent/onefuzz/src/input_tester.rs b/src/agent/onefuzz/src/input_tester.rs index d10c11c2f..7ee74ae42 100644 --- a/src/agent/onefuzz/src/input_tester.rs +++ b/src/agent/onefuzz/src/input_tester.rs @@ -16,6 +16,7 @@ const DEFAULT_TIMEOUT_SECS: u64 = 5; const CRASH_SITE_UNAVAILABLE: &str = ""; pub struct Tester<'a> { + setup_dir: &'a Path, exe_path: &'a Path, arguments: &'a [String], environ: &'a HashMap, @@ -42,6 +43,7 @@ pub struct TestResult { impl<'a> Tester<'a> { pub fn new( + setup_dir: &'a Path, exe_path: &'a Path, arguments: &'a [String], environ: &'a HashMap, @@ -53,6 +55,7 @@ impl<'a> Tester<'a> { ) -> Self { let timeout = Duration::from_secs(timeout.unwrap_or(DEFAULT_TIMEOUT_SECS)); Self { + setup_dir, exe_path, arguments, environ, @@ -193,6 +196,8 @@ impl<'a> Tester<'a> { .target_exe(&self.exe_path) .target_options(&self.arguments); + expand.setup_dir(&self.setup_dir); + let argv = expand.evaluate(&self.arguments)?; let mut env: HashMap = HashMap::new(); for (k, v) in self.environ { @@ -218,7 +223,7 @@ impl<'a> Tester<'a> { Err(error) => (None, Some(error), None), } } else { - match run_cmd(self.exe_path, argv.clone(), &env, self.timeout).await { + match run_cmd(&self.exe_path, argv.clone(), &env, self.timeout).await { Ok(output) => (None, None, Some(output)), Err(error) => (None, Some(error), None), } diff --git a/src/agent/onefuzz/src/libfuzzer.rs b/src/agent/onefuzz/src/libfuzzer.rs index cf4dca7a0..ae6cdf3da 100644 --- a/src/agent/onefuzz/src/libfuzzer.rs +++ b/src/agent/onefuzz/src/libfuzzer.rs @@ -22,6 +22,7 @@ pub struct LibFuzzerMergeOutput { } pub struct LibFuzzer<'a> { + setup_dir: PathBuf, exe: PathBuf, options: &'a [String], env: &'a HashMap, @@ -32,11 +33,13 @@ impl<'a> LibFuzzer<'a> { exe: impl Into, options: &'a [String], env: &'a HashMap, + setup_dir: impl Into, ) -> Self { Self { exe: exe.into(), options, env, + setup_dir: setup_dir.into(), } } @@ -53,7 +56,10 @@ impl<'a> LibFuzzer<'a> { .arg("-help=1"); let mut expand = Expand::new(); - expand.target_exe(&self.exe).target_options(&self.options); + expand + .target_exe(&self.exe) + .target_options(&self.options) + .setup_dir(&self.setup_dir); for (k, v) in self.env { cmd.env(k, expand.evaluate_value(v)?); @@ -85,7 +91,8 @@ impl<'a> LibFuzzer<'a> { .target_exe(&self.exe) .target_options(&self.options) .input_corpus(&corpus_dir) - .crashes(&fault_dir); + .crashes(&fault_dir) + .setup_dir(&self.setup_dir); let mut cmd = Command::new(&self.exe); cmd.kill_on_drop(true) @@ -148,7 +155,15 @@ impl<'a> LibFuzzer<'a> { options.push("{input}".to_string()); let tester = Tester::new( - &self.exe, &options, &self.env, &timeout, false, true, false, retry, + &self.setup_dir, + &self.exe, + &options, + &self.env, + &timeout, + false, + true, + false, + retry, ); tester.test_input(test_input.as_ref()).await } @@ -162,7 +177,8 @@ impl<'a> LibFuzzer<'a> { expand .target_exe(&self.exe) .target_options(&self.options) - .input_corpus(&corpus_dir); + .input_corpus(&corpus_dir) + .setup_dir(&self.setup_dir); let mut cmd = Command::new(&self.exe);