Skip to content
This repository has been archived by the owner on Nov 1, 2023. It is now read-only.

Commit

Permalink
initial support for running the agent locally on OSX (#1016)
Browse files Browse the repository at this point in the history
  • Loading branch information
bmc-msft committed Jun 29, 2021
1 parent b5388d3 commit 2f71689
Show file tree
Hide file tree
Showing 21 changed files with 158 additions and 51 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ jobs:
os:
- ubuntu-18.04
- windows-2019
- macos-10.15
azcopy:
runs-on: ubuntu-18.04
steps:
Expand Down
10 changes: 10 additions & 0 deletions src/agent/coverage/examples/coverage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ fn input_command(argv: &[String], input: &Path) -> Command {
cmd
}

#[cfg(target_os = "macos")]
fn record(
_cache: &mut ModuleCache,
_filter: CmdFilter,
_cmd: Command,
_timeout: Duration,
) -> Result<Coverage> {
unimplemented!("coverage recording is not supported on macOS");
}

#[cfg(target_os = "linux")]
fn record(
cache: &mut ModuleCache,
Expand Down
5 changes: 5 additions & 0 deletions src/agent/coverage/examples/elf_sancov_tables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ struct Opt {
inline: bool,
}

#[cfg(target_os = "macos")]
fn main() -> Result<()> {
Ok(())
}

#[cfg(target_os = "windows")]
fn main() -> Result<()> {
Ok(())
Expand Down
5 changes: 5 additions & 0 deletions src/agent/coverage/examples/pdb_sancov_tables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,8 @@ fn main() -> Result<()> {
fn main() -> Result<()> {
Ok(())
}

#[cfg(target_os = "macos")]
fn main() -> Result<()> {
Ok(())
}
1 change: 1 addition & 0 deletions src/agent/coverage/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use std::collections::{BTreeSet, HashMap};

#[cfg(any(target_os = "windows", target_os = "linux"))]
use anyhow::Result;
use serde::{Deserialize, Serialize};

Expand Down
32 changes: 19 additions & 13 deletions src/agent/onefuzz-agent/src/local/cmd.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use std::time::Duration;

#[cfg(any(target_os = "linux", target_os = "windows"))]
use crate::local::libfuzzer_coverage;
use crate::local::{
common::add_common_config, generic_analysis, generic_crash_report, generic_generator,
libfuzzer, libfuzzer_crash_report, libfuzzer_fuzz, libfuzzer_merge, libfuzzer_regression,
libfuzzer_test_input, radamsa, test_input, tui::TerminalUi,
};
use anyhow::Result;
use clap::{App, Arg, SubCommand};
use crossterm::tty::IsTty;
use std::time::Duration;
use tokio::{select, time::timeout};

use crate::local::{
common::add_common_config, generic_analysis, generic_crash_report, generic_generator,
libfuzzer, libfuzzer_coverage, libfuzzer_crash_report, libfuzzer_fuzz, libfuzzer_merge,
libfuzzer_regression, libfuzzer_test_input, radamsa, test_input, tui::TerminalUi,
};

const RADAMSA: &str = "radamsa";
const LIBFUZZER: &str = "libfuzzer";
const LIBFUZZER_FUZZ: &str = "libfuzzer-fuzz";
const LIBFUZZER_CRASH_REPORT: &str = "libfuzzer-crash-report";
#[cfg(any(target_os = "linux", target_os = "windows"))]
const LIBFUZZER_COVERAGE: &str = "libfuzzer-coverage";
const LIBFUZZER_MERGE: &str = "libfuzzer-merge";
const LIBFUZZER_TEST_INPUT: &str = "libfuzzer-test-input";
Expand All @@ -42,6 +43,7 @@ pub async fn run(args: clap::ArgMatches<'static>) -> Result<()> {
(RADAMSA, Some(sub)) => radamsa::run(sub, event_sender).await,
(LIBFUZZER, Some(sub)) => libfuzzer::run(sub, event_sender).await,
(LIBFUZZER_FUZZ, Some(sub)) => libfuzzer_fuzz::run(sub, event_sender).await,
#[cfg(any(target_os = "linux", target_os = "windows"))]
(LIBFUZZER_COVERAGE, Some(sub)) => libfuzzer_coverage::run(sub, event_sender).await,
(LIBFUZZER_CRASH_REPORT, Some(sub)) => {
libfuzzer_crash_report::run(sub, event_sender).await
Expand Down Expand Up @@ -84,7 +86,7 @@ pub async fn run(args: clap::ArgMatches<'static>) -> Result<()> {
}

pub fn args(name: &str) -> App<'static, 'static> {
SubCommand::with_name(name)
let cmd = SubCommand::with_name(name)
.about("pre-release local fuzzing")
.arg(
Arg::with_name(TIMEOUT)
Expand All @@ -95,9 +97,6 @@ pub fn args(name: &str) -> App<'static, 'static> {
.subcommand(add_common_config(radamsa::args(RADAMSA)))
.subcommand(add_common_config(libfuzzer::args(LIBFUZZER)))
.subcommand(add_common_config(libfuzzer_fuzz::args(LIBFUZZER_FUZZ)))
.subcommand(add_common_config(libfuzzer_coverage::args(
LIBFUZZER_COVERAGE,
)))
.subcommand(add_common_config(libfuzzer_merge::args(LIBFUZZER_MERGE)))
.subcommand(add_common_config(libfuzzer_regression::args(
LIBFUZZER_REGRESSION,
Expand All @@ -115,5 +114,12 @@ pub fn args(name: &str) -> App<'static, 'static> {
.subcommand(add_common_config(test_input::args(GENERIC_TEST_INPUT)))
.subcommand(add_common_config(libfuzzer_test_input::args(
LIBFUZZER_TEST_INPUT,
)))
)));

#[cfg(any(target_os = "linux", target_os = "windows"))]
let cmd = cmd.subcommand(add_common_config(libfuzzer_coverage::args(
LIBFUZZER_COVERAGE,
)));

cmd
}
18 changes: 14 additions & 4 deletions src/agent/onefuzz-agent/src/local/libfuzzer.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#[cfg(any(target_os = "linux", target_os = "windows"))]
use crate::{
local::{
common::COVERAGE_DIR,
libfuzzer_coverage::{build_coverage_config, build_shared_args as build_coverage_args},
},
tasks::coverage::libfuzzer_coverage::CoverageTask,
};
use crate::{
local::{
common::{
build_local_context, wait_for_dir, DirectoryMonitorQueue, UiEvent, ANALYZER_EXE,
COVERAGE_DIR, REGRESSION_REPORTS_DIR, UNIQUE_REPORTS_DIR,
REGRESSION_REPORTS_DIR, UNIQUE_REPORTS_DIR,
},
generic_analysis::{build_analysis_config, build_shared_args as build_analysis_args},
libfuzzer_coverage::{build_coverage_config, build_shared_args as build_coverage_args},
libfuzzer_crash_report::{build_report_config, build_shared_args as build_crash_args},
libfuzzer_fuzz::{build_fuzz_config, build_shared_args as build_fuzz_args},
libfuzzer_regression::{
Expand All @@ -17,8 +24,8 @@ use crate::{
},
tasks::{
analysis::generic::run as run_analysis, config::CommonConfig,
coverage::libfuzzer_coverage::CoverageTask, fuzz::libfuzzer_fuzz::LibFuzzerFuzzTask,
regression::libfuzzer::LibFuzzerRegressionTask, report::libfuzzer_report::ReportTask,
fuzz::libfuzzer_fuzz::LibFuzzerFuzzTask, regression::libfuzzer::LibFuzzerRegressionTask,
report::libfuzzer_report::ReportTask,
},
};
use anyhow::Result;
Expand Down Expand Up @@ -68,6 +75,7 @@ pub async fn run(args: &clap::ArgMatches<'_>, event_sender: Option<Sender<UiEven
task_handles.push(crash_report_input_monitor.handle);
}

#[cfg(any(target_os = "linux", target_os = "windows"))]
if args.is_present(COVERAGE_DIR) {
let coverage_input_monitor =
DirectoryMonitorQueue::start_monitoring(crash_dir.clone()).await?;
Expand Down Expand Up @@ -129,10 +137,12 @@ pub fn args(name: &'static str) -> App<'static, 'static> {
let mut app = SubCommand::with_name(name).about("run a local libfuzzer & crash reporting task");

let mut used = HashSet::new();

for args in &[
build_fuzz_args(),
build_crash_args(),
build_analysis_args(false),
#[cfg(any(target_os = "linux", target_os = "windows"))]
build_coverage_args(true),
build_regression_args(false),
] {
Expand Down
1 change: 1 addition & 0 deletions src/agent/onefuzz-agent/src/local/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod generic_analysis;
pub mod generic_crash_report;
pub mod generic_generator;
pub mod libfuzzer;
#[cfg(any(target_os = "linux", target_os = "windows"))]
pub mod libfuzzer_coverage;
pub mod libfuzzer_crash_report;
pub mod libfuzzer_fuzz;
Expand Down
14 changes: 13 additions & 1 deletion src/agent/onefuzz-agent/src/tasks/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
// Licensed under the MIT License.

#![allow(clippy::large_enum_variant)]
#[cfg(any(target_os = "linux", target_os = "windows"))]
use crate::tasks::coverage;
use crate::tasks::{
analysis, coverage, fuzz,
analysis, fuzz,
heartbeat::{init_task_heartbeat, TaskHeartbeatClient},
merge, regression, report,
};
Expand Down Expand Up @@ -61,6 +63,7 @@ impl CommonConfig {
#[derive(Debug, Deserialize)]
#[serde(tag = "task_type")]
pub enum Config {
#[cfg(any(target_os = "linux", target_os = "windows"))]
#[serde(alias = "coverage")]
Coverage(coverage::generic::Config),

Expand All @@ -73,6 +76,7 @@ pub enum Config {
#[serde(alias = "libfuzzer_merge")]
LibFuzzerMerge(merge::libfuzzer_merge::Config),

#[cfg(any(target_os = "linux", target_os = "windows"))]
#[serde(alias = "libfuzzer_coverage")]
LibFuzzerCoverage(coverage::libfuzzer_coverage::Config),

Expand Down Expand Up @@ -112,10 +116,12 @@ impl Config {

fn common_mut(&mut self) -> &mut CommonConfig {
match self {
#[cfg(any(target_os = "linux", target_os = "windows"))]
Config::Coverage(c) => &mut c.common,
Config::LibFuzzerFuzz(c) => &mut c.common,
Config::LibFuzzerMerge(c) => &mut c.common,
Config::LibFuzzerReport(c) => &mut c.common,
#[cfg(any(target_os = "linux", target_os = "windows"))]
Config::LibFuzzerCoverage(c) => &mut c.common,
Config::LibFuzzerRegression(c) => &mut c.common,
Config::GenericAnalysis(c) => &mut c.common,
Expand All @@ -129,10 +135,12 @@ impl Config {

pub fn common(&self) -> &CommonConfig {
match self {
#[cfg(any(target_os = "linux", target_os = "windows"))]
Config::Coverage(c) => &c.common,
Config::LibFuzzerFuzz(c) => &c.common,
Config::LibFuzzerMerge(c) => &c.common,
Config::LibFuzzerReport(c) => &c.common,
#[cfg(any(target_os = "linux", target_os = "windows"))]
Config::LibFuzzerCoverage(c) => &c.common,
Config::LibFuzzerRegression(c) => &c.common,
Config::GenericAnalysis(c) => &c.common,
Expand All @@ -146,10 +154,12 @@ impl Config {

pub fn report_event(&self) {
let event_type = match self {
#[cfg(any(target_os = "linux", target_os = "windows"))]
Config::Coverage(_) => "coverage",
Config::LibFuzzerFuzz(_) => "libfuzzer_fuzz",
Config::LibFuzzerMerge(_) => "libfuzzer_merge",
Config::LibFuzzerReport(_) => "libfuzzer_crash_report",
#[cfg(any(target_os = "linux", target_os = "windows"))]
Config::LibFuzzerCoverage(_) => "libfuzzer_coverage",
Config::LibFuzzerRegression(_) => "libfuzzer_regression",
Config::GenericAnalysis(_) => "generic_analysis",
Expand Down Expand Up @@ -189,6 +199,7 @@ impl Config {
self.report_event();

match self {
#[cfg(any(target_os = "linux", target_os = "windows"))]
Config::Coverage(config) => coverage::generic::CoverageTask::new(config).run().await,
Config::LibFuzzerFuzz(config) => {
fuzz::libfuzzer_fuzz::LibFuzzerFuzzTask::new(config)?
Expand All @@ -200,6 +211,7 @@ impl Config {
.managed_run()
.await
}
#[cfg(any(target_os = "linux", target_os = "windows"))]
Config::LibFuzzerCoverage(config) => {
coverage::libfuzzer_coverage::CoverageTask::new(config)
.managed_run()
Expand Down
1 change: 1 addition & 0 deletions src/agent/onefuzz-agent/src/tasks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

pub mod analysis;
pub mod config;
#[cfg(any(target_os = "linux", target_os = "windows"))]
pub mod coverage;
pub mod fuzz;
pub mod generic;
Expand Down
2 changes: 1 addition & 1 deletion src/agent/onefuzz-supervisor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ clap = "2.33"
reqwest-retry = { path = "../reqwest-retry" }
onefuzz-telemetry = { path = "../onefuzz-telemetry" }

[target.'cfg(target_os = "linux")'.dependencies]
[target.'cfg(target_family = "unix")'.dependencies]
users = "0.11"
14 changes: 7 additions & 7 deletions src/agent/onefuzz-supervisor/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,31 @@ use onefuzz::{auth::Secret, machine_id::get_scaleset_name};
use std::process::Stdio;
use tokio::{fs, io::AsyncWriteExt, process::Command};

#[cfg(target_os = "windows")]
#[cfg(target_family = "windows")]
use std::{env, path::PathBuf};

#[cfg(target_os = "windows")]
#[cfg(target_family = "windows")]
use tokio::sync::{OnceCell, SetError};

#[cfg(target_os = "linux")]
#[cfg(target_family = "unix")]
use users::{get_user_by_name, os::unix::UserExt};

#[cfg(target_os = "linux")]
#[cfg(target_family = "unix")]
const ONEFUZZ_SERVICE_USER: &str = "onefuzz";

// On Windows, removing permissions that have already been removed fails. As
// such, this needs to happen once and only once. NOTE: SSH keys are added as
// node commands, which are processed serially. As such, this should never get
// called concurrently.
#[cfg(target_os = "windows")]
#[cfg(target_family = "windows")]
static SET_PERMISSION_ONCE: OnceCell<()> = OnceCell::const_new();

#[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct SshKeyInfo {
pub public_key: Secret<String>,
}

#[cfg(target_os = "windows")]
#[cfg(target_family = "windows")]
pub async fn add_ssh_key(key_info: SshKeyInfo) -> Result<()> {
if get_scaleset_name().await?.is_none() {
warn!("adding ssh keys only supported on managed nodes");
Expand Down Expand Up @@ -133,7 +133,7 @@ pub async fn add_ssh_key(key_info: SshKeyInfo) -> Result<()> {
Ok(())
}

#[cfg(target_os = "linux")]
#[cfg(target_family = "unix")]
pub async fn add_ssh_key(key_info: SshKeyInfo) -> Result<()> {
if get_scaleset_name().await?.is_none() {
warn!("adding ssh keys only supported on managed nodes");
Expand Down
4 changes: 2 additions & 2 deletions src/agent/onefuzz-supervisor/src/reboot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl Reboot {
Ok(Some(ctx))
}

#[cfg(target_os = "linux")]
#[cfg(target_family = "unix")]
pub fn invoke(&mut self) -> Result<()> {
info!("invoking local reboot command");

Expand All @@ -90,7 +90,7 @@ impl Reboot {
self.wait_for_reboot()
}

#[cfg(target_os = "windows")]
#[cfg(target_family = "windows")]
pub fn invoke(&mut self) -> Result<()> {
info!("invoking local reboot command");

Expand Down
Loading

0 comments on commit 2f71689

Please sign in to comment.