@@ -20,6 +20,7 @@ use std::os::fd::AsRawFd;
20
20
#[ cfg( unix) ]
21
21
use std:: os:: linux:: fs:: MetadataExt ;
22
22
use std:: path:: Path ;
23
+ use std:: sync:: atomic:: { AtomicU64 , Ordering } ;
23
24
use std:: sync:: { Arc , Mutex } ;
24
25
25
26
use hyperlight_common:: flatbuffer_wrappers:: function_call:: { FunctionCall , FunctionCallType } ;
@@ -31,6 +32,7 @@ use tracing::{Span, instrument};
31
32
use super :: host_funcs:: FunctionRegistry ;
32
33
use super :: snapshot:: Snapshot ;
33
34
use super :: { Callable , MemMgrWrapper , WrapperGetter } ;
35
+ use crate :: HyperlightError :: SnapshotSandboxMismatch ;
34
36
use crate :: func:: guest_err:: check_for_guest_error;
35
37
use crate :: func:: { ParameterTuple , SupportedReturnType } ;
36
38
#[ cfg( gdb) ]
@@ -44,6 +46,9 @@ use crate::mem::shared_mem::HostSharedMemory;
44
46
use crate :: metrics:: maybe_time_and_emit_guest_call;
45
47
use crate :: { HyperlightError , Result , log_then_return} ;
46
48
49
+ /// Global counter for assigning unique IDs to sandboxes
50
+ static SANDBOX_ID_COUNTER : AtomicU64 = AtomicU64 :: new ( 0 ) ;
51
+
47
52
/// A sandbox that supports being used Multiple times.
48
53
/// The implication of being used multiple times is two-fold:
49
54
///
@@ -53,6 +58,8 @@ use crate::{HyperlightError, Result, log_then_return};
53
58
/// 2. A MultiUseGuestCallContext can be created from the sandbox and used to make multiple guest function calls to the Sandbox.
54
59
/// in this case the state of the sandbox is not reset until the context is finished and the `MultiUseSandbox` is returned.
55
60
pub struct MultiUseSandbox {
61
+ /// Unique identifier for this sandbox instance
62
+ id : u64 ,
56
63
// We need to keep a reference to the host functions, even if the compiler marks it as unused. The compiler cannot detect our dynamic usages of the host function in `HyperlightFunction::call`.
57
64
pub ( super ) _host_funcs : Arc < Mutex < FunctionRegistry > > ,
58
65
pub ( crate ) mem_mgr : MemMgrWrapper < HostSharedMemory > ,
@@ -77,6 +84,7 @@ impl MultiUseSandbox {
77
84
#[ cfg( gdb) ] dbg_mem_access_fn : DbgMemAccessHandlerWrapper ,
78
85
) -> MultiUseSandbox {
79
86
Self {
87
+ id : SANDBOX_ID_COUNTER . fetch_add ( 1 , Ordering :: Relaxed ) ,
80
88
_host_funcs : host_funcs,
81
89
mem_mgr : mgr,
82
90
vm,
@@ -91,7 +99,10 @@ impl MultiUseSandbox {
91
99
pub fn snapshot ( & mut self ) -> Result < Snapshot > {
92
100
let mapped_regions_iter = self . vm . get_mapped_regions ( ) ;
93
101
let mapped_regions_vec: Vec < MemoryRegion > = mapped_regions_iter. cloned ( ) . collect ( ) ;
94
- let memory_snapshot = self . mem_mgr . unwrap_mgr_mut ( ) . snapshot ( mapped_regions_vec) ?;
102
+ let memory_snapshot = self
103
+ . mem_mgr
104
+ . unwrap_mgr_mut ( )
105
+ . snapshot ( self . id , mapped_regions_vec) ?;
95
106
Ok ( Snapshot {
96
107
inner : memory_snapshot,
97
108
} )
@@ -100,6 +111,10 @@ impl MultiUseSandbox {
100
111
/// Restore the sandbox's memory to the state captured in the given snapshot.
101
112
#[ instrument( err( Debug ) , skip_all, parent = Span :: current( ) ) ]
102
113
pub fn restore ( & mut self , snapshot : & Snapshot ) -> Result < ( ) > {
114
+ if self . id != snapshot. inner . sandbox_id ( ) {
115
+ return Err ( SnapshotSandboxMismatch ) ;
116
+ }
117
+
103
118
self . mem_mgr
104
119
. unwrap_mgr_mut ( )
105
120
. restore_snapshot ( & snapshot. inner ) ?;
@@ -708,4 +723,36 @@ mod tests {
708
723
err
709
724
) ;
710
725
}
726
+
727
+ #[ test]
728
+ fn snapshot_different_sandbox ( ) {
729
+ let mut sandbox = {
730
+ let path = simple_guest_as_string ( ) . unwrap ( ) ;
731
+ let u_sbox = UninitializedSandbox :: new ( GuestBinary :: FilePath ( path) , None ) . unwrap ( ) ;
732
+ u_sbox. evolve ( ) . unwrap ( )
733
+ } ;
734
+
735
+ let mut sandbox2 = {
736
+ let path = simple_guest_as_string ( ) . unwrap ( ) ;
737
+ let u_sbox = UninitializedSandbox :: new ( GuestBinary :: FilePath ( path) , None ) . unwrap ( ) ;
738
+ u_sbox. evolve ( ) . unwrap ( )
739
+ } ;
740
+ assert_ne ! ( sandbox. id, sandbox2. id) ;
741
+
742
+ let snapshot = sandbox. snapshot ( ) . unwrap ( ) ;
743
+ let err = sandbox2. restore ( & snapshot) ;
744
+ assert ! ( matches!( err, Err ( HyperlightError :: SnapshotSandboxMismatch ) ) ) ;
745
+
746
+ let sandbox_id = sandbox. id ;
747
+ drop ( sandbox) ;
748
+ drop ( sandbox2) ;
749
+ drop ( snapshot) ;
750
+
751
+ let sandbox3 = {
752
+ let path = simple_guest_as_string ( ) . unwrap ( ) ;
753
+ let u_sbox = UninitializedSandbox :: new ( GuestBinary :: FilePath ( path) , None ) . unwrap ( ) ;
754
+ u_sbox. evolve ( ) . unwrap ( )
755
+ } ;
756
+ assert_ne ! ( sandbox3. id, sandbox_id) ;
757
+ }
711
758
}
0 commit comments