diff --git a/src/hyperlight_host/src/func/host_functions.rs b/src/hyperlight_host/src/func/host_functions.rs index cbb231111..14c950faa 100644 --- a/src/hyperlight_host/src/func/host_functions.rs +++ b/src/hyperlight_host/src/func/host_functions.rs @@ -14,232 +14,153 @@ See the License for the specific language governing permissions and limitations under the License. */ -#![allow(non_snake_case)] use std::sync::{Arc, Mutex}; -use hyperlight_common::flatbuffer_wrappers::function_types::ParameterValue; -use tracing::{instrument, Span}; +use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnValue}; -use super::{HyperlightFunction, SupportedParameterType, SupportedReturnType}; +use super::utils::for_each_tuple; +use super::{ParameterTuple, ResultType, SupportedReturnType}; use crate::sandbox::{ExtraAllowedSyscall, UninitializedSandbox}; -use crate::HyperlightError::UnexpectedNoOfArguments; use crate::{log_then_return, new_error, Result}; -/// Trait for registering a host function -pub trait HostFunction { - /// Register the host function with the given name in the sandbox. - fn register(&self, sandbox: &mut UninitializedSandbox, name: &str) -> Result<()>; - - /// Register the host function with the given name in the sandbox, allowing extra syscalls. - #[cfg(all(feature = "seccomp", target_os = "linux"))] - fn register_with_extra_allowed_syscalls( - &self, - sandbox: &mut UninitializedSandbox, - name: &str, - extra_allowed_syscalls: Vec, - ) -> Result<()>; +/// A representation of a host function. +/// This is a thin wrapper around a `Fn(Args) -> Result`. +#[derive(Clone)] +pub struct HostFunction +where + Args: ParameterTuple, + Output: SupportedReturnType, +{ + // This is a thin wrapper around a `Fn(Args) -> Result`. + // But unlike `Fn` which is a trait, this is a concrete type. + // This allows us to: + // 1. Impose constraints on the function arguments and return type. + // 2. Impose a single function signature. + // + // This second point is important because the `Fn` trait is generic + // over the function arguments (with an associated return type). + // This means that a given type could implement `Fn` for multiple + // function signatures. + // This means we can't do something like: + // ```rust,ignore + // impl SomeTrait for F + // where + // F: Fn(Args) -> Result, + // { ... } + // ``` + // because the concrete type F might implement `Fn` for multiple times, + // and that would means implementing `SomeTrait` multiple times for the + // same type. + + // Use Arc in here instead of Box because it's useful in tests and + // presumably in other places to be able to clone a HostFunction and + // use it across different sandboxes. + func: Arc Result + Send + Sync + 'static>, } -/// Tait for types that can be converted into types implementing `HostFunction`. -pub trait IntoHostFunction { - /// Concrete type of the returned host function - type Output: HostFunction; - - /// Convert the type into a host function - fn into_host_function(self) -> Self::Output; +pub(crate) struct TypeErasedHostFunction { + func: Box) -> Result + Send + Sync + 'static>, } -macro_rules! impl_host_function { - (@count) => { 0 }; - (@count $P:ident $(, $R:ident)*) => { - impl_host_function!(@count $($R),*) + 1 - }; - (@impl $($P:ident),*) => { - const _: () = { - impl HostFunction for Arc> - where - F: FnMut($($P),*) -> Result + Send + 'static, - $($P: SupportedParameterType + Clone,)* - R: SupportedReturnType, - { - /// Register the host function with the given name in the sandbox. - #[instrument( - err(Debug), skip(self, sandbox), parent = Span::current(), level = "Trace" - )] - fn register( - &self, - sandbox: &mut UninitializedSandbox, - name: &str, - ) -> Result<()> { - register_host_function(self.clone(), sandbox, name, None) - } - - /// Register the host function with the given name in the sandbox, allowing extra syscalls. - #[cfg(all(feature = "seccomp", target_os = "linux"))] - #[instrument( - err(Debug), skip(self, sandbox, extra_allowed_syscalls), - parent = Span::current(), level = "Trace" - )] - fn register_with_extra_allowed_syscalls( - &self, - sandbox: &mut UninitializedSandbox, - name: &str, - extra_allowed_syscalls: Vec, - ) -> Result<()> { - register_host_function(self.clone(), sandbox, name, Some(extra_allowed_syscalls)) - } - } - - impl HostFunction for &dyn HostFunction - where - $($P: SupportedParameterType + Clone,)* - R: SupportedReturnType, - { - /// Register the host function with the given name in the sandbox. - #[instrument( - err(Debug), skip(self, sandbox), parent = Span::current(), level = "Trace" - )] - fn register( - &self, - sandbox: &mut UninitializedSandbox, - name: &str, - ) -> Result<()> { - (**self).register(sandbox, name) - } - - /// Register the host function with the given name in the sandbox, allowing extra syscalls. - #[cfg(all(feature = "seccomp", target_os = "linux"))] - #[instrument( - err(Debug), skip(self, sandbox, extra_allowed_syscalls), - parent = Span::current(), level = "Trace" - )] - fn register_with_extra_allowed_syscalls( - &self, - sandbox: &mut UninitializedSandbox, - name: &str, - extra_allowed_syscalls: Vec, - ) -> Result<()> { - (**self).register_with_extra_allowed_syscalls(sandbox, name, extra_allowed_syscalls) - } - } - - impl IntoHostFunction for F - where - F: FnMut($($P),*) -> Result + Send + 'static, - Arc>: HostFunction, - { - type Output = Arc>; - - fn into_host_function(self) -> Self::Output { - Arc::new(Mutex::new(self)) - } - } - - impl IntoHostFunction for Arc> - where - F: FnMut($($P),*) -> Result + Send + 'static, - Arc>: HostFunction, - { - type Output = Arc>; +impl HostFunction +where + Args: ParameterTuple, + Output: SupportedReturnType, +{ + /// Call the host function with the given arguments. + pub fn call(&self, args: Args) -> Result { + (self.func)(args) + } +} - fn into_host_function(self) -> Self::Output { - self - } - } +impl TypeErasedHostFunction { + pub(crate) fn call(&self, args: Vec) -> Result { + (self.func)(args) + } +} - impl IntoHostFunction for &Arc> - where - F: FnMut($($P),*) -> Result + Send + 'static, - Arc>: HostFunction, - { - type Output = Arc>; +impl From> for TypeErasedHostFunction +where + Args: ParameterTuple, + Output: SupportedReturnType, +{ + fn from(func: HostFunction) -> TypeErasedHostFunction { + TypeErasedHostFunction { + func: Box::new(move |args: Vec| { + let args = Args::from_value(args)?; + Ok(func.call(args)?.into_value()) + }), + } + } +} - fn into_host_function(self) -> Self::Output { - self.clone() +macro_rules! impl_host_function { + ([$N:expr] ($($p:ident: $P:ident),*)) => { + /* + // Normally for a `Fn + Send + Sync` we don't need to use a Mutex + // like we do in the case of a `FnMut`. + // However, we can't implement `IntoHostFunction` for `Fn` and `FnMut` + // because `FnMut` is a supertrait of `Fn`. + */ + + impl From for HostFunction + where + F: FnMut($($P),*) -> R + Send + 'static, + ($($P,)*): ParameterTuple, + R: ResultType, + { + fn from(mut func: F) -> HostFunction { + let func = move |($($p,)*): ($($P,)*)| -> Result { + func($($p),*).into_result() + }; + let func = Mutex::new(func); + HostFunction { + func: Arc::new(move |args: ($($P,)*)| { + func.try_lock() + .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))? + (args) + }) } } + } + }; +} - impl IntoHostFunction for &dyn HostFunction - where - R: SupportedReturnType, - $($P: SupportedParameterType + Clone,)* - { - type Output = Self; +for_each_tuple!(impl_host_function); - fn into_host_function(self) -> Self::Output { - self - } - } +pub(crate) fn register_host_function( + func: impl Into>, + sandbox: &mut UninitializedSandbox, + name: &str, + extra_allowed_syscalls: Option>, +) -> Result<()> { + let func = func.into().into(); - fn register_host_function( - self_: Arc>, - sandbox: &mut UninitializedSandbox, - name: &str, - extra_allowed_syscalls: Option>, - ) -> Result<()> - where - T: FnMut($($P),*) -> Result + Send + 'static, - $($P: SupportedParameterType + Clone,)* - R: SupportedReturnType, + if let Some(_eas) = extra_allowed_syscalls { + if cfg!(all(feature = "seccomp", target_os = "linux")) { + // Register with extra allowed syscalls + #[cfg(all(feature = "seccomp", target_os = "linux"))] { - const N: usize = impl_host_function!(@count $($P),*); - let cloned = self_.clone(); - let func = Box::new(move |args: Vec| { - let ($($P,)*) = match <[ParameterValue; N]>::try_from(args) { - Ok([$($P,)*]) => ($($P::from_value($P)?,)*), - Err(args) => { log_then_return!(UnexpectedNoOfArguments(args.len(), N)); } - }; - - let result = cloned - .try_lock() - .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?( - $($P),* - )?; - Ok(result.into_value()) - }); - - if let Some(_eas) = extra_allowed_syscalls { - if cfg!(all(feature = "seccomp", target_os = "linux")) { - // Register with extra allowed syscalls - #[cfg(all(feature = "seccomp", target_os = "linux"))] - { - sandbox - .host_funcs - .try_lock() - .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))? - .register_host_function_with_syscalls( - name.to_string(), - HyperlightFunction::new(func), - _eas, - )?; - } - } else { - // Log and return an error - log_then_return!("Extra allowed syscalls are only supported on Linux with seccomp enabled"); - } - } else { - // Register without extra allowed syscalls - sandbox - .host_funcs - .try_lock() - .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))? - .register_host_function( - name.to_string(), - HyperlightFunction::new(func), - )?; - } - - Ok(()) + sandbox + .host_funcs + .try_lock() + .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))? + .register_host_function_with_syscalls(name.to_string(), func, _eas)?; } - }; - }; - () => { - impl_host_function!(@impl); - }; - ($P:ident $(, $R:ident)*) => { - impl_host_function!($($R),*); - impl_host_function!(@impl $P $(, $R)*); - }; + } else { + // Log and return an error + log_then_return!( + "Extra allowed syscalls are only supported on Linux with seccomp enabled" + ); + } + } else { + // Register without extra allowed syscalls + sandbox + .host_funcs + .try_lock() + .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))? + .register_host_function(name.to_string(), func)?; + } + + Ok(()) } - -impl_host_function!(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10); diff --git a/src/hyperlight_host/src/func/mod.rs b/src/hyperlight_host/src/func/mod.rs index 9e9642789..e813ea7d5 100644 --- a/src/hyperlight_host/src/func/mod.rs +++ b/src/hyperlight_host/src/func/mod.rs @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -use crate::{new_error, Result}; /// Context structures used to allow the user to call one or more guest /// functions on the same Hyperlight sandbox instance, all from within the /// same state and mutual exclusion context. @@ -34,48 +33,21 @@ pub(crate) mod guest_err; /// - Registering host functions to be callable by the guest /// - Dynamically dispatching a call from the guest to the appropriate /// host function -pub mod host_functions; +pub(crate) mod host_functions; /// Definitions and functionality for supported parameter types pub(crate) mod param_type; /// Definitions and functionality for supported return types -pub mod ret_type; - -use std::sync::{Arc, Mutex}; +pub(crate) mod ret_type; +/// Re-export for `HostFunction` trait +pub use host_functions::HostFunction; /// Re-export for `ParameterValue` enum pub use hyperlight_common::flatbuffer_wrappers::function_types::ParameterValue; /// Re-export for `ReturnType` enum pub use hyperlight_common::flatbuffer_wrappers::function_types::ReturnType; /// Re-export for `ReturnType` enum pub use hyperlight_common::flatbuffer_wrappers::function_types::ReturnValue; -pub use param_type::SupportedParameterType; -pub use ret_type::SupportedReturnType; -use tracing::{instrument, Span}; - -type HLFunc = Arc) -> Result + Send>>>; - -/// Generic HyperlightFunction -#[derive(Clone)] -pub struct HyperlightFunction(HLFunc); +pub use param_type::{ParameterTuple, SupportedParameterType}; +pub use ret_type::{ResultType, SupportedReturnType}; -impl HyperlightFunction { - #[instrument(skip_all, parent = Span::current(), level= "Trace")] - pub(crate) fn new(f: F) -> Self - where - F: FnMut(Vec) -> Result + Send + 'static, - { - Self(Arc::new(Mutex::new(Box::new(f)))) - } - - #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")] - pub(crate) fn call(&self, args: Vec) -> Result { - let mut f = self - .0 - .try_lock() - .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?; - f(args) - } -} - -/// Re-export for `HostFunction` trait -pub use host_functions::HostFunction; +mod utils; diff --git a/src/hyperlight_host/src/func/param_type.rs b/src/hyperlight_host/src/func/param_type.rs index 4282304e8..407b202da 100644 --- a/src/hyperlight_host/src/func/param_type.rs +++ b/src/hyperlight_host/src/func/param_type.rs @@ -17,7 +17,8 @@ limitations under the License. use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterType, ParameterValue}; use tracing::{instrument, Span}; -use crate::HyperlightError::ParameterValueConversionFailure; +use super::utils::for_each_tuple; +use crate::HyperlightError::{ParameterValueConversionFailure, UnexpectedNoOfArguments}; use crate::{log_then_return, Result}; /// This is a marker trait that is used to indicate that a type is a @@ -25,7 +26,7 @@ use crate::{log_then_return, Result}; /// /// For each parameter type Hyperlight supports in host functions, we /// provide an implementation for `SupportedParameterType` -pub trait SupportedParameterType: Sized { +pub trait SupportedParameterType: Sized + Clone + Send + Sync + 'static { /// The underlying Hyperlight parameter type representing this `SupportedParameterType` const TYPE: ParameterType; @@ -76,3 +77,47 @@ macro_rules! impl_supported_param_type { } for_each_param_type!(impl_supported_param_type); + +/// A trait to describe the tuple of parameters that a host function can take. +pub trait ParameterTuple: Sized + Clone + Send + Sync + 'static { + /// The number of parameters in the tuple + const SIZE: usize; + + /// The underlying Hyperlight parameter types representing this tuple of `SupportedParameterType` + const TYPE: &[ParameterType]; + + /// Get the underling Hyperlight parameter value representing this + /// `SupportedParameterType` + fn into_value(self) -> Vec; + + /// Get the actual inner value of this `SupportedParameterType` + fn from_value(value: Vec) -> Result; +} + +macro_rules! impl_param_tuple { + ([$N:expr] ($($name:ident: $param:ident),*)) => { + impl<$($param: SupportedParameterType),*> ParameterTuple for ($($param,)*) { + const SIZE: usize = $N; + + const TYPE: &[ParameterType] = &[ + $($param::TYPE),* + ]; + + #[instrument(skip_all, parent = Span::current(), level= "Trace")] + fn into_value(self) -> Vec { + let ($($name,)*) = self; + vec![$($name.into_value()),*] + } + + #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")] + fn from_value(value: Vec) -> Result { + match <[ParameterValue; $N]>::try_from(value) { + Ok([$($name,)*]) => Ok(($($param::from_value($name)?,)*)), + Err(value) => { log_then_return!(UnexpectedNoOfArguments(value.len(), $N)); } + } + } + } + }; +} + +for_each_tuple!(impl_param_tuple); diff --git a/src/hyperlight_host/src/func/ret_type.rs b/src/hyperlight_host/src/func/ret_type.rs index 756113ba3..1006fe649 100644 --- a/src/hyperlight_host/src/func/ret_type.rs +++ b/src/hyperlight_host/src/func/ret_type.rs @@ -21,7 +21,7 @@ use crate::HyperlightError::ReturnValueConversionFailure; use crate::{log_then_return, Result}; /// This is a marker trait that is used to indicate that a type is a valid Hyperlight return type. -pub trait SupportedReturnType: Sized { +pub trait SupportedReturnType: Sized + Clone + Send + Sync + 'static { /// The return type of the supported return value const TYPE: ReturnType; @@ -32,6 +32,15 @@ pub trait SupportedReturnType: Sized { fn from_value(value: ReturnValue) -> Result; } +/// A trait to handle either a SupportedReturnType or a Result +pub trait ResultType { + /// The return type of the supported return value + type ReturnType: SupportedReturnType; + + /// Convert the return type into a Result + fn into_result(self) -> Result; +} + macro_rules! for_each_return_type { ($macro:ident) => { $macro!((), Void); @@ -68,6 +77,24 @@ macro_rules! impl_supported_return_type { } } } + + impl ResultType for $type { + type ReturnType = $type; + + #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")] + fn into_result(self) -> Result { + Ok(self) + } + } + + impl ResultType for Result<$type> { + type ReturnType = $type; + + #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")] + fn into_result(self) -> Result { + self + } + } }; } diff --git a/src/hyperlight_host/src/func/utils.rs b/src/hyperlight_host/src/func/utils.rs new file mode 100644 index 000000000..b02666bf5 --- /dev/null +++ b/src/hyperlight_host/src/func/utils.rs @@ -0,0 +1,63 @@ +/// An utility macro to execute a macro for each tuple of parameters +/// up to 32 parameters. This is useful to implement traits on functions +/// for may parameter tuples. +/// +/// Usage: +/// ```rust +/// macro_rules! my_macro { +/// ([$count:expr] ($($name:ident: $type:ident),*)) => { +/// // $count is the arity of the tuple +/// // $name is the name of the parameter: p1, p2, ..., p$count +/// // $type is the type of the parameter: P1, P2, ..., P$count +/// }; +/// } +/// +/// for_each_tuple!(impl_host_function); +/// ``` +macro_rules! for_each_tuple { + (@ + $macro:ident + [$count:expr] + [ + $($param_id:ident: $param_ty:ident),* + ] + [] + ) => { + $macro!([$count] ($($param_id: $param_ty),*)); + }; + (@ + $macro:ident + [$count:expr] + [ + $($param_id:ident: $param_ty:ident),* + ] + [ + $first_ident:ident: $first_type:ident + $(, $rest_ident:ident: $rest_type:ident)* + $(,)? + ] + ) => { + $macro!([$count] ($($param_id: $param_ty),*)); + for_each_tuple!(@ + $macro + [$count + 1] + [ + $($param_id: $param_ty, )* + $first_ident: $first_type + ] + [ + $($rest_ident: $rest_type),* + ] + ); + }; + ($macro:ident) => { + for_each_tuple!(@ $macro [0] [] [ + p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, + p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, + p17: P17, p18: P18, p19: P19, p20: P20, p21: P21, p22: P22, p23: P23, p24: P24, + p25: P25, p26: P26, p27: P27, p28: P28, p29: P29, p30: P30, p31: P31, p32: P32, + ]); + }; +} + +pub(super) use for_each_tuple; diff --git a/src/hyperlight_host/src/sandbox/host_funcs.rs b/src/hyperlight_host/src/sandbox/host_funcs.rs index 84baf30df..dbdea7187 100644 --- a/src/hyperlight_host/src/sandbox/host_funcs.rs +++ b/src/hyperlight_host/src/sandbox/host_funcs.rs @@ -22,19 +22,18 @@ use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; use tracing::{instrument, Span}; use super::ExtraAllowedSyscall; -use crate::func::HyperlightFunction; +use crate::func::host_functions::TypeErasedHostFunction; use crate::HyperlightError::HostFunctionNotFound; use crate::{new_error, Result}; -#[derive(Default, Clone)] +#[derive(Default)] /// A Wrapper around details of functions exposed by the Host pub struct FunctionRegistry { functions_map: HashMap, } -#[derive(Clone)] pub struct FunctionEntry { - pub function: HyperlightFunction, + pub function: TypeErasedHostFunction, pub extra_allowed_syscalls: Option>, } @@ -44,7 +43,7 @@ impl FunctionRegistry { pub(crate) fn register_host_function( &mut self, name: String, - func: HyperlightFunction, + func: TypeErasedHostFunction, ) -> Result<()> { self.register_host_function_helper(name, func, None) } @@ -56,7 +55,7 @@ impl FunctionRegistry { pub(crate) fn register_host_function_with_syscalls( &mut self, name: String, - func: HyperlightFunction, + func: TypeErasedHostFunction, extra_allowed_syscalls: Vec, ) -> Result<()> { self.register_host_function_helper(name, func, Some(extra_allowed_syscalls)) @@ -92,7 +91,7 @@ impl FunctionRegistry { fn register_host_function_helper( &mut self, name: String, - function: HyperlightFunction, + function: TypeErasedHostFunction, extra_allowed_syscalls: Option>, ) -> Result<()> { #[cfg(not(all(feature = "seccomp", target_os = "linux")))] @@ -101,6 +100,7 @@ impl FunctionRegistry { "Extra syscalls are only supported on Linux with seccomp" )); } + self.functions_map.insert( name, FunctionEntry { diff --git a/src/hyperlight_host/src/sandbox/uninitialized.rs b/src/hyperlight_host/src/sandbox/uninitialized.rs index caf22b38b..d3614a7ed 100644 --- a/src/hyperlight_host/src/sandbox/uninitialized.rs +++ b/src/hyperlight_host/src/sandbox/uninitialized.rs @@ -29,7 +29,8 @@ use super::host_funcs::{default_writer_func, FunctionRegistry}; use super::mem_mgr::MemMgrWrapper; use super::run_options::SandboxRunOptions; use super::uninitialized_evolve::evolve_impl_multi_use; -use crate::func::host_functions::{HostFunction, IntoHostFunction}; +use crate::func::host_functions::{register_host_function, HostFunction}; +use crate::func::{ParameterTuple, SupportedReturnType}; #[cfg(feature = "build-metadata")] use crate::log_build_details; use crate::mem::exe::ExeInfo; @@ -240,30 +241,29 @@ impl UninitializedSandbox { } /// Register a host function with the given name in the sandbox. - pub fn register(&mut self, name: impl AsRef, host_func: F) -> Result<()> - where - F: IntoHostFunction, - { - host_func.into_host_function().register(self, name.as_ref()) + pub fn register( + &mut self, + name: impl AsRef, + host_func: impl Into>, + ) -> Result<()> { + register_host_function(host_func, self, name.as_ref(), None) } /// Register the host function with the given name in the sandbox. /// Unlike `register`, this variant takes a list of extra syscalls that will /// allowed during the execution of the function handler. #[cfg(all(feature = "seccomp", target_os = "linux"))] - pub fn register_with_extra_allowed_syscalls( + pub fn register_with_extra_allowed_syscalls< + Args: ParameterTuple, + Output: SupportedReturnType, + >( &mut self, name: impl AsRef, - host_func: F, + host_func: impl Into>, extra_allowed_syscalls: impl IntoIterator, - ) -> Result<()> - where - F: IntoHostFunction, - { + ) -> Result<()> { let extra_allowed_syscalls: Vec<_> = extra_allowed_syscalls.into_iter().collect(); - host_func - .into_host_function() - .register_with_extra_allowed_syscalls(self, name.as_ref(), extra_allowed_syscalls) + register_host_function(host_func, self, name.as_ref(), Some(extra_allowed_syscalls)) } /// Register a host function named "HostPrint" that will be called by the guest @@ -272,7 +272,7 @@ impl UninitializedSandbox { /// `FnMut(String) -> i32` signature. pub fn register_print( &mut self, - print_func: impl IntoHostFunction, + print_func: impl Into>, ) -> Result<()> { #[cfg(not(all(target_os = "linux", feature = "seccomp")))] self.register("HostPrint", print_func)?; @@ -296,7 +296,7 @@ impl UninitializedSandbox { #[cfg(all(feature = "seccomp", target_os = "linux"))] pub fn register_print_with_extra_allowed_syscalls( &mut self, - print_func: impl IntoHostFunction, + print_func: impl Into>, extra_allowed_syscalls: impl IntoIterator, ) -> Result<()> { #[cfg(all(target_os = "linux", feature = "seccomp"))] diff --git a/src/hyperlight_host/tests/common/mod.rs b/src/hyperlight_host/tests/common/mod.rs index 716035864..6b0287bc0 100644 --- a/src/hyperlight_host/tests/common/mod.rs +++ b/src/hyperlight_host/tests/common/mod.rs @@ -43,7 +43,7 @@ pub fn new_uninit_rust() -> Result { } pub fn get_simpleguest_sandboxes( - writer: Option<&dyn HostFunction>, // An optional writer to make sure correct info is passed to the host printer + writer: Option>, // An optional writer to make sure correct info is passed to the host printer ) -> Vec { let elf_path = get_c_or_rust_simpleguest_path(); @@ -55,7 +55,7 @@ pub fn get_simpleguest_sandboxes( sandboxes .into_iter() .map(|mut sandbox| { - if let Some(writer) = writer { + if let Some(writer) = writer.clone() { sandbox.register_print(writer).unwrap(); } sandbox.evolve(Noop::default()).unwrap() @@ -64,7 +64,7 @@ pub fn get_simpleguest_sandboxes( } pub fn get_callbackguest_uninit_sandboxes( - writer: Option<&dyn HostFunction>, // An optional writer to make sure correct info is passed to the host printer + writer: Option>, // An optional writer to make sure correct info is passed to the host printer ) -> Vec { let elf_path = get_c_or_rust_callbackguest_path(); @@ -76,7 +76,7 @@ pub fn get_callbackguest_uninit_sandboxes( sandboxes .into_iter() .map(|mut sandbox| { - if let Some(writer) = writer { + if let Some(writer) = writer.clone() { sandbox.register_print(writer).unwrap(); } sandbox diff --git a/src/hyperlight_host/tests/sandbox_host_tests.rs b/src/hyperlight_host/tests/sandbox_host_tests.rs index 6407510df..0c5dd8285 100644 --- a/src/hyperlight_host/tests/sandbox_host_tests.rs +++ b/src/hyperlight_host/tests/sandbox_host_tests.rs @@ -160,17 +160,15 @@ fn set_static() { fn multiple_parameters() { let messages = Arc::new(Mutex::new(Vec::new())); let messages_clone = messages.clone(); - let writer = move |msg| { + let writer = move |msg: String| { let mut lock = messages_clone .try_lock() .map_err(|_| new_error!("Error locking")) .unwrap(); lock.push(msg); - Ok(0) + 0 }; - let writer_func = Arc::new(Mutex::new(writer)); - let test_cases = vec![ ( "PrintTwoArgs", @@ -320,7 +318,7 @@ fn multiple_parameters() { ) ]; - for mut sandbox in get_simpleguest_sandboxes(Some(&writer_func)).into_iter() { + for mut sandbox in get_simpleguest_sandboxes(Some(writer.into())).into_iter() { for (fn_name, args, _expected) in test_cases.clone().into_iter() { let res = sandbox.call_guest_function_by_name(fn_name, ReturnType::Int, Some(args)); println!("{:?}", res); @@ -426,14 +424,13 @@ fn simple_test_helper() -> Result<()> { .map_err(|_| new_error!("Error locking")) .unwrap(); lock.push(msg); - Ok(len as i32) + len as i32 }; let message = "hello"; let message2 = "world"; - let writer_func = Arc::new(Mutex::new(writer)); - for mut sandbox in get_simpleguest_sandboxes(Some(&writer_func)).into_iter() { + for mut sandbox in get_simpleguest_sandboxes(Some(writer.into())).into_iter() { let res = sandbox.call_guest_function_by_name( "PrintOutput", ReturnType::Int,