From c411b3671c2b56bbc43c7b7416d0ea469eaab4bb Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Sun, 26 Mar 2023 17:57:28 -0700 Subject: [PATCH 01/13] WIP: Adding a validation command to the agent --- src/agent/Cargo.lock | 1 + src/agent/onefuzz-agent/Cargo.toml | 1 + src/agent/onefuzz-agent/src/Validation.rs | 37 +++++++++++++++++ src/agent/onefuzz-agent/src/main.rs | 11 ++++++ src/agent/onefuzz-agent/src/work.rs | 48 +++++++++++++++++++++++ 5 files changed, 98 insertions(+) create mode 100644 src/agent/onefuzz-agent/src/Validation.rs diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock index 1c52c7c334..2bd3bfdb3c 100644 --- a/src/agent/Cargo.lock +++ b/src/agent/Cargo.lock @@ -1987,6 +1987,7 @@ dependencies = [ "log", "nix", "onefuzz", + "onefuzz-task", "onefuzz-telemetry", "reqwest", "reqwest-retry", diff --git a/src/agent/onefuzz-agent/Cargo.toml b/src/agent/onefuzz-agent/Cargo.toml index fd7acd9ace..884f8a7ee4 100644 --- a/src/agent/onefuzz-agent/Cargo.toml +++ b/src/agent/onefuzz-agent/Cargo.toml @@ -14,6 +14,7 @@ env_logger = "0.10" futures = "0.3" log = "0.4" onefuzz = { path = "../onefuzz" } +onefuzz-task = { path = "../onefuzz-task" } reqwest = { version = "0.11", features = [ "json", "stream", diff --git a/src/agent/onefuzz-agent/src/Validation.rs b/src/agent/onefuzz-agent/src/Validation.rs new file mode 100644 index 0000000000..50fcbd0da5 --- /dev/null +++ b/src/agent/onefuzz-agent/src/Validation.rs @@ -0,0 +1,37 @@ +use anyhow::{Context, Result}; +use clap::{ArgAction, Parser}; + +#[derive(Parser, Debug)] +#[clap(rename_all = "snake_case")] +pub enum ValidationCommand{ + ValidateSetup, + ValidateLibfuzzer, + ShowDebuggerSnap +} + + +pub async fn validate(validation_command: ValidationCommand) -> Result<()> { + match validation_command { + ValidationCommand::ValidateSetup => { + validate_setup().await + }, + ValidationCommand::ValidateLibfuzzer => { + validate_libfuzzer().await + }, + ValidationCommand::ShowDebuggerSnap => { + show_debugger_snap().await + } + } +} + +async fn show_debugger_snap() -> Result<()> { + todo!() +} + +async fn validate_libfuzzer() -> Result<()> { + todo!() +} + +async fn validate_setup() -> Result<()> { + todo!() +} \ No newline at end of file diff --git a/src/agent/onefuzz-agent/src/main.rs b/src/agent/onefuzz-agent/src/main.rs index ce809bcf3b..8c32cdb17d 100644 --- a/src/agent/onefuzz-agent/src/main.rs +++ b/src/agent/onefuzz-agent/src/main.rs @@ -40,6 +40,7 @@ pub mod panic; pub mod reboot; pub mod scheduler; pub mod setup; +pub mod Validation; pub mod work; pub mod worker; @@ -48,6 +49,8 @@ enum Opt { Run(RunOpt), #[clap(subcommand)] Debug(debug::DebugOpt), + #[clap(subcommand)] + Validate(Validation::ValidationCommand), Licenses, Version, } @@ -84,11 +87,19 @@ fn main() -> Result<()> { Opt::Debug(opt) => debug::debug(opt)?, Opt::Licenses => licenses()?, Opt::Version => version(), + Opt::Validate(opt) => validate(opt)?, }; Ok(()) } +fn validate(validation_command: Validation::ValidationCommand) -> Result<()> { + let rt = tokio::runtime::Runtime::new()?; + rt.block_on(async { + Validation::validate(validation_command).await + }) +} + fn version() { println!( "{} onefuzz:{} git:{}", diff --git a/src/agent/onefuzz-agent/src/work.rs b/src/agent/onefuzz-agent/src/work.rs index c68aabc493..0dfef625d2 100644 --- a/src/agent/onefuzz-agent/src/work.rs +++ b/src/agent/onefuzz-agent/src/work.rs @@ -252,3 +252,51 @@ impl WorkQueue { #[cfg(test)] pub mod double; + + +#[cfg(test)] +pub mod test { + + use super::*; + use reqwest::Url; + use serde_json; + + #[test] + fn test(){ + + let w1 = WorkSet { + reboot: true, + setup_url: BlobContainerUrl::BlobContainer( + Url::parse("https://onefuzz-test.blob.core.windows.net/containers/1?sv=2019-12-12&sr=c&sig=123&se=2020-12-31T00%3A00%3A00Z&sp=r").unwrap(), + ), + extra_url: None, + script: true, + work_units: vec![] + }; + + let w2 = WorkSet { + reboot: true, + setup_url: BlobContainerUrl::Path( + PathBuf::from("c:\\test\\test"), + ), + extra_url: None, + script: true, + work_units: vec![] + }; + + println!("{}", serde_json::to_string(&w1).unwrap()) ; + + let w2_json = serde_json::to_string(&w2).unwrap(); + println!("{}", w2_json) ; + + let w3: WorkSet = serde_json::from_str(&w2_json).unwrap(); + + // asse + + println!("{:?}", w3); + + + + + } +} From dc4834db99128fdff1de7a6c8d77a81205339131 Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Sun, 26 Mar 2023 18:24:17 -0700 Subject: [PATCH 02/13] introducing a ValidationConfig --- src/agent/onefuzz-agent/src/main.rs | 8 +++--- .../src/{Validation.rs => validation.rs} | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) rename src/agent/onefuzz-agent/src/{Validation.rs => validation.rs} (50%) diff --git a/src/agent/onefuzz-agent/src/main.rs b/src/agent/onefuzz-agent/src/main.rs index 8c32cdb17d..b1defa30c5 100644 --- a/src/agent/onefuzz-agent/src/main.rs +++ b/src/agent/onefuzz-agent/src/main.rs @@ -40,7 +40,7 @@ pub mod panic; pub mod reboot; pub mod scheduler; pub mod setup; -pub mod Validation; +pub mod validation; pub mod work; pub mod worker; @@ -50,7 +50,7 @@ enum Opt { #[clap(subcommand)] Debug(debug::DebugOpt), #[clap(subcommand)] - Validate(Validation::ValidationCommand), + Validate(validation::ValidationCommand), Licenses, Version, } @@ -93,10 +93,10 @@ fn main() -> Result<()> { Ok(()) } -fn validate(validation_command: Validation::ValidationCommand) -> Result<()> { +fn validate(validation_command: validation::ValidationCommand) -> Result<()> { let rt = tokio::runtime::Runtime::new()?; rt.block_on(async { - Validation::validate(validation_command).await + validation::validate(validation_command).await }) } diff --git a/src/agent/onefuzz-agent/src/Validation.rs b/src/agent/onefuzz-agent/src/validation.rs similarity index 50% rename from src/agent/onefuzz-agent/src/Validation.rs rename to src/agent/onefuzz-agent/src/validation.rs index 50fcbd0da5..05f0e2040a 100644 --- a/src/agent/onefuzz-agent/src/Validation.rs +++ b/src/agent/onefuzz-agent/src/validation.rs @@ -1,3 +1,5 @@ +use std::{path::PathBuf, collections::HashMap}; + use anyhow::{Context, Result}; use clap::{ArgAction, Parser}; @@ -9,6 +11,29 @@ pub enum ValidationCommand{ ShowDebuggerSnap } +#[derive(Parser, Debug)] +pub struct ValidationConfig { + pub seeds: PathBuf, + pub setup_folder: PathBuf, + pub target_exe: PathBuf, + #[arg(short = 'D', value_parser = parse_key_val::)] + pub target_env: Vec<(String, String)>, + pub target_options: Vec, +} + +fn parse_key_val(s: &str) -> Result<(T, U), Box> +where + T: std::str::FromStr, + T::Err: std::error::Error + Send + Sync + 'static, + U: std::str::FromStr, + U::Err: std::error::Error + Send + Sync + 'static, +{ + let pos = s + .find('=') + .ok_or_else(|| format!("invalid KEY=value: no `=` found in `{s}`"))?; + Ok((s[..pos].parse()?, s[pos + 1..].parse()?)) +} + pub async fn validate(validation_command: ValidationCommand) -> Result<()> { match validation_command { From cb646ce477f2f366dd6fc94a1c448b00fead22b0 Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Mon, 27 Mar 2023 10:33:14 -0700 Subject: [PATCH 03/13] refactoring --- src/agent/.rustfmt.toml | 3 +- src/agent/onefuzz-agent/src/main.rs | 11 ++-- src/agent/onefuzz-agent/src/setup.rs | 36 +++++++------ src/agent/onefuzz-agent/src/validation.rs | 62 ---------------------- src/agent/onefuzz-agent/src/validation2.rs | 62 ++++++++++++++++++++++ src/agent/onefuzz-agent/src/work.rs | 48 ++++++----------- src/agent/onefuzz/src/blob/url.rs | 12 ++++- 7 files changed, 116 insertions(+), 118 deletions(-) delete mode 100644 src/agent/onefuzz-agent/src/validation.rs create mode 100644 src/agent/onefuzz-agent/src/validation2.rs diff --git a/src/agent/.rustfmt.toml b/src/agent/.rustfmt.toml index c51666e8f4..dbce25e980 100644 --- a/src/agent/.rustfmt.toml +++ b/src/agent/.rustfmt.toml @@ -1 +1,2 @@ -edition = "2018" \ No newline at end of file +edition = "2018" +newline_style = "Native" \ No newline at end of file diff --git a/src/agent/onefuzz-agent/src/main.rs b/src/agent/onefuzz-agent/src/main.rs index b1defa30c5..f27f3c0503 100644 --- a/src/agent/onefuzz-agent/src/main.rs +++ b/src/agent/onefuzz-agent/src/main.rs @@ -40,7 +40,7 @@ pub mod panic; pub mod reboot; pub mod scheduler; pub mod setup; -pub mod validation; +pub mod validation2; pub mod work; pub mod worker; @@ -49,8 +49,7 @@ enum Opt { Run(RunOpt), #[clap(subcommand)] Debug(debug::DebugOpt), - #[clap(subcommand)] - Validate(validation::ValidationCommand), + Validate(validation2::Config), Licenses, Version, } @@ -93,11 +92,9 @@ fn main() -> Result<()> { Ok(()) } -fn validate(validation_command: validation::ValidationCommand) -> Result<()> { +fn validate(validation_command: validation2::Config) -> Result<()> { let rt = tokio::runtime::Runtime::new()?; - rt.block_on(async { - validation::validate(validation_command).await - }) + rt.block_on(async { validation2::validate(validation_command).await }) } fn version() { diff --git a/src/agent/onefuzz-agent/src/setup.rs b/src/agent/onefuzz-agent/src/setup.rs index 0362ab1ea6..6504186f5c 100644 --- a/src/agent/onefuzz-agent/src/setup.rs +++ b/src/agent/onefuzz-agent/src/setup.rs @@ -8,6 +8,7 @@ use std::time::Duration; use anyhow::{Context, Result}; use downcast_rs::Downcast; use onefuzz::az_copy; +use onefuzz::blob::BlobContainerUrl; use onefuzz::process::Output; use tokio::fs; use tokio::process::Command; @@ -80,10 +81,22 @@ impl SetupRunner { onefuzz::fs::set_executable(&setup_dir).await?; // Create setup container directory symlinks for tasks. - for work_unit in &work_set.work_units { - create_setup_symlink(&setup_dir, work_unit, self.machine_id).await?; + let working_dirs = work_set + .work_units + .iter() + .map(|w| w.working_dir(self.machine_id)) + .collect::>() + .into_iter() + .collect::>>()?; + + for work_dir in working_dirs { + create_setup_symlink(&setup_dir, work_dir).await?; } + Self::run_setup_script(setup_dir).await + } + + pub async fn run_setup_script(setup_dir: PathBuf) -> std::result::Result, anyhow::Error> { // Run setup script, if any. let setup_script = SetupScript::new(setup_dir).await?; @@ -111,7 +124,6 @@ impl SetupRunner { Some(output) } else { info!("no setup script to run"); - None }; @@ -119,16 +131,14 @@ impl SetupRunner { } } + + #[cfg(target_family = "windows")] -async fn create_setup_symlink( - setup_dir: &Path, - work_unit: &WorkUnit, - machine_id: Uuid, -) -> Result<()> { +async fn create_setup_symlink(setup_dir: &Path, working_dir: impl AsRef) -> Result<()> { use std::os::windows::fs::symlink_dir; use tokio::task::spawn_blocking; - let working_dir = work_unit.working_dir(machine_id)?; + let working_dir = working_dir.as_ref(); let create_work_dir = fs::create_dir_all(&working_dir).await.with_context(|| { format!( @@ -162,14 +172,10 @@ async fn create_setup_symlink( } #[cfg(target_family = "unix")] -async fn create_setup_symlink( - setup_dir: &Path, - work_unit: &WorkUnit, - machine_id: Uuid, -) -> Result<()> { +async fn create_setup_symlink(setup_dir: &Path, working_dir: impl AsRef) -> Result<()> { use tokio::fs::symlink; - let working_dir = work_unit.working_dir(machine_id)?; + let working_dir = working_dir.as_ref(); tokio::fs::create_dir_all(&working_dir) .await diff --git a/src/agent/onefuzz-agent/src/validation.rs b/src/agent/onefuzz-agent/src/validation.rs deleted file mode 100644 index 05f0e2040a..0000000000 --- a/src/agent/onefuzz-agent/src/validation.rs +++ /dev/null @@ -1,62 +0,0 @@ -use std::{path::PathBuf, collections::HashMap}; - -use anyhow::{Context, Result}; -use clap::{ArgAction, Parser}; - -#[derive(Parser, Debug)] -#[clap(rename_all = "snake_case")] -pub enum ValidationCommand{ - ValidateSetup, - ValidateLibfuzzer, - ShowDebuggerSnap -} - -#[derive(Parser, Debug)] -pub struct ValidationConfig { - pub seeds: PathBuf, - pub setup_folder: PathBuf, - pub target_exe: PathBuf, - #[arg(short = 'D', value_parser = parse_key_val::)] - pub target_env: Vec<(String, String)>, - pub target_options: Vec, -} - -fn parse_key_val(s: &str) -> Result<(T, U), Box> -where - T: std::str::FromStr, - T::Err: std::error::Error + Send + Sync + 'static, - U: std::str::FromStr, - U::Err: std::error::Error + Send + Sync + 'static, -{ - let pos = s - .find('=') - .ok_or_else(|| format!("invalid KEY=value: no `=` found in `{s}`"))?; - Ok((s[..pos].parse()?, s[pos + 1..].parse()?)) -} - - -pub async fn validate(validation_command: ValidationCommand) -> Result<()> { - match validation_command { - ValidationCommand::ValidateSetup => { - validate_setup().await - }, - ValidationCommand::ValidateLibfuzzer => { - validate_libfuzzer().await - }, - ValidationCommand::ShowDebuggerSnap => { - show_debugger_snap().await - } - } -} - -async fn show_debugger_snap() -> Result<()> { - todo!() -} - -async fn validate_libfuzzer() -> Result<()> { - todo!() -} - -async fn validate_setup() -> Result<()> { - todo!() -} \ No newline at end of file diff --git a/src/agent/onefuzz-agent/src/validation2.rs b/src/agent/onefuzz-agent/src/validation2.rs new file mode 100644 index 0000000000..c3496369f1 --- /dev/null +++ b/src/agent/onefuzz-agent/src/validation2.rs @@ -0,0 +1,62 @@ +use std::{collections::HashMap, path::PathBuf}; + +use anyhow::{Context, Result}; +use clap::{ArgAction, Parser}; +use crate::setup::SetupRunner; +use uuid::Uuid; + + +#[derive(Parser, Debug)] +#[clap(rename_all = "snake_case")] +pub enum ValidationCommand { + ValidateSetup, + ValidateLibfuzzer, + ShowDebuggerSnap, +} + +#[derive(Parser, Debug)] +#[clap(rename_all = "snake_case")] +pub struct Config { + pub config_path: PathBuf, + #[clap(subcommand)] + pub command: ValidationCommand, +} + +#[derive(Debug, Deserialize)] +pub struct ValidationConfig { + pub seeds: PathBuf, + pub setup_folder: PathBuf, + pub target_exe: PathBuf, + pub target_env: Vec<(String, String)>, + pub target_options: Vec, +} + + +pub async fn validate(config: Config) -> Result<()> { + let validation_config = serde_json::from_str::( + &std::fs::read_to_string(&config.config_path) + .context("unable to read config file")?, + )?; + + + match config.command { + ValidationCommand::ValidateSetup => validate_setup(validation_config).await, + ValidationCommand::ValidateLibfuzzer => validate_libfuzzer().await, + ValidationCommand::ShowDebuggerSnap => show_debugger_snap().await, + } +} + +async fn show_debugger_snap() -> Result<()> { + Ok(()) +} + +async fn validate_libfuzzer() -> Result<()> { + Ok(()) +} + +async fn validate_setup(config: ValidationConfig) -> Result<()> { + + let result = SetupRunner::run_setup_script(config.setup_folder).await?; + // SetupRunner::run_setup(&config.se, &config.extra_folder).await?; + Ok(()) +} diff --git a/src/agent/onefuzz-agent/src/work.rs b/src/agent/onefuzz-agent/src/work.rs index 0dfef625d2..f2a99938d8 100644 --- a/src/agent/onefuzz-agent/src/work.rs +++ b/src/agent/onefuzz-agent/src/work.rs @@ -84,29 +84,21 @@ impl WorkSet { Ok(()) } + pub fn get_root_folder(&self) -> Result { + onefuzz::fs::onefuzz_root().map(|root| root.join("blob-containers")) + } + pub fn setup_dir(&self) -> Result { - let setup_dir = self - .setup_url - .account() - .ok_or_else(|| anyhow!("Invalid container Url"))?; - Ok(onefuzz::fs::onefuzz_root()? - .join("blob-containers") - .join(setup_dir)) + let root = self.get_root_folder()?; + self.setup_url.as_path(root.join("blob-containers")) } pub fn extra_dir(&self) -> Result> { - if let Some(extra_url) = &self.extra_url { - let extra_dir = extra_url - .account() - .ok_or_else(|| anyhow!("Invalid container Url"))?; - Ok(Some( - onefuzz::fs::onefuzz_root()? - .join("blob-containers") - .join(extra_dir), - )) - } else { - Ok(None) - } + let root = self.get_root_folder()?; + self.extra_url + .as_ref() + .map(|url| url.as_path(root.join("blob-containers"))) + .transpose() } } @@ -253,7 +245,6 @@ impl WorkQueue { #[cfg(test)] pub mod double; - #[cfg(test)] pub mod test { @@ -262,8 +253,7 @@ pub mod test { use serde_json; #[test] - fn test(){ - + fn test() { let w1 = WorkSet { reboot: true, setup_url: BlobContainerUrl::BlobContainer( @@ -276,27 +266,21 @@ pub mod test { let w2 = WorkSet { reboot: true, - setup_url: BlobContainerUrl::Path( - PathBuf::from("c:\\test\\test"), - ), + setup_url: BlobContainerUrl::Path(PathBuf::from("c:\\test\\test")), extra_url: None, script: true, - work_units: vec![] + work_units: vec![], }; - println!("{}", serde_json::to_string(&w1).unwrap()) ; + println!("{}", serde_json::to_string(&w1).unwrap()); let w2_json = serde_json::to_string(&w2).unwrap(); - println!("{}", w2_json) ; + println!("{}", w2_json); let w3: WorkSet = serde_json::from_str(&w2_json).unwrap(); // asse println!("{:?}", w3); - - - - } } diff --git a/src/agent/onefuzz/src/blob/url.rs b/src/agent/onefuzz/src/blob/url.rs index 6e057e381b..961e9f7af6 100644 --- a/src/agent/onefuzz/src/blob/url.rs +++ b/src/agent/onefuzz/src/blob/url.rs @@ -1,7 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -use std::{fmt, path::PathBuf}; +use std::{ + fmt, + path::{Path, PathBuf}, +}; use anyhow::Result; use reqwest::Url; @@ -187,6 +190,13 @@ impl BlobContainerUrl { Self::Path(p) => BlobUrl::LocalFile(p.join(name.as_ref())), } } + + pub fn as_path(&self, prefix: impl AsRef) -> Result { + let dir = self + .account() + .ok_or_else(|| anyhow!("Invalid container Url"))?; + Ok(prefix.as_ref().join(dir)) + } } impl fmt::Debug for BlobContainerUrl { From 11e594ab870340e8a339d48a69804b54a2e27775 Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Mon, 27 Mar 2023 11:19:36 -0700 Subject: [PATCH 04/13] adding verification code --- src/agent/onefuzz-agent/src/main.rs | 8 +-- src/agent/onefuzz-agent/src/setup.rs | 7 +- src/agent/onefuzz-agent/src/validation2.rs | 62 ------------------ src/agent/onefuzz-agent/src/validations.rs | 76 ++++++++++++++++++++++ 4 files changed, 83 insertions(+), 70 deletions(-) delete mode 100644 src/agent/onefuzz-agent/src/validation2.rs create mode 100644 src/agent/onefuzz-agent/src/validations.rs diff --git a/src/agent/onefuzz-agent/src/main.rs b/src/agent/onefuzz-agent/src/main.rs index f27f3c0503..cb17943d9e 100644 --- a/src/agent/onefuzz-agent/src/main.rs +++ b/src/agent/onefuzz-agent/src/main.rs @@ -40,7 +40,7 @@ pub mod panic; pub mod reboot; pub mod scheduler; pub mod setup; -pub mod validation2; +pub mod validations; pub mod work; pub mod worker; @@ -49,7 +49,7 @@ enum Opt { Run(RunOpt), #[clap(subcommand)] Debug(debug::DebugOpt), - Validate(validation2::Config), + Validate(validations::Config), Licenses, Version, } @@ -92,9 +92,9 @@ fn main() -> Result<()> { Ok(()) } -fn validate(validation_command: validation2::Config) -> Result<()> { +fn validate(validation_command: validations::Config) -> Result<()> { let rt = tokio::runtime::Runtime::new()?; - rt.block_on(async { validation2::validate(validation_command).await }) + rt.block_on(async { validations::validate(validation_command).await }) } fn version() { diff --git a/src/agent/onefuzz-agent/src/setup.rs b/src/agent/onefuzz-agent/src/setup.rs index 6504186f5c..2536b4ca05 100644 --- a/src/agent/onefuzz-agent/src/setup.rs +++ b/src/agent/onefuzz-agent/src/setup.rs @@ -8,7 +8,6 @@ use std::time::Duration; use anyhow::{Context, Result}; use downcast_rs::Downcast; use onefuzz::az_copy; -use onefuzz::blob::BlobContainerUrl; use onefuzz::process::Output; use tokio::fs; use tokio::process::Command; @@ -96,7 +95,9 @@ impl SetupRunner { Self::run_setup_script(setup_dir).await } - pub async fn run_setup_script(setup_dir: PathBuf) -> std::result::Result, anyhow::Error> { + pub async fn run_setup_script( + setup_dir: PathBuf, + ) -> std::result::Result, anyhow::Error> { // Run setup script, if any. let setup_script = SetupScript::new(setup_dir).await?; @@ -131,8 +132,6 @@ impl SetupRunner { } } - - #[cfg(target_family = "windows")] async fn create_setup_symlink(setup_dir: &Path, working_dir: impl AsRef) -> Result<()> { use std::os::windows::fs::symlink_dir; diff --git a/src/agent/onefuzz-agent/src/validation2.rs b/src/agent/onefuzz-agent/src/validation2.rs deleted file mode 100644 index c3496369f1..0000000000 --- a/src/agent/onefuzz-agent/src/validation2.rs +++ /dev/null @@ -1,62 +0,0 @@ -use std::{collections::HashMap, path::PathBuf}; - -use anyhow::{Context, Result}; -use clap::{ArgAction, Parser}; -use crate::setup::SetupRunner; -use uuid::Uuid; - - -#[derive(Parser, Debug)] -#[clap(rename_all = "snake_case")] -pub enum ValidationCommand { - ValidateSetup, - ValidateLibfuzzer, - ShowDebuggerSnap, -} - -#[derive(Parser, Debug)] -#[clap(rename_all = "snake_case")] -pub struct Config { - pub config_path: PathBuf, - #[clap(subcommand)] - pub command: ValidationCommand, -} - -#[derive(Debug, Deserialize)] -pub struct ValidationConfig { - pub seeds: PathBuf, - pub setup_folder: PathBuf, - pub target_exe: PathBuf, - pub target_env: Vec<(String, String)>, - pub target_options: Vec, -} - - -pub async fn validate(config: Config) -> Result<()> { - let validation_config = serde_json::from_str::( - &std::fs::read_to_string(&config.config_path) - .context("unable to read config file")?, - )?; - - - match config.command { - ValidationCommand::ValidateSetup => validate_setup(validation_config).await, - ValidationCommand::ValidateLibfuzzer => validate_libfuzzer().await, - ValidationCommand::ShowDebuggerSnap => show_debugger_snap().await, - } -} - -async fn show_debugger_snap() -> Result<()> { - Ok(()) -} - -async fn validate_libfuzzer() -> Result<()> { - Ok(()) -} - -async fn validate_setup(config: ValidationConfig) -> Result<()> { - - let result = SetupRunner::run_setup_script(config.setup_folder).await?; - // SetupRunner::run_setup(&config.se, &config.extra_folder).await?; - Ok(()) -} diff --git a/src/agent/onefuzz-agent/src/validations.rs b/src/agent/onefuzz-agent/src/validations.rs new file mode 100644 index 0000000000..42cf164445 --- /dev/null +++ b/src/agent/onefuzz-agent/src/validations.rs @@ -0,0 +1,76 @@ +use std::{collections::HashMap, path::PathBuf}; + +use crate::setup::SetupRunner; +use anyhow::{Context, Result}; +use clap::Parser; +use onefuzz::{libfuzzer::LibFuzzer, machine_id::MachineIdentity}; +use uuid::Uuid; + +#[derive(Parser, Debug)] +#[clap(rename_all = "snake_case")] +pub enum ValidationCommand { + ValidateSetup, + ValidateLibfuzzer, +} + +#[derive(Parser, Debug)] +#[clap(rename_all = "snake_case")] +pub struct Config { + pub config_path: PathBuf, + #[clap(subcommand)] + pub command: ValidationCommand, +} + +#[derive(Debug, Deserialize)] +pub struct ValidationConfig { + pub seeds: PathBuf, + pub setup_folder: PathBuf, + pub target_exe: PathBuf, + pub target_env: HashMap, + pub target_options: Vec, +} + +pub async fn validate(config: Config) -> Result<()> { + let validation_config = serde_json::from_str::( + &std::fs::read_to_string(&config.config_path).context("unable to read config file")?, + )?; + + match config.command { + ValidationCommand::ValidateSetup => validate_setup(validation_config).await, + ValidationCommand::ValidateLibfuzzer => validate_libfuzzer(validation_config).await, + } +} + +async fn validate_libfuzzer(config: ValidationConfig) -> Result<()> { + let libfuzzer = LibFuzzer::new( + &config.target_exe, + config.target_options.clone(), + config.target_env.clone(), + config.setup_folder.clone(), + None::<&PathBuf>, + MachineIdentity { + machine_id: Uuid::nil(), + machine_name: "".to_string(), + scaleset_name: None, + }, + ); + + libfuzzer.verify(true, Some(vec![config.seeds])).await?; + Ok(()) +} + +async fn validate_setup(config: ValidationConfig) -> Result<()> { + let output = SetupRunner::run_setup_script(config.setup_folder).await?; + match output { + Some(output) => { + if !output.exit_status.success { + let error = "error running target setup script".to_owned(); + bail!("{}", error); + } + } + None => { + println!("no setup script to run") + } + } + Ok(()) +} From 8c9c8b8463ce88f36d2a4758af880d436c8fd0e4 Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Mon, 27 Mar 2023 13:22:06 -0700 Subject: [PATCH 05/13] remove unused test --- src/agent/onefuzz-agent/src/validations.rs | 2 +- src/agent/onefuzz-agent/src/work.rs | 42 +--------------------- 2 files changed, 2 insertions(+), 42 deletions(-) diff --git a/src/agent/onefuzz-agent/src/validations.rs b/src/agent/onefuzz-agent/src/validations.rs index 42cf164445..c6d5f46412 100644 --- a/src/agent/onefuzz-agent/src/validations.rs +++ b/src/agent/onefuzz-agent/src/validations.rs @@ -21,7 +21,7 @@ pub struct Config { pub command: ValidationCommand, } -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, Clone)] pub struct ValidationConfig { pub seeds: PathBuf, pub setup_folder: PathBuf, diff --git a/src/agent/onefuzz-agent/src/work.rs b/src/agent/onefuzz-agent/src/work.rs index f2a99938d8..0716964e70 100644 --- a/src/agent/onefuzz-agent/src/work.rs +++ b/src/agent/onefuzz-agent/src/work.rs @@ -243,44 +243,4 @@ impl WorkQueue { } #[cfg(test)] -pub mod double; - -#[cfg(test)] -pub mod test { - - use super::*; - use reqwest::Url; - use serde_json; - - #[test] - fn test() { - let w1 = WorkSet { - reboot: true, - setup_url: BlobContainerUrl::BlobContainer( - Url::parse("https://onefuzz-test.blob.core.windows.net/containers/1?sv=2019-12-12&sr=c&sig=123&se=2020-12-31T00%3A00%3A00Z&sp=r").unwrap(), - ), - extra_url: None, - script: true, - work_units: vec![] - }; - - let w2 = WorkSet { - reboot: true, - setup_url: BlobContainerUrl::Path(PathBuf::from("c:\\test\\test")), - extra_url: None, - script: true, - work_units: vec![], - }; - - println!("{}", serde_json::to_string(&w1).unwrap()); - - let w2_json = serde_json::to_string(&w2).unwrap(); - println!("{}", w2_json); - - let w3: WorkSet = serde_json::from_str(&w2_json).unwrap(); - - // asse - - println!("{:?}", w3); - } -} +pub mod double; \ No newline at end of file From a520d322880ff8ef1ff85073cdac0afd22f7686b Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Mon, 27 Mar 2023 13:54:21 -0700 Subject: [PATCH 06/13] format --- src/agent/onefuzz-agent/src/work.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/agent/onefuzz-agent/src/work.rs b/src/agent/onefuzz-agent/src/work.rs index 0716964e70..617bb298ba 100644 --- a/src/agent/onefuzz-agent/src/work.rs +++ b/src/agent/onefuzz-agent/src/work.rs @@ -243,4 +243,4 @@ impl WorkQueue { } #[cfg(test)] -pub mod double; \ No newline at end of file +pub mod double; From 81f750ced51099ce4807137fc1374b2769bc260b Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Tue, 28 Mar 2023 09:21:14 -0700 Subject: [PATCH 07/13] update dependencies --- src/agent/Cargo.lock | 1 - src/agent/onefuzz-agent/Cargo.toml | 1 - src/ci/check-dependencies.sh | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock index 6762b19b16..d1b7f2d566 100644 --- a/src/agent/Cargo.lock +++ b/src/agent/Cargo.lock @@ -1987,7 +1987,6 @@ dependencies = [ "log", "nix", "onefuzz", - "onefuzz-task", "onefuzz-telemetry", "reqwest", "reqwest-retry", diff --git a/src/agent/onefuzz-agent/Cargo.toml b/src/agent/onefuzz-agent/Cargo.toml index 884f8a7ee4..fd7acd9ace 100644 --- a/src/agent/onefuzz-agent/Cargo.toml +++ b/src/agent/onefuzz-agent/Cargo.toml @@ -14,7 +14,6 @@ env_logger = "0.10" futures = "0.3" log = "0.4" onefuzz = { path = "../onefuzz" } -onefuzz-task = { path = "../onefuzz-task" } reqwest = { version = "0.11", features = [ "json", "stream", diff --git a/src/ci/check-dependencies.sh b/src/ci/check-dependencies.sh index 4214e4dcc4..965fe90bdf 100755 --- a/src/ci/check-dependencies.sh +++ b/src/ci/check-dependencies.sh @@ -96,6 +96,7 @@ apphelp.dll bcrypt.dll bcryptPrimitives.dll crypt32.dll +dbghelp.dll msvcrt.dll ntdll.dll sechost.dll From 702ecadbd956c57267e4ac90741b422cb8c171dd Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Wed, 29 Mar 2023 11:43:30 -0700 Subject: [PATCH 08/13] adding a command to get the loading logs --- docs/unmanaged-nodes.md | 8 +++++ src/agent/Cargo.lock | 1 + src/agent/dynamic-library/src/linux.rs | 4 +++ src/agent/dynamic-library/src/windows.rs | 23 ++++++++++---- src/agent/onefuzz-agent/Cargo.toml | 1 + src/agent/onefuzz-agent/src/validations.rs | 35 ++++++++++++++++++++++ src/agent/onefuzz/src/libfuzzer.rs | 2 +- 7 files changed, 67 insertions(+), 7 deletions(-) diff --git a/docs/unmanaged-nodes.md b/docs/unmanaged-nodes.md index db87f307d5..1861ed09ab 100644 --- a/docs/unmanaged-nodes.md +++ b/docs/unmanaged-nodes.md @@ -142,3 +142,11 @@ linux ``` docker run --it --rm --entrypoint bash ``` + +### mount a local folder in the container + +docker allows you to [mount](https://docs.docker.com/storage/bind-mounts/#mount-into-a-non-empty-directory-on-the-container) a local folder when running a container + +``` +docker run -it --rm --mount type=bind,source=,target= +``` \ No newline at end of file diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock index d1b7f2d566..7ed58fdada 100644 --- a/src/agent/Cargo.lock +++ b/src/agent/Cargo.lock @@ -1981,6 +1981,7 @@ dependencies = [ "backtrace", "clap", "downcast-rs", + "dynamic-library", "env_logger", "futures", "ipc-channel", diff --git a/src/agent/dynamic-library/src/linux.rs b/src/agent/dynamic-library/src/linux.rs index 0556088ff8..7ac04e076c 100644 --- a/src/agent/dynamic-library/src/linux.rs +++ b/src/agent/dynamic-library/src/linux.rs @@ -37,6 +37,10 @@ pub fn find_missing(mut cmd: Command) -> Result, Ok(logs.missing()) } +pub fn get_logs(cmd: Command) -> Result, io::Error> { + todo!() +} + // Compute the `LD_LIBRARY_PATH` value that a `Command` sets, if any. // // If the command either inherits or unsets the variable, returns `None`. diff --git a/src/agent/dynamic-library/src/windows.rs b/src/agent/dynamic-library/src/windows.rs index 16852c36f4..137d10ea03 100644 --- a/src/agent/dynamic-library/src/windows.rs +++ b/src/agent/dynamic-library/src/windows.rs @@ -27,17 +27,28 @@ pub enum CheckDynamicLibrariesError { pub fn find_missing( cmd: Command, ) -> Result, CheckDynamicLibrariesError> { - let image_file = ImageFile::new(cmd.get_program())?; - let _sls = image_file.show_loader_snaps()?; + let mut handler = LoaderSnapsHandler::default(); + setup_debugger(cmd, &mut handler)?; + Ok(handler.missing_libraries()) +} +pub fn get_logs(cmd: Command) -> Result, CheckDynamicLibrariesError> { let mut handler = LoaderSnapsHandler::default(); + setup_debugger(cmd, &mut handler)?; + Ok(handler.debug_strings) +} +fn setup_debugger( + cmd: Command, + handler: &mut LoaderSnapsHandler, +) -> Result<(), CheckDynamicLibrariesError> { + let image_file = ImageFile::new(cmd.get_program())?; + let _sls = image_file.show_loader_snaps()?; let (mut dbg, _child) = - Debugger::init(cmd, &mut handler).map_err(CheckDynamicLibrariesError::Debugger)?; - + Debugger::init(cmd, handler).map_err(CheckDynamicLibrariesError::Debugger)?; while !dbg.target().exited() { if !dbg - .process_event(&mut handler, 1000) + .process_event(handler, 1000) .map_err(CheckDynamicLibrariesError::Debugger)? { break; @@ -47,7 +58,7 @@ pub fn find_missing( .map_err(CheckDynamicLibrariesError::Debugger)?; } - Ok(handler.missing_libraries()) + Ok(()) } #[derive(Debug, Error)] diff --git a/src/agent/onefuzz-agent/Cargo.toml b/src/agent/onefuzz-agent/Cargo.toml index fd7acd9ace..943ade7fa4 100644 --- a/src/agent/onefuzz-agent/Cargo.toml +++ b/src/agent/onefuzz-agent/Cargo.toml @@ -30,6 +30,7 @@ reqwest-retry = { path = "../reqwest-retry" } onefuzz-telemetry = { path = "../onefuzz-telemetry" } backtrace = "0.3" ipc-channel = { git = "https://github.com/servo/ipc-channel", rev = "7f432aa" } +dynamic-library = {path = "../dynamic-library" } [target.'cfg(target_family = "unix")'.dependencies] diff --git a/src/agent/onefuzz-agent/src/validations.rs b/src/agent/onefuzz-agent/src/validations.rs index c6d5f46412..6988767e62 100644 --- a/src/agent/onefuzz-agent/src/validations.rs +++ b/src/agent/onefuzz-agent/src/validations.rs @@ -11,6 +11,7 @@ use uuid::Uuid; pub enum ValidationCommand { ValidateSetup, ValidateLibfuzzer, + ExecutionLog, } #[derive(Parser, Debug)] @@ -38,6 +39,7 @@ pub async fn validate(config: Config) -> Result<()> { match config.command { ValidationCommand::ValidateSetup => validate_setup(validation_config).await, ValidationCommand::ValidateLibfuzzer => validate_libfuzzer(validation_config).await, + ValidationCommand::ExecutionLog => get_logs(validation_config).await, } } @@ -74,3 +76,36 @@ async fn validate_setup(config: ValidationConfig) -> Result<()> { } Ok(()) } + +async fn get_logs(config: ValidationConfig) -> Result<()> { + let libfuzzer = LibFuzzer::new( + &config.target_exe, + config.target_options.clone(), + config.target_env.clone(), + config.setup_folder.clone(), + None::<&PathBuf>, + MachineIdentity { + machine_id: Uuid::nil(), + machine_name: "".to_string(), + scaleset_name: None, + }, + ); + + let cmd = libfuzzer.build_std_command(None, None, None).await?; + + // #[cfg(target_os = "linux")] + // let blocking = move || dynamic_library::linux::find_missing(cmd); + + #[cfg(target_os = "windows")] + let logs = dynamic_library::windows::get_logs(cmd)?; + + for log in logs { + println!("{log:x?}"); + } + + Ok(()) +} + +// https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/extra-tools#installation-directory +// ./gflags /i C:\setup\Xbox.Shell.OneStoreServices.FuzzerTest.exe +sls +// ./cdb -c "q" C:\setup\Xbox.Shell.OneStoreServices.FuzzerTest.exe diff --git a/src/agent/onefuzz/src/libfuzzer.rs b/src/agent/onefuzz/src/libfuzzer.rs index ef13bfa7bf..c5468b1d3c 100644 --- a/src/agent/onefuzz/src/libfuzzer.rs +++ b/src/agent/onefuzz/src/libfuzzer.rs @@ -84,7 +84,7 @@ impl LibFuzzer { } // Build a non-async `Command`. - async fn build_std_command( + pub async fn build_std_command( &self, fault_dir: Option<&Path>, corpus_dir: Option<&Path>, From 00347b55bd97b9a47f1eee74e8db0bf9b4b7aae8 Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Thu, 30 Mar 2023 11:30:34 -0700 Subject: [PATCH 09/13] add print logs for linux --- src/agent/dynamic-library/src/linux.rs | 30 ++++++++++++++++------ src/agent/onefuzz-agent/src/validations.rs | 24 ++++++++++++----- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/agent/dynamic-library/src/linux.rs b/src/agent/dynamic-library/src/linux.rs index 7ac04e076c..964f423b28 100644 --- a/src/agent/dynamic-library/src/linux.rs +++ b/src/agent/dynamic-library/src/linux.rs @@ -4,7 +4,7 @@ use std::collections::{HashMap, HashSet}; use std::ffi::OsStr; -use std::io; +use std::io::{self}; use std::path::Path; use std::process::Command; @@ -37,8 +37,17 @@ pub fn find_missing(mut cmd: Command) -> Result, Ok(logs.missing()) } -pub fn get_logs(cmd: Command) -> Result, io::Error> { - todo!() +pub fn get_linked_library_logs<'a>(cmd: &Command) -> Result { + let library_path = explicit_library_path(cmd); + let output = LinkedDynamicLibraries::run(cmd.get_program(), library_path)?; + Ok(output) +} + +pub fn get_loaded_libraries_logs<'a>(cmd: Command) -> Result { + let mut cmd = Command::from(cmd); + cmd.env("LD_DEBUG", "libs"); + let output = cmd.output()?; + Ok(output) } // Compute the `LD_LIBRARY_PATH` value that a `Command` sets, if any. @@ -257,19 +266,24 @@ impl LinkedDynamicLibraries { module: impl AsRef, library_path: Option<&OsStr>, ) -> Result { + let output = Self::run(module, library_path)?; + let linked = Self::parse(&*output.stdout); + Ok(linked) + } + + pub fn run( + module: impl AsRef, + library_path: Option<&OsStr>, + ) -> Result { let mut cmd = Command::new("ldd"); cmd.arg(module); - if let Some(library_path) = library_path { cmd.env(LD_LIBRARY_PATH, library_path); } else { cmd.env_remove(LD_LIBRARY_PATH); } - let output = cmd.output()?; - let linked = Self::parse(&*output.stdout); - - Ok(linked) + Ok(output) } pub fn parse(readable: R) -> Self { diff --git a/src/agent/onefuzz-agent/src/validations.rs b/src/agent/onefuzz-agent/src/validations.rs index 6988767e62..4e1642126e 100644 --- a/src/agent/onefuzz-agent/src/validations.rs +++ b/src/agent/onefuzz-agent/src/validations.rs @@ -90,16 +90,28 @@ async fn get_logs(config: ValidationConfig) -> Result<()> { scaleset_name: None, }, ); - let cmd = libfuzzer.build_std_command(None, None, None).await?; + print_logs(cmd)?; + Ok(()) +} - // #[cfg(target_os = "linux")] - // let blocking = move || dynamic_library::linux::find_missing(cmd); - - #[cfg(target_os = "windows")] +#[cfg(target_os = "windows")] +fn print_logs(cmd: std::process::Command) -> Result<(), anyhow::Error> { let logs = dynamic_library::windows::get_logs(cmd)?; + Ok(for log in logs { + println!("{log:x?}"); + }) +} + +#[cfg(target_os = "linux")] +fn print_logs(cmd: std::process::Command) -> Result<(), anyhow::Error> { + let logs = dynamic_library::linux::get_linked_library_logs(&cmd)?; + for log in logs.stdout { + println!("{log:x?}"); + } - for log in logs { + let logs2 = dynamic_library::linux::get_loaded_libraries_logs(cmd)?; + for log in logs2.stderr { println!("{log:x?}"); } From aee6fb67a015ac17087dfccbb937217590eeb3ef Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Thu, 30 Mar 2023 12:29:46 -0700 Subject: [PATCH 10/13] clippy fix --- src/agent/dynamic-library/src/linux.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/agent/dynamic-library/src/linux.rs b/src/agent/dynamic-library/src/linux.rs index 964f423b28..f438e3fa58 100644 --- a/src/agent/dynamic-library/src/linux.rs +++ b/src/agent/dynamic-library/src/linux.rs @@ -37,14 +37,14 @@ pub fn find_missing(mut cmd: Command) -> Result, Ok(logs.missing()) } -pub fn get_linked_library_logs<'a>(cmd: &Command) -> Result { +pub fn get_linked_library_logs(cmd: &Command) -> Result { let library_path = explicit_library_path(cmd); let output = LinkedDynamicLibraries::run(cmd.get_program(), library_path)?; Ok(output) } -pub fn get_loaded_libraries_logs<'a>(cmd: Command) -> Result { - let mut cmd = Command::from(cmd); +pub fn get_loaded_libraries_logs(cmd: Command) -> Result { + let mut cmd = cmd; cmd.env("LD_DEBUG", "libs"); let output = cmd.output()?; Ok(output) From 763304a137aeb259b242546aa4d75ca85bd4f6a6 Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Thu, 30 Mar 2023 12:50:24 -0700 Subject: [PATCH 11/13] clippy on windows --- src/agent/onefuzz-agent/src/validations.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/agent/onefuzz-agent/src/validations.rs b/src/agent/onefuzz-agent/src/validations.rs index 4e1642126e..866aa91882 100644 --- a/src/agent/onefuzz-agent/src/validations.rs +++ b/src/agent/onefuzz-agent/src/validations.rs @@ -98,9 +98,11 @@ async fn get_logs(config: ValidationConfig) -> Result<()> { #[cfg(target_os = "windows")] fn print_logs(cmd: std::process::Command) -> Result<(), anyhow::Error> { let logs = dynamic_library::windows::get_logs(cmd)?; - Ok(for log in logs { + for log in logs { println!("{log:x?}"); - }) + } + + Ok(()) } #[cfg(target_os = "linux")] From f25ec00dc48e1b358fd381c301baeffc990fb0e7 Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Thu, 30 Mar 2023 18:42:54 -0700 Subject: [PATCH 12/13] renaming stuff --- src/agent/onefuzz-agent/src/main.rs | 5 +- src/agent/onefuzz-agent/src/setup.rs | 2 +- src/agent/onefuzz-agent/src/validations.rs | 90 +++++++++++++--------- 3 files changed, 59 insertions(+), 38 deletions(-) diff --git a/src/agent/onefuzz-agent/src/main.rs b/src/agent/onefuzz-agent/src/main.rs index cb17943d9e..32df2c2614 100644 --- a/src/agent/onefuzz-agent/src/main.rs +++ b/src/agent/onefuzz-agent/src/main.rs @@ -49,7 +49,8 @@ enum Opt { Run(RunOpt), #[clap(subcommand)] Debug(debug::DebugOpt), - Validate(validations::Config), + #[clap(subcommand)] + Validate(validations::ValidationCommand), Licenses, Version, } @@ -92,7 +93,7 @@ fn main() -> Result<()> { Ok(()) } -fn validate(validation_command: validations::Config) -> Result<()> { +fn validate(validation_command: validations::ValidationCommand) -> Result<()> { let rt = tokio::runtime::Runtime::new()?; rt.block_on(async { validations::validate(validation_command).await }) } diff --git a/src/agent/onefuzz-agent/src/setup.rs b/src/agent/onefuzz-agent/src/setup.rs index 2536b4ca05..60d6296dad 100644 --- a/src/agent/onefuzz-agent/src/setup.rs +++ b/src/agent/onefuzz-agent/src/setup.rs @@ -96,7 +96,7 @@ impl SetupRunner { } pub async fn run_setup_script( - setup_dir: PathBuf, + setup_dir: impl AsRef, ) -> std::result::Result, anyhow::Error> { // Run setup script, if any. let setup_script = SetupScript::new(setup_dir).await?; diff --git a/src/agent/onefuzz-agent/src/validations.rs b/src/agent/onefuzz-agent/src/validations.rs index 866aa91882..7b0ce2438a 100644 --- a/src/agent/onefuzz-agent/src/validations.rs +++ b/src/agent/onefuzz-agent/src/validations.rs @@ -1,7 +1,7 @@ -use std::{collections::HashMap, path::PathBuf}; +use std::path::{Path, PathBuf}; use crate::setup::SetupRunner; -use anyhow::{Context, Result}; +use anyhow::Result; use clap::Parser; use onefuzz::{libfuzzer::LibFuzzer, machine_id::MachineIdentity}; use uuid::Uuid; @@ -9,37 +9,54 @@ use uuid::Uuid; #[derive(Parser, Debug)] #[clap(rename_all = "snake_case")] pub enum ValidationCommand { - ValidateSetup, - ValidateLibfuzzer, - ExecutionLog, + /// Run the setup script + RunSetup { setup_folder: PathBuf }, + /// Validate the libfuzzer target + ValidateLibfuzzer(ValidationConfig), + /// Get the execution logs to debug loading issues + ExecutionLog(ValidationConfig), } -#[derive(Parser, Debug)] -#[clap(rename_all = "snake_case")] -pub struct Config { - pub config_path: PathBuf, - #[clap(subcommand)] - pub command: ValidationCommand, +fn parse_key_val( + s: &str, +) -> Result<(T, U), Box> +where + T: std::str::FromStr, + T::Err: std::error::Error + Send + Sync + 'static, + U: std::str::FromStr, + U::Err: std::error::Error + Send + Sync + 'static, +{ + let pos = s + .find('=') + .ok_or_else(|| format!("invalid KEY=value: no `=` found in `{s}`"))?; + + println!("******** pos: {}", pos); + + Ok((s[..pos].parse()?, s[pos + 1..].parse()?)) } -#[derive(Debug, Deserialize, Clone)] +#[derive(Parser, Debug, Deserialize)] +#[clap(rename_all = "snake_case")] pub struct ValidationConfig { - pub seeds: PathBuf, - pub setup_folder: PathBuf, + #[clap(long = "seeds")] + pub seeds: Option, + #[clap(long = "target_exe")] pub target_exe: PathBuf, - pub target_env: HashMap, + #[clap(long = "setup_folder")] + pub setup_folder: Option, + #[clap(long = "target_options")] pub target_options: Vec, + #[arg(value_parser = parse_key_val::, long = "target_env")] + pub target_env: Vec<(String, String)>, } -pub async fn validate(config: Config) -> Result<()> { - let validation_config = serde_json::from_str::( - &std::fs::read_to_string(&config.config_path).context("unable to read config file")?, - )?; - - match config.command { - ValidationCommand::ValidateSetup => validate_setup(validation_config).await, - ValidationCommand::ValidateLibfuzzer => validate_libfuzzer(validation_config).await, - ValidationCommand::ExecutionLog => get_logs(validation_config).await, +pub async fn validate(command: ValidationCommand) -> Result<()> { + match command { + ValidationCommand::RunSetup { setup_folder } => run_setup(setup_folder).await, + ValidationCommand::ValidateLibfuzzer(validation_config) => { + validate_libfuzzer(validation_config).await + } + ValidationCommand::ExecutionLog(validation_config) => get_logs(validation_config).await, } } @@ -47,8 +64,10 @@ async fn validate_libfuzzer(config: ValidationConfig) -> Result<()> { let libfuzzer = LibFuzzer::new( &config.target_exe, config.target_options.clone(), - config.target_env.clone(), - config.setup_folder.clone(), + config.target_env.into_iter().collect(), + config + .setup_folder + .unwrap_or(config.target_exe.parent().unwrap().to_path_buf()), None::<&PathBuf>, MachineIdentity { machine_id: Uuid::nil(), @@ -57,12 +76,15 @@ async fn validate_libfuzzer(config: ValidationConfig) -> Result<()> { }, ); - libfuzzer.verify(true, Some(vec![config.seeds])).await?; + if let Some(seeds) = config.seeds { + libfuzzer.verify(true, Some(vec![seeds])).await?; + } + Ok(()) } -async fn validate_setup(config: ValidationConfig) -> Result<()> { - let output = SetupRunner::run_setup_script(config.setup_folder).await?; +async fn run_setup(setup_folder: impl AsRef) -> Result<()> { + let output = SetupRunner::run_setup_script(setup_folder.as_ref()).await?; match output { Some(output) => { if !output.exit_status.success { @@ -81,8 +103,10 @@ async fn get_logs(config: ValidationConfig) -> Result<()> { let libfuzzer = LibFuzzer::new( &config.target_exe, config.target_options.clone(), - config.target_env.clone(), - config.setup_folder.clone(), + config.target_env.into_iter().collect(), + config + .setup_folder + .unwrap_or(config.target_exe.parent().unwrap().to_path_buf()), None::<&PathBuf>, MachineIdentity { machine_id: Uuid::nil(), @@ -119,7 +143,3 @@ fn print_logs(cmd: std::process::Command) -> Result<(), anyhow::Error> { Ok(()) } - -// https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/extra-tools#installation-directory -// ./gflags /i C:\setup\Xbox.Shell.OneStoreServices.FuzzerTest.exe +sls -// ./cdb -c "q" C:\setup\Xbox.Shell.OneStoreServices.FuzzerTest.exe From 0b931d48e1b04fe36877ab01f1ea3a724ea330d3 Mon Sep 17 00:00:00 2001 From: Cheick Keita Date: Fri, 31 Mar 2023 08:59:44 -0700 Subject: [PATCH 13/13] bug fix --- src/agent/onefuzz-agent/src/work.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/agent/onefuzz-agent/src/work.rs b/src/agent/onefuzz-agent/src/work.rs index 617bb298ba..18a6024bdf 100644 --- a/src/agent/onefuzz-agent/src/work.rs +++ b/src/agent/onefuzz-agent/src/work.rs @@ -90,14 +90,14 @@ impl WorkSet { pub fn setup_dir(&self) -> Result { let root = self.get_root_folder()?; - self.setup_url.as_path(root.join("blob-containers")) + self.setup_url.as_path(root) } pub fn extra_dir(&self) -> Result> { let root = self.get_root_folder()?; self.extra_url .as_ref() - .map(|url| url.as_path(root.join("blob-containers"))) + .map(|url| url.as_path(root)) .transpose() } }