1use std::sync::{Arc, Mutex};
18
19use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnValue};
20
21use super::utils::for_each_tuple;
22use super::{ParameterTuple, ResultType, SupportedReturnType};
23use crate::sandbox::host_funcs::FunctionEntry;
24use crate::sandbox::{ExtraAllowedSyscall, UninitializedSandbox};
25use crate::{Result, new_error};
26
27pub trait Registerable {
30 fn register_host_function<Args: ParameterTuple, Output: SupportedReturnType>(
32 &mut self,
33 name: &str,
34 hf: impl Into<HostFunction<Output, Args>>,
35 ) -> Result<()>;
36 #[cfg(all(feature = "seccomp", target_os = "linux"))]
39 fn register_host_function_with_syscalls<Args: ParameterTuple, Output: SupportedReturnType>(
40 &mut self,
41 name: &str,
42 hf: impl Into<HostFunction<Output, Args>>,
43 eas: Vec<ExtraAllowedSyscall>,
44 ) -> Result<()>;
45}
46impl Registerable for UninitializedSandbox {
47 fn register_host_function<Args: ParameterTuple, Output: SupportedReturnType>(
48 &mut self,
49 name: &str,
50 hf: impl Into<HostFunction<Output, Args>>,
51 ) -> Result<()> {
52 let mut hfs = self
53 .host_funcs
54 .try_lock()
55 .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?;
56
57 let entry = FunctionEntry {
58 function: hf.into().into(),
59 extra_allowed_syscalls: None,
60 parameter_types: Args::TYPE,
61 return_type: Output::TYPE,
62 };
63
64 (*hfs).register_host_function(name.to_string(), entry, self.mgr.unwrap_mgr_mut())
65 }
66 #[cfg(all(feature = "seccomp", target_os = "linux"))]
67 fn register_host_function_with_syscalls<Args: ParameterTuple, Output: SupportedReturnType>(
68 &mut self,
69 name: &str,
70 hf: impl Into<HostFunction<Output, Args>>,
71 eas: Vec<ExtraAllowedSyscall>,
72 ) -> Result<()> {
73 let mut hfs = self
74 .host_funcs
75 .try_lock()
76 .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?;
77
78 let entry = FunctionEntry {
79 function: hf.into().into(),
80 extra_allowed_syscalls: Some(eas),
81 parameter_types: Args::TYPE,
82 return_type: Output::TYPE,
83 };
84
85 (*hfs).register_host_function(name.to_string(), entry, self.mgr.unwrap_mgr_mut())
86 }
87}
88
89#[derive(Clone)]
92pub struct HostFunction<Output, Args>
93where
94 Args: ParameterTuple,
95 Output: SupportedReturnType,
96{
97 func: Arc<dyn Fn(Args) -> Result<Output> + Send + Sync + 'static>,
122}
123
124pub(crate) struct TypeErasedHostFunction {
125 func: Box<dyn Fn(Vec<ParameterValue>) -> Result<ReturnValue> + Send + Sync + 'static>,
126}
127
128impl<Args, Output> HostFunction<Output, Args>
129where
130 Args: ParameterTuple,
131 Output: SupportedReturnType,
132{
133 pub fn call(&self, args: Args) -> Result<Output> {
135 (self.func)(args)
136 }
137}
138
139impl TypeErasedHostFunction {
140 pub(crate) fn call(&self, args: Vec<ParameterValue>) -> Result<ReturnValue> {
141 (self.func)(args)
142 }
143}
144
145impl<Args, Output> From<HostFunction<Output, Args>> for TypeErasedHostFunction
146where
147 Args: ParameterTuple,
148 Output: SupportedReturnType,
149{
150 fn from(func: HostFunction<Output, Args>) -> TypeErasedHostFunction {
151 TypeErasedHostFunction {
152 func: Box::new(move |args: Vec<ParameterValue>| {
153 let args = Args::from_value(args)?;
154 Ok(func.call(args)?.into_value())
155 }),
156 }
157 }
158}
159
160macro_rules! impl_host_function {
161 ([$N:expr] ($($p:ident: $P:ident),*)) => {
162 impl<F, R, $($P),*> From<F> for HostFunction<R::ReturnType, ($($P,)*)>
170 where
171 F: FnMut($($P),*) -> R + Send + 'static,
172 ($($P,)*): ParameterTuple,
173 R: ResultType,
174 {
175 fn from(mut func: F) -> HostFunction<R::ReturnType, ($($P,)*)> {
176 let func = move |($($p,)*): ($($P,)*)| -> Result<R::ReturnType> {
177 func($($p),*).into_result()
178 };
179 let func = Mutex::new(func);
180 HostFunction {
181 func: Arc::new(move |args: ($($P,)*)| {
182 func.try_lock()
183 .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?
184 (args)
185 })
186 }
187 }
188 }
189 };
190}
191
192for_each_tuple!(impl_host_function);
193
194pub(crate) fn register_host_function<Args: ParameterTuple, Output: SupportedReturnType>(
195 func: impl Into<HostFunction<Output, Args>>,
196 sandbox: &mut UninitializedSandbox,
197 name: &str,
198 extra_allowed_syscalls: Option<Vec<ExtraAllowedSyscall>>,
199) -> Result<()> {
200 let func = func.into().into();
201
202 let entry = FunctionEntry {
203 function: func,
204 extra_allowed_syscalls: extra_allowed_syscalls.clone(),
205 parameter_types: Args::TYPE,
206 return_type: Output::TYPE,
207 };
208
209 sandbox
210 .host_funcs
211 .try_lock()
212 .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?
213 .register_host_function(name.to_string(), entry, sandbox.mgr.unwrap_mgr_mut())?;
214
215 Ok(())
216}