From 77945b31a9afefe140641d8d8e88729f7e48a53c Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg Date: Thu, 27 Feb 2025 17:28:43 -0800 Subject: [PATCH] Change fuzzing to fuzz return type and parameters Signed-off-by: Ludvig Liljenberg --- .vscode/settings.json | 3 ++- Cargo.lock | 15 +++++++++++++++ src/hyperlight_common/Cargo.toml | 2 ++ .../src/flatbuffer_wrappers/function_types.rs | 2 ++ src/hyperlight_common/src/lib.rs | 3 ++- src/hyperlight_host/Cargo.toml | 1 + src/hyperlight_host/fuzz/Cargo.toml | 2 +- src/hyperlight_host/fuzz/README.md | 13 ++++--------- .../fuzz/fuzz_targets/fuzz_target_1.rs | 17 +++-------------- 9 files changed, 32 insertions(+), 26 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 1ec1edf0e..538384f9f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,7 @@ "Cargo.toml", // guest crates for testing, not part of the workspace "src/tests/rust_guests/simpleguest/Cargo.toml", - "src/tests/rust_guests/callbackguest/Cargo.toml" + "src/tests/rust_guests/callbackguest/Cargo.toml", + "src/hyperlight_host/fuzz/Cargo.toml" ] } \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 961870175..9d39305e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,9 @@ name = "arbitrary" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] [[package]] name = "async-stream" @@ -589,6 +592,17 @@ dependencies = [ "typenum", ] +[[package]] +name = "derive_arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "digest" version = "0.10.7" @@ -1092,6 +1106,7 @@ name = "hyperlight-common" version = "0.2.0" dependencies = [ "anyhow", + "arbitrary", "flatbuffers", "hyperlight-testing", "log", diff --git a/src/hyperlight_common/Cargo.toml b/src/hyperlight_common/Cargo.toml index 772bdc15d..31956a281 100644 --- a/src/hyperlight_common/Cargo.toml +++ b/src/hyperlight_common/Cargo.toml @@ -20,9 +20,11 @@ anyhow = { version = "1.0.96", default-features = false } log = "0.4.25" tracing = { version = "0.1.41", optional = true } strum = {version = "0.27", default-features = false, features = ["derive"]} +arbitrary = {version = "1.4.1", optional = true, features = ["derive"]} [features] default = ["tracing"] +fuzzing = ["dep:arbitrary"] [dev-dependencies] hyperlight-testing = { workspace = true } diff --git a/src/hyperlight_common/src/flatbuffer_wrappers/function_types.rs b/src/hyperlight_common/src/flatbuffer_wrappers/function_types.rs index 6eda6b267..42a26c81c 100644 --- a/src/hyperlight_common/src/flatbuffer_wrappers/function_types.rs +++ b/src/hyperlight_common/src/flatbuffer_wrappers/function_types.rs @@ -32,6 +32,7 @@ use crate::flatbuffers::hyperlight::generated::{ }; /// Supported parameter types with values for function calling. +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] #[derive(Debug, Clone, PartialEq)] pub enum ParameterValue { /// i32 @@ -104,6 +105,7 @@ pub enum ReturnValue { } /// Supported return types from function calling. +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] #[derive(Debug, Copy, Clone, PartialEq, Eq, Default)] #[repr(C)] pub enum ReturnType { diff --git a/src/hyperlight_common/src/lib.rs b/src/hyperlight_common/src/lib.rs index a291508ba..e2e75cc9e 100644 --- a/src/hyperlight_common/src/lib.rs +++ b/src/hyperlight_common/src/lib.rs @@ -14,7 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -#![no_std] +// We use Arbitrary during fuzzing, which requires std +#![cfg_attr(not(feature = "fuzzing"), no_std)] extern crate alloc; diff --git a/src/hyperlight_host/Cargo.toml b/src/hyperlight_host/Cargo.toml index 28f7f974b..e93ed32af 100644 --- a/src/hyperlight_host/Cargo.toml +++ b/src/hyperlight_host/Cargo.toml @@ -132,6 +132,7 @@ mshv3 = ["dep:mshv-bindings3", "dep:mshv-ioctls3"] inprocess = [] # This enables easy debug in the guest gdb = ["dep:gdbstub", "dep:gdbstub_arch"] +fuzzing = ["hyperlight-common/fuzzing"] [[bench]] name = "benchmarks" diff --git a/src/hyperlight_host/fuzz/Cargo.toml b/src/hyperlight_host/fuzz/Cargo.toml index aab002916..7114b1d2e 100644 --- a/src/hyperlight_host/fuzz/Cargo.toml +++ b/src/hyperlight_host/fuzz/Cargo.toml @@ -10,7 +10,7 @@ cargo-fuzz = true [dependencies] libfuzzer-sys = "0.4" hyperlight-testing = { workspace = true } -hyperlight-host = { workspace = true, default-features = true } +hyperlight-host = { workspace = true, default-features = true, features = ["fuzzing"]} [[bin]] name = "fuzz_target_1" diff --git a/src/hyperlight_host/fuzz/README.md b/src/hyperlight_host/fuzz/README.md index 8e7fcf2bb..1b0c49648 100644 --- a/src/hyperlight_host/fuzz/README.md +++ b/src/hyperlight_host/fuzz/README.md @@ -4,23 +4,18 @@ This directory contains the fuzzing infrastructure for Hyperlight. We use `cargo You can run the fuzzers with: ```sh -cargo +nightly-2023-11-28-x86_64-unknown-linux-gnu fuzz run --release +just fuzz ``` -> Note: Because nightly toolchains are not stable, we pin the nightly version to `2023-11-28`. To install this toolchain, run: -> ```sh -> rustup toolchain install nightly-2023-11-28-x86_64-unknown-linux-gnu -> ``` - As per Microsoft's Offensive Research & Security Engineering (MORSE) team, all host exposed functions that receive or interact with guest data must be continuously fuzzed for, at least, 500 million fuzz test cases without any crashes. Because `cargo-fuzz` doesn't support setting a maximum number of iterations; instead, we use the `--max_total_time` flag to set a maximum time to run the fuzzer. We have a GitHub action (acting like a CRON job) that runs the fuzzers for 24 hours every week. -Currently, we only fuzz the `PrintOutput` function. We plan to add more fuzzers in the future. +Currently, we only fuzz the parameters and return type to a hardcoded `PrintOutput` guest function. We plan to add more fuzzers in the future. ## On Failure If you encounter a failure, you can re-run an entire seed (i.e., group of inputs) with: ```sh -cargo +nightly-2023-11-28-x86_64-unknown-linux-gnu fuzz run --release -- -seed= +cargo +nightly fuzz run -- -seed= ``` The seed number can be seed in a specific run, like: @@ -29,5 +24,5 @@ The seed number can be seed in a specific run, like: Or, if repro-ing a failure from CI, you can download the artifact from the fuzzing run, and run it like: ```sh -cargo +nightly-2023-11-28-x86_64-unknown-linux-gnu fuzz run --release -O +cargo +nightly fuzz run -O ``` \ No newline at end of file diff --git a/src/hyperlight_host/fuzz/fuzz_targets/fuzz_target_1.rs b/src/hyperlight_host/fuzz/fuzz_targets/fuzz_target_1.rs index e500c6276..e66971e3c 100644 --- a/src/hyperlight_host/fuzz/fuzz_targets/fuzz_target_1.rs +++ b/src/hyperlight_host/fuzz/fuzz_targets/fuzz_target_1.rs @@ -24,7 +24,7 @@ use hyperlight_host::{MultiUseSandbox, UninitializedSandbox}; use hyperlight_testing::simple_guest_as_string; use libfuzzer_sys::fuzz_target; -fuzz_target!(|data: &[u8]| { +fuzz_target!(|data: (ReturnType, Option>)| { let u_sbox = UninitializedSandbox::new( GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), None, @@ -33,18 +33,7 @@ fuzz_target!(|data: &[u8]| { ) .unwrap(); - let mu_sbox: MultiUseSandbox = u_sbox.evolve(Noop::default()).unwrap(); + let mut mu_sbox: MultiUseSandbox = u_sbox.evolve(Noop::default()).unwrap(); - let msg = String::from_utf8_lossy(data).to_string(); - let len = msg.len() as i32; - let mut ctx = mu_sbox.new_call_context(); - let result = ctx - .call( - "PrintOutput", - ReturnType::Int, - Some(vec![ParameterValue::String(msg.clone())]), - ) - .unwrap(); - - assert_eq!(result, ReturnValue::Int(len)); + let _ = mu_sbox.call_guest_function_by_name("PrintOutput", data.0, data.1); });