Skip to main content

hyperlight_host/sandbox/
mod.rs

1/*
2Copyright 2025  The Hyperlight Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17/// Configuration needed to establish a sandbox.
18pub mod config;
19/// Host-side file mapping preparation for `map_file_cow`.
20pub(crate) mod file_mapping;
21/// Functionality for reading, but not modifying host functions
22pub(crate) mod host_funcs;
23/// Functionality for dealing with initialized sandboxes that can
24/// call 0 or more guest functions
25pub mod initialized_multi_use;
26pub(crate) mod outb;
27/// Functionality for creating uninitialized sandboxes, manipulating them,
28/// and converting them to initialized sandboxes.
29pub mod uninitialized;
30/// Functionality for properly converting `UninitializedSandbox`es to
31/// initialized `Sandbox`es.
32pub(crate) mod uninitialized_evolve;
33
34/// Representation of a snapshot of a `Sandbox`.
35pub mod snapshot;
36
37/// Trait used by the macros to paper over the differences between hyperlight and hyperlight-wasm
38mod callable;
39
40/// Module for tracing guest execution
41#[cfg(feature = "trace_guest")]
42pub(crate) mod trace;
43
44/// Trait used by the macros to paper over the differences between hyperlight and hyperlight-wasm
45pub use callable::Callable;
46/// Re-export for `SandboxConfiguration` type
47pub use config::SandboxConfiguration;
48/// Re-export for the `MultiUseSandbox` type
49pub use initialized_multi_use::{MultiUseSandbox, PtRootFinder};
50/// Re-export for `GuestBinary` type
51pub use uninitialized::GuestBinary;
52/// Re-export for `UninitializedSandbox` type
53pub use uninitialized::UninitializedSandbox;
54
55#[cfg(test)]
56mod tests {
57    use std::sync::Arc;
58    use std::thread;
59
60    use crossbeam_queue::ArrayQueue;
61    use hyperlight_testing::simple_guest_as_string;
62
63    use crate::sandbox::uninitialized::GuestBinary;
64    use crate::{MultiUseSandbox, UninitializedSandbox, new_error};
65
66    #[test]
67    fn check_create_and_use_sandbox_on_different_threads() {
68        let unintializedsandbox_queue = Arc::new(ArrayQueue::<UninitializedSandbox>::new(10));
69        let sandbox_queue = Arc::new(ArrayQueue::<MultiUseSandbox>::new(10));
70
71        for i in 0..10 {
72            let simple_guest_path = simple_guest_as_string().expect("Guest Binary Missing");
73            let unintializedsandbox =
74                UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_path), None)
75                    .unwrap_or_else(|_| panic!("Failed to create UninitializedSandbox {}", i));
76
77            unintializedsandbox_queue
78                .push(unintializedsandbox)
79                .unwrap_or_else(|_| panic!("Failed to push UninitializedSandbox {}", i));
80        }
81
82        let thread_handles = (0..10)
83            .map(|i| {
84                let uq = unintializedsandbox_queue.clone();
85                let sq = sandbox_queue.clone();
86                thread::spawn(move || {
87                    let uninitialized_sandbox = uq.pop().unwrap_or_else(|| {
88                        panic!("Failed to pop UninitializedSandbox thread {}", i)
89                    });
90                    let host_funcs = uninitialized_sandbox
91                        .host_funcs
92                        .try_lock()
93                        .map_err(|_| new_error!("Error locking"));
94
95                    assert!(host_funcs.is_ok());
96
97                    host_funcs
98                        .unwrap()
99                        .host_print(format!(
100                            "Printing from UninitializedSandbox on Thread {}\n",
101                            i
102                        ))
103                        .unwrap();
104
105                    let sandbox = uninitialized_sandbox.evolve().unwrap_or_else(|_| {
106                        panic!("Failed to initialize UninitializedSandbox thread {}", i)
107                    });
108
109                    sq.push(sandbox).unwrap_or_else(|_| {
110                        panic!("Failed to push UninitializedSandbox thread {}", i)
111                    })
112                })
113            })
114            .collect::<Vec<_>>();
115
116        for handle in thread_handles {
117            handle.join().unwrap();
118        }
119
120        let thread_handles = (0..10)
121            .map(|i| {
122                let sq = sandbox_queue.clone();
123                thread::spawn(move || {
124                    let sandbox = sq
125                        .pop()
126                        .unwrap_or_else(|| panic!("Failed to pop Sandbox thread {}", i));
127                    let host_funcs = sandbox
128                        .host_funcs
129                        .try_lock()
130                        .map_err(|_| new_error!("Error locking"));
131
132                    assert!(host_funcs.is_ok());
133
134                    host_funcs
135                        .unwrap()
136                        .host_print(format!("Print from Sandbox on Thread {}\n", i))
137                        .unwrap();
138                })
139            })
140            .collect::<Vec<_>>();
141
142        for handle in thread_handles {
143            handle.join().unwrap();
144        }
145    }
146}