@@ -20,6 +20,7 @@ use std::os::fd::AsRawFd;
2020#[ cfg( unix) ]
2121use std:: os:: linux:: fs:: MetadataExt ;
2222use std:: path:: Path ;
23+ use std:: sync:: atomic:: { AtomicU64 , Ordering } ;
2324use std:: sync:: { Arc , Mutex } ;
2425
2526use hyperlight_common:: flatbuffer_wrappers:: function_call:: { FunctionCall , FunctionCallType } ;
@@ -31,6 +32,7 @@ use tracing::{Span, instrument};
3132use super :: host_funcs:: FunctionRegistry ;
3233use super :: snapshot:: Snapshot ;
3334use super :: { Callable , MemMgrWrapper , WrapperGetter } ;
35+ use crate :: HyperlightError :: SnapshotSandboxMismatch ;
3436use crate :: func:: guest_err:: check_for_guest_error;
3537use crate :: func:: { ParameterTuple , SupportedReturnType } ;
3638#[ cfg( gdb) ]
@@ -44,6 +46,9 @@ use crate::mem::shared_mem::HostSharedMemory;
4446use crate :: metrics:: maybe_time_and_emit_guest_call;
4547use crate :: { HyperlightError , Result , log_then_return} ;
4648
49+ /// Global counter for assigning unique IDs to sandboxes
50+ static SANDBOX_ID_COUNTER : AtomicU64 = AtomicU64 :: new ( 0 ) ;
51+
4752/// A sandbox that supports being used Multiple times.
4853/// The implication of being used multiple times is two-fold:
4954///
@@ -53,6 +58,8 @@ use crate::{HyperlightError, Result, log_then_return};
5358/// 2. A MultiUseGuestCallContext can be created from the sandbox and used to make multiple guest function calls to the Sandbox.
5459/// in this case the state of the sandbox is not reset until the context is finished and the `MultiUseSandbox` is returned.
5560pub struct MultiUseSandbox {
61+ /// Unique identifier for this sandbox instance
62+ id : u64 ,
5663 // 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`.
5764 pub ( super ) _host_funcs : Arc < Mutex < FunctionRegistry > > ,
5865 pub ( crate ) mem_mgr : MemMgrWrapper < HostSharedMemory > ,
@@ -77,6 +84,7 @@ impl MultiUseSandbox {
7784 #[ cfg( gdb) ] dbg_mem_access_fn : DbgMemAccessHandlerWrapper ,
7885 ) -> MultiUseSandbox {
7986 Self {
87+ id : SANDBOX_ID_COUNTER . fetch_add ( 1 , Ordering :: Relaxed ) ,
8088 _host_funcs : host_funcs,
8189 mem_mgr : mgr,
8290 vm,
@@ -91,7 +99,10 @@ impl MultiUseSandbox {
9199 pub fn snapshot ( & mut self ) -> Result < Snapshot > {
92100 let mapped_regions_iter = self . vm . get_mapped_regions ( ) ;
93101 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) ?;
95106 Ok ( Snapshot {
96107 inner : memory_snapshot,
97108 } )
@@ -100,6 +111,10 @@ impl MultiUseSandbox {
100111 /// Restore the sandbox's memory to the state captured in the given snapshot.
101112 #[ instrument( err( Debug ) , skip_all, parent = Span :: current( ) ) ]
102113 pub fn restore ( & mut self , snapshot : & Snapshot ) -> Result < ( ) > {
114+ if self . id != snapshot. inner . sandbox_id ( ) {
115+ return Err ( SnapshotSandboxMismatch ) ;
116+ }
117+
103118 self . mem_mgr
104119 . unwrap_mgr_mut ( )
105120 . restore_snapshot ( & snapshot. inner ) ?;
@@ -765,4 +780,36 @@ mod tests {
765780 err
766781 ) ;
767782 }
783+
784+ #[ test]
785+ fn snapshot_different_sandbox ( ) {
786+ let mut sandbox = {
787+ let path = simple_guest_as_string ( ) . unwrap ( ) ;
788+ let u_sbox = UninitializedSandbox :: new ( GuestBinary :: FilePath ( path) , None ) . unwrap ( ) ;
789+ u_sbox. evolve ( ) . unwrap ( )
790+ } ;
791+
792+ let mut sandbox2 = {
793+ let path = simple_guest_as_string ( ) . unwrap ( ) ;
794+ let u_sbox = UninitializedSandbox :: new ( GuestBinary :: FilePath ( path) , None ) . unwrap ( ) ;
795+ u_sbox. evolve ( ) . unwrap ( )
796+ } ;
797+ assert_ne ! ( sandbox. id, sandbox2. id) ;
798+
799+ let snapshot = sandbox. snapshot ( ) . unwrap ( ) ;
800+ let err = sandbox2. restore ( & snapshot) ;
801+ assert ! ( matches!( err, Err ( HyperlightError :: SnapshotSandboxMismatch ) ) ) ;
802+
803+ let sandbox_id = sandbox. id ;
804+ drop ( sandbox) ;
805+ drop ( sandbox2) ;
806+ drop ( snapshot) ;
807+
808+ let sandbox3 = {
809+ let path = simple_guest_as_string ( ) . unwrap ( ) ;
810+ let u_sbox = UninitializedSandbox :: new ( GuestBinary :: FilePath ( path) , None ) . unwrap ( ) ;
811+ u_sbox. evolve ( ) . unwrap ( )
812+ } ;
813+ assert_ne ! ( sandbox3. id, sandbox_id) ;
814+ }
768815}
0 commit comments