diff --git a/fuzz/fuzz_targets/host_call.rs b/fuzz/fuzz_targets/host_call.rs index 5c72a98e5..8011c7314 100644 --- a/fuzz/fuzz_targets/host_call.rs +++ b/fuzz/fuzz_targets/host_call.rs @@ -19,34 +19,57 @@ limitations under the License. use std::sync::{Mutex, OnceLock}; use hyperlight_host::func::{ParameterValue, ReturnType}; +use hyperlight_host::sandbox::SandboxConfiguration; +use hyperlight_host::sandbox::snapshot::Snapshot; use hyperlight_host::sandbox::uninitialized::GuestBinary; use hyperlight_host::{HyperlightError, MultiUseSandbox, UninitializedSandbox}; use hyperlight_testing::simple_guest_for_fuzzing_as_string; use libfuzzer_sys::fuzz_target; + +// TODO: this SNAPSHOT is needed because of the memory leak in: https://github.com/hyperlight-dev/hyperlight/issues/826 +// This should be removed once the leak is fixed +static SNAPSHOT: OnceLock> = OnceLock::new(); static SANDBOX: OnceLock> = OnceLock::new(); // This fuzz target tests all combinations of ReturnType and Parameters for `call_guest_function_by_name`. // For fuzzing efficiency, we create one Sandbox and reuse it for all fuzzing iterations. fuzz_target!( init: { + let mut cfg = SandboxConfiguration::default(); + cfg.set_output_data_size(64 * 1024); // 64 KB output buffer + cfg.set_input_data_size(64 * 1024); // 64 KB input buffer let u_sbox = UninitializedSandbox::new( GuestBinary::FilePath(simple_guest_for_fuzzing_as_string().expect("Guest Binary Missing")), - None + Some(cfg) ) .unwrap(); - let mu_sbox: MultiUseSandbox = u_sbox.evolve().unwrap(); + let mut mu_sbox: MultiUseSandbox = u_sbox.evolve().unwrap(); + let snapshot = mu_sbox.snapshot().unwrap(); SANDBOX.set(Mutex::new(mu_sbox)).unwrap(); + SNAPSHOT.set(Mutex::new(snapshot)).map_err(|_| "Snapshot already set").unwrap(); }, |data: (String, ReturnType, Vec)| { let (host_func_name, host_func_return, mut host_func_params) = data; let mut sandbox = SANDBOX.get().unwrap().lock().unwrap(); + let snapshot = SNAPSHOT.get().unwrap().lock().unwrap(); + sandbox.restore(&snapshot).unwrap(); + host_func_params.insert(0, ParameterValue::String(host_func_name)); match sandbox.call_type_erased_guest_function_by_name("FuzzHostFunc", host_func_return, host_func_params) { - Err(HyperlightError::GuestAborted(_, message)) if !message.contains("Host Function Not Found") => { - // We don't allow GuestAborted errors, except for the "Host Function Not Found" case - panic!("Guest Aborted: {}", message); + Err(e) => { + match e { + // the following are expected errors and occur frequently since + // we are randomly generating the function name and parameters + // to call with. + HyperlightError::HostFunctionNotFound(_) => {} + HyperlightError::UnexpectedNoOfArguments(_, _) => {}, + HyperlightError::ParameterValueConversionFailure(_, _) => {}, + + // any other error should be reported + _ => panic!("Guest Aborted with Unexpected Error: {:?}", e), + } } _ => {} } diff --git a/src/hyperlight_host/src/sandbox/initialized_multi_use.rs b/src/hyperlight_host/src/sandbox/initialized_multi_use.rs index 40464e328..82a920158 100644 --- a/src/hyperlight_host/src/sandbox/initialized_multi_use.rs +++ b/src/hyperlight_host/src/sandbox/initialized_multi_use.rs @@ -381,6 +381,8 @@ impl MultiUseSandbox { ret_type: ReturnType, args: Vec, ) -> Result { + // Reset snapshot since we are mutating the sandbox state + self.snapshot = None; maybe_time_and_emit_guest_call(func_name, || { self.call_guest_function_by_name_no_reset(func_name, ret_type, args) })