hyperlight_host/sandbox/
mod.rs1pub mod config;
19mod host_funcs;
21pub(crate) mod hypervisor;
23pub mod initialized_multi_use;
26#[cfg(inprocess)]
31pub(crate) mod leaked_outb;
32pub(crate) mod mem_access;
35pub(crate) mod mem_mgr;
38pub(crate) mod outb;
39mod run_options;
41pub mod uninitialized;
44pub(crate) mod uninitialized_evolve;
47
48use std::collections::HashMap;
49
50pub use config::SandboxConfiguration;
52pub use initialized_multi_use::MultiUseSandbox;
54pub use run_options::SandboxRunOptions;
56use tracing::{instrument, Span};
57pub use uninitialized::GuestBinary;
59pub use uninitialized::UninitializedSandbox;
61
62use self::mem_mgr::MemMgrWrapper;
63use crate::func::HyperlightFunction;
64use crate::hypervisor::hypervisor_handler::HypervisorHandler;
65#[cfg(target_os = "windows")]
66use crate::hypervisor::windows_hypervisor_platform;
67use crate::mem::shared_mem::HostSharedMemory;
68
69#[instrument(skip_all, parent = Span::current())]
78pub fn is_supported_platform() -> bool {
79 #[cfg(not(target_os = "linux"))]
80 #[cfg(not(target_os = "windows"))]
81 return false;
82
83 true
84}
85
86pub type ExtraAllowedSyscall = i64;
88
89#[derive(Clone, Default)]
94pub(super) struct FunctionsMap(
95 HashMap<String, (HyperlightFunction, Option<Vec<ExtraAllowedSyscall>>)>,
96);
97
98impl FunctionsMap {
99 pub(super) fn insert(
101 &mut self,
102 key: String,
103 value: HyperlightFunction,
104 extra_syscalls: Option<Vec<ExtraAllowedSyscall>>,
105 ) {
106 self.0.insert(key, (value, extra_syscalls));
107 }
108
109 pub(super) fn get(
111 &self,
112 key: &str,
113 ) -> Option<&(HyperlightFunction, Option<Vec<ExtraAllowedSyscall>>)> {
114 self.0.get(key)
115 }
116
117 fn len(&self) -> usize {
119 self.0.len()
120 }
121}
122
123impl PartialEq for FunctionsMap {
124 #[instrument(skip_all, parent = Span::current(), level= "Trace")]
125 fn eq(&self, other: &Self) -> bool {
126 self.len() == other.len() && self.0.keys().all(|k| other.0.contains_key(k))
127 }
128}
129
130impl Eq for FunctionsMap {}
131
132#[instrument(skip_all, parent = Span::current())]
137pub fn is_hypervisor_present() -> bool {
138 hypervisor::get_available_hypervisor().is_some()
139}
140
141pub(crate) trait WrapperGetter {
142 #[allow(dead_code)]
143 fn get_mgr_wrapper(&self) -> &MemMgrWrapper<HostSharedMemory>;
144 fn get_mgr_wrapper_mut(&mut self) -> &mut MemMgrWrapper<HostSharedMemory>;
145 fn get_hv_handler(&self) -> &HypervisorHandler;
146 #[allow(dead_code)]
147 fn get_hv_handler_mut(&mut self) -> &mut HypervisorHandler;
148}
149
150#[cfg(test)]
151mod tests {
152 use std::sync::Arc;
153 use std::thread;
154
155 use crossbeam_queue::ArrayQueue;
156 use hyperlight_testing::simple_guest_as_string;
157
158 use crate::sandbox::uninitialized::GuestBinary;
159 use crate::sandbox_state::sandbox::EvolvableSandbox;
160 use crate::sandbox_state::transition::Noop;
161 use crate::{new_error, MultiUseSandbox, UninitializedSandbox};
162
163 #[test]
164 #[cfg(target_os = "linux")]
166 fn is_hypervisor_present() {
167 use std::path::Path;
168
169 cfg_if::cfg_if! {
170 if #[cfg(all(kvm, mshv))] {
171 assert_eq!(Path::new("/dev/kvm").exists() || Path::new("/dev/mshv").exists(), super::is_hypervisor_present());
172 } else if #[cfg(kvm)] {
173 assert_eq!(Path::new("/dev/kvm").exists(), super::is_hypervisor_present());
174 } else if #[cfg(mshv)] {
175 assert_eq!(Path::new("/dev/mshv").exists(), super::is_hypervisor_present());
176 } else {
177 assert!(!super::is_hypervisor_present());
178 }
179 }
180 }
181
182 #[test]
183 fn check_create_and_use_sandbox_on_different_threads() {
184 let unintializedsandbox_queue = Arc::new(ArrayQueue::<UninitializedSandbox>::new(10));
185 let sandbox_queue = Arc::new(ArrayQueue::<MultiUseSandbox>::new(10));
186
187 for i in 0..10 {
188 let simple_guest_path = simple_guest_as_string().expect("Guest Binary Missing");
189 let unintializedsandbox = UninitializedSandbox::new(
190 GuestBinary::FilePath(simple_guest_path),
191 None,
192 None,
193 None,
194 )
195 .unwrap_or_else(|_| panic!("Failed to create UninitializedSandbox {}", i));
196
197 unintializedsandbox_queue
198 .push(unintializedsandbox)
199 .unwrap_or_else(|_| panic!("Failed to push UninitializedSandbox {}", i));
200 }
201
202 let thread_handles = (0..10)
203 .map(|i| {
204 let uq = unintializedsandbox_queue.clone();
205 let sq = sandbox_queue.clone();
206 thread::spawn(move || {
207 let uninitialized_sandbox = uq.pop().unwrap_or_else(|| {
208 panic!("Failed to pop UninitializedSandbox thread {}", i)
209 });
210 let host_funcs = uninitialized_sandbox
211 .host_funcs
212 .try_lock()
213 .map_err(|_| new_error!("Error locking"));
214
215 assert!(host_funcs.is_ok());
216
217 host_funcs
218 .unwrap()
219 .host_print(format!(
220 "Printing from UninitializedSandbox on Thread {}\n",
221 i
222 ))
223 .unwrap();
224
225 let sandbox = uninitialized_sandbox
226 .evolve(Noop::default())
227 .unwrap_or_else(|_| {
228 panic!("Failed to initialize UninitializedSandbox thread {}", i)
229 });
230
231 sq.push(sandbox).unwrap_or_else(|_| {
232 panic!("Failed to push UninitializedSandbox thread {}", i)
233 })
234 })
235 })
236 .collect::<Vec<_>>();
237
238 for handle in thread_handles {
239 handle.join().unwrap();
240 }
241
242 let thread_handles = (0..10)
243 .map(|i| {
244 let sq = sandbox_queue.clone();
245 thread::spawn(move || {
246 let sandbox = sq
247 .pop()
248 .unwrap_or_else(|| panic!("Failed to pop Sandbox thread {}", i));
249 let host_funcs = sandbox
250 ._host_funcs
251 .try_lock()
252 .map_err(|_| new_error!("Error locking"));
253
254 assert!(host_funcs.is_ok());
255
256 host_funcs
257 .unwrap()
258 .host_print(format!("Print from Sandbox on Thread {}\n", i))
259 .unwrap();
260 })
261 })
262 .collect::<Vec<_>>();
263
264 for handle in thread_handles {
265 handle.join().unwrap();
266 }
267 }
268}