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

initial support for running the agent locally on OSX #1016

Merged
merged 14 commits into from
Jun 29, 2021
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 osx");
bmc-msft marked this conversation as resolved.
Show resolved Hide resolved
}

#[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