Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ cargo-fuzz = true
libfuzzer-sys = "0.4"
hyperlight-testing = { workspace = true }
hyperlight-host = { workspace = true, default-features = true, features = ["fuzzing"]}
hyperlight-common = {workspace = true}

[[bin]]
name = "fuzz_host_print"
Expand Down
17 changes: 6 additions & 11 deletions fuzz/fuzz_targets/host_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,14 @@ limitations under the License.

use std::sync::{Mutex, OnceLock};

use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
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<Mutex<Snapshot>> = OnceLock::new();
static SANDBOX: OnceLock<Mutex<MultiUseSandbox>> = OnceLock::new();

// This fuzz target tests all combinations of ReturnType and Parameters for `call_guest_function_by_name`.
Expand All @@ -44,27 +41,25 @@ fuzz_target!(
)
.unwrap();

let mut mu_sbox: MultiUseSandbox = u_sbox.evolve().unwrap();
let snapshot = mu_sbox.snapshot().unwrap();
let mu_sbox: MultiUseSandbox = u_sbox.evolve().unwrap();
SANDBOX.set(Mutex::new(mu_sbox)).unwrap();
SNAPSHOT.set(Mutex::new(snapshot)).map_err(|_| "Snapshot already set").unwrap();
},

|data: (String, ReturnType, Vec<ParameterValue>)| {
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));
host_func_params.insert(0, ParameterValue::String(host_func_name.clone()));
if let Err(e) = sandbox.call_type_erased_guest_function_by_name("FuzzHostFunc", host_func_return, host_func_params) {
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::GuestError(ErrorCode::HostFunctionError, msg) if msg == format!("HostFunction {} was not found", host_func_name) => {}
HyperlightError::UnexpectedNoOfArguments(_, _) => {},
HyperlightError::GuestError(ErrorCode::HostFunctionError, msg) if msg.contains("The number of arguments to the function is wrong") => {}
HyperlightError::ParameterValueConversionFailure(_, _) => {},
HyperlightError::GuestError(ErrorCode::HostFunctionError, msg) if msg.contains("Failed To Convert Parameter Value") => {}

// any other error should be reported
_ => panic!("Guest Aborted with Unexpected Error: {:?}", e),
Expand Down
15 changes: 15 additions & 0 deletions src/hyperlight_guest/src/guest_handle/host_comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,21 @@ impl GuestHandle {
}
}

pub fn get_host_return_raw(&self) -> Result<ReturnValue> {
let inner = self
.try_pop_shared_input_data_into::<FunctionCallResult>()
.expect("Unable to deserialize a return value from host")
.into_inner();

match inner {
Ok(ret) => Ok(ret),
Err(e) => Err(HyperlightGuestError {
kind: e.code,
message: e.message,
}),
}
}

/// Call a host function without reading its return value from shared mem.
/// This is used by both the Rust and C APIs to reduce code duplication.
///
Expand Down
5 changes: 5 additions & 0 deletions src/hyperlight_guest_bin/src/host_comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ pub fn call_host_function_without_returning_result(
handle.call_host_function_without_returning_result(function_name, parameters, return_type)
}

pub fn get_host_return_value_raw() -> Result<ReturnValue> {
let handle = unsafe { GUEST_HANDLE };
handle.get_host_return_raw()
}

pub fn get_host_return_value<T: TryFrom<ReturnValue>>() -> Result<T> {
let handle = unsafe { GUEST_HANDLE };
handle.get_host_return_value::<T>()
Expand Down
24 changes: 20 additions & 4 deletions src/tests/rust_guests/simpleguest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use core::ptr::write_volatile;

use hyperlight_common::flatbuffer_wrappers::function_call::{FunctionCall, FunctionCallType};
use hyperlight_common::flatbuffer_wrappers::function_types::{
ParameterType, ParameterValue, ReturnType,
ParameterType, ParameterValue, ReturnType, ReturnValue,
};
use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
use hyperlight_common::flatbuffer_wrappers::guest_log_level::LogLevel;
Expand All @@ -47,8 +47,8 @@ use hyperlight_guest::exit::{abort_with_code, abort_with_code_and_message};
use hyperlight_guest_bin::guest_function::definition::GuestFunctionDefinition;
use hyperlight_guest_bin::guest_function::register::register_function;
use hyperlight_guest_bin::host_comm::{
call_host_function, call_host_function_without_returning_result, print_output_with_host_print,
read_n_bytes_from_user_memory,
call_host_function, call_host_function_without_returning_result, get_host_return_value_raw,
print_output_with_host_print, read_n_bytes_from_user_memory,
};
use hyperlight_guest_bin::memory::malloc;
use hyperlight_guest_bin::{MIN_STACK_ADDRESS, guest_logger};
Expand Down Expand Up @@ -1665,7 +1665,23 @@ fn fuzz_host_function(func: FunctionCall) -> Result<Vec<u8>> {
func.expected_return_type,
)
.expect("failed to call host function");
Ok(get_flatbuffer_result(()))

let host_return = get_host_return_value_raw();
match host_return {
Ok(return_value) => match return_value {
ReturnValue::Int(i) => Ok(get_flatbuffer_result(i)),
ReturnValue::UInt(i) => Ok(get_flatbuffer_result(i)),
ReturnValue::Long(i) => Ok(get_flatbuffer_result(i)),
ReturnValue::ULong(i) => Ok(get_flatbuffer_result(i)),
ReturnValue::Float(i) => Ok(get_flatbuffer_result(i)),
ReturnValue::Double(i) => Ok(get_flatbuffer_result(i)),
ReturnValue::String(str) => Ok(get_flatbuffer_result(str.as_str())),
ReturnValue::Bool(bool) => Ok(get_flatbuffer_result(bool)),
ReturnValue::Void(()) => Ok(get_flatbuffer_result(())),
ReturnValue::VecBytes(byte) => Ok(get_flatbuffer_result(byte.as_slice())),
},
Err(e) => Err(e),
}
}

#[no_mangle]
Expand Down