@@ -14,15 +14,18 @@ See the License for the specific language governing permissions and
1414limitations under the License. 
1515*/ 
1616
17+ use  std:: collections:: HashMap ; 
1718use  std:: fmt:: Debug ; 
1819use  std:: option:: Option ; 
1920use  std:: path:: Path ; 
2021use  std:: sync:: { Arc ,  Mutex } ; 
22+ #[ cfg( target_os = "linux" ) ]  
23+ use  std:: time:: Duration ; 
2124
2225use  log:: LevelFilter ; 
2326use  tracing:: { Span ,  instrument} ; 
2427
25- use  super :: host_funcs:: { FunctionRegistry ,  default_writer_func} ; 
28+ use  super :: host_funcs:: { FunctionEntry ,   FunctionRegistry ,  default_writer_func} ; 
2629use  super :: mem_mgr:: MemMgrWrapper ; 
2730use  super :: uninitialized_evolve:: evolve_impl_multi_use; 
2831use  crate :: func:: host_functions:: { HostFunction ,  register_host_function} ; 
@@ -34,6 +37,8 @@ use crate::mem::memory_region::{DEFAULT_GUEST_BLOB_MEM_FLAGS, MemoryRegionFlags}
3437use  crate :: mem:: mgr:: { STACK_COOKIE_LEN ,  SandboxMemoryManager } ; 
3538use  crate :: mem:: shared_mem:: ExclusiveSharedMemory ; 
3639use  crate :: sandbox:: SandboxConfiguration ; 
40+ #[ cfg( gdb) ]  
41+ use  crate :: sandbox:: config:: DebugInfo ; 
3742use  crate :: { MultiUseSandbox ,  Result ,  new_error} ; 
3843
3944#[ cfg( all( target_os = "linux" ,  feature = "seccomp" ) ) ]  
@@ -69,6 +74,8 @@ pub(crate) struct SandboxRuntimeConfig {
6974/// host-implemented functions you need to be available to the guest, then 
7075/// call  `evolve` to transform your 
7176/// `UninitializedSandbox` into an initialized `Sandbox`. 
77+ #[ doc( hidden) ]  
78+ //TODO: deprecate this #[deprecated(since = "0.8.0", note = "Deprecated in favour of Builder")] 
7279pub  struct  UninitializedSandbox  { 
7380    /// Registered host functions 
7481pub ( crate )  host_funcs :  Arc < Mutex < FunctionRegistry > > , 
@@ -81,6 +88,212 @@ pub struct UninitializedSandbox {
8188    pub ( crate )  load_info :  crate :: mem:: exe:: LoadInfo , 
8289} 
8390
91+ /// A builder for `Sandbox`. 
92+ /// This builder allows you to configure the sandbox, and register host functions. 
93+ #[ derive( Default ) ]  
94+ pub  struct  Builder  { 
95+     config :  SandboxConfiguration , 
96+     host_functions :  HashMap < String ,  FunctionEntry > , 
97+ } 
98+ 
99+ impl  Builder  { 
100+     /// The default size of input data 
101+ pub  const  DEFAULT_INPUT_SIZE :  usize  = SandboxConfiguration :: DEFAULT_INPUT_SIZE ; 
102+     /// The minimum size of input data 
103+ pub  const  MIN_INPUT_SIZE :  usize  = SandboxConfiguration :: MIN_INPUT_SIZE ; 
104+     /// The default size of output data 
105+ pub  const  DEFAULT_OUTPUT_SIZE :  usize  = SandboxConfiguration :: DEFAULT_OUTPUT_SIZE ; 
106+     /// The minimum size of output data 
107+ pub  const  MIN_OUTPUT_SIZE :  usize  = SandboxConfiguration :: MIN_OUTPUT_SIZE ; 
108+     /// The default size of host function definitionsSET 
109+ /// Host function definitions has its own page in memory, in order to be READ-ONLY 
110+ /// from a guest's perspective. 
111+ pub  const  DEFAULT_HOST_FUNCTION_DEFINITION_SIZE :  usize  =
112+         SandboxConfiguration :: DEFAULT_HOST_FUNCTION_DEFINITION_SIZE ; 
113+     /// The minimum size of host function definitions 
114+ pub  const  MIN_HOST_FUNCTION_DEFINITION_SIZE :  usize  =
115+         SandboxConfiguration :: MIN_HOST_FUNCTION_DEFINITION_SIZE ; 
116+     /// The default interrupt retry delay 
117+ #[ cfg( target_os = "linux" ) ]  
118+     pub  const  DEFAULT_INTERRUPT_RETRY_DELAY :  Duration  =
119+         SandboxConfiguration :: DEFAULT_INTERRUPT_RETRY_DELAY ; 
120+     /// The default signal offset from `SIGRTMIN` used to determine the signal number for interrupting 
121+ #[ cfg( target_os = "linux" ) ]  
122+     pub  const  INTERRUPT_VCPU_SIGRTMIN_OFFSET :  u8  =
123+         SandboxConfiguration :: INTERRUPT_VCPU_SIGRTMIN_OFFSET ; 
124+ 
125+     /// Set the size of the memory buffer that is made available for serialising host function definitions 
126+ /// the minimum value is MIN_HOST_FUNCTION_DEFINITION_SIZE 
127+ pub  fn  host_function_definition_size ( & mut  self ,  bytes :  usize )  -> & mut  Self  { 
128+         self . config . set_host_function_definition_size ( bytes) ; 
129+         self 
130+     } 
131+ 
132+     /// Set the size of the memory buffer that is made available for input to the guest 
133+ /// the minimum value is MIN_INPUT_SIZE 
134+ pub  fn  input_data_size ( & mut  self ,  bytes :  usize )  -> & mut  Self  { 
135+         self . config . set_input_data_size ( bytes) ; 
136+         self 
137+     } 
138+ 
139+     /// Set the size of the memory buffer that is made available for output from the guest 
140+ /// the minimum value is MIN_OUTPUT_SIZE 
141+ pub  fn  output_data_size ( & mut  self ,  output_data_size :  usize )  -> & mut  Self  { 
142+         self . config . set_output_data_size ( output_data_size) ; 
143+         self 
144+     } 
145+ 
146+     /// Set the stack size to use in the guest sandbox. 
147+ /// If set to 0, the stack size will be determined from the PE file header 
148+ pub  fn  stack_size ( & mut  self ,  bytes :  usize )  -> & mut  Self  { 
149+         self . config . set_stack_size ( bytes as  u64 ) ; 
150+         self 
151+     } 
152+ 
153+     /// Set the heap size to use in the guest sandbox. 
154+ /// If set to 0, the heap size will be determined from the PE file header 
155+ pub  fn  heap_size ( & mut  self ,  bytes :  usize )  -> & mut  Self  { 
156+         self . config . set_heap_size ( bytes as  u64 ) ; 
157+         self 
158+     } 
159+ 
160+     /// Sets the interrupt retry delay 
161+ #[ cfg( target_os = "linux" ) ]  
162+     pub  fn  interrupt_retry_delay ( & mut  self ,  delay :  Duration )  -> & mut  Self  { 
163+         self . config . set_interrupt_retry_delay ( delay) ; 
164+         self 
165+     } 
166+ 
167+     /// Sets the offset from `SIGRTMIN` to determine the real-time signal used for 
168+ /// interrupting the VCPU thread. 
169+ /// 
170+ /// The final signal number is computed as `SIGRTMIN + offset`, and it must fall within 
171+ /// the valid range of real-time signals supported by the host system. 
172+ /// 
173+ /// Returns an error if the offset exceeds the maximum real-time signal number. 
174+ #[ cfg( target_os = "linux" ) ]  
175+     pub  fn  interrupt_vcpu_sigrtmin_offset ( & mut  self ,  offset :  u8 )  -> Result < & mut  Self >  { 
176+         self . config . set_interrupt_vcpu_sigrtmin_offset ( offset) ?; 
177+         Ok ( self ) 
178+     } 
179+ 
180+     /// Enables the guest core dump generation for a sandbox 
181+ #[ cfg( crashdump) ]  
182+     pub  fn  enable_core_dump ( & mut  self )  -> & mut  Self  { 
183+         self . config . set_guest_core_dump ( true ) ; 
184+         self 
185+     } 
186+ 
187+     /// Sets the configuration for the guest debug 
188+ #[ cfg( gdb) ]  
189+     pub  fn  debug_info ( & mut  self ,  debug_info :  DebugInfo )  -> & mut  Self  { 
190+         self . config . set_guest_debug_info ( debug_info) ; 
191+         self 
192+     } 
193+ 
194+     /// Register a host function with the given name in the sandbox. 
195+ pub  fn  register < Args :  ParameterTuple ,  Output :  SupportedReturnType > ( 
196+         & mut  self , 
197+         name :  impl  AsRef < str > , 
198+         host_func :  impl  Into < HostFunction < Output ,  Args > > , 
199+     )  -> & mut  Self  { 
200+         let  name = name. as_ref ( ) . to_string ( ) ; 
201+         let  entry = FunctionEntry  { 
202+             function :  host_func. into ( ) . into ( ) , 
203+             extra_allowed_syscalls :  None , 
204+             parameter_types :  Args :: TYPE , 
205+             return_type :  Output :: TYPE , 
206+         } ; 
207+         self . host_functions . insert ( name,  entry) ; 
208+         self 
209+     } 
210+ 
211+     /// Register the host function with the given name in the sandbox. 
212+ /// Unlike `register`, this variant takes a list of extra syscalls that will 
213+ /// allowed during the execution of the function handler. 
214+ #[ cfg( all( feature = "seccomp" ,  target_os = "linux" ) ) ]  
215+     pub  fn  register_with_syscalls < Args :  ParameterTuple ,  Output :  SupportedReturnType > ( 
216+         & mut  self , 
217+         name :  impl  AsRef < str > , 
218+         host_func :  impl  Into < HostFunction < Output ,  Args > > , 
219+         extra_allowed_syscalls :  impl  IntoIterator < Item  = crate :: sandbox:: ExtraAllowedSyscall > , 
220+     )  -> & mut  Self  { 
221+         let  name = name. as_ref ( ) . to_string ( ) ; 
222+         let  entry = FunctionEntry  { 
223+             function :  host_func. into ( ) . into ( ) , 
224+             extra_allowed_syscalls :  Some ( extra_allowed_syscalls. into_iter ( ) . collect ( ) ) , 
225+             parameter_types :  Args :: TYPE , 
226+             return_type :  Output :: TYPE , 
227+         } ; 
228+         self . host_functions . insert ( name,  entry) ; 
229+         self 
230+     } 
231+ 
232+     /// Register a host function named "HostPrint" that will be called by the guest 
233+ /// when it wants to print to the console. 
234+ /// The "HostPrint" host function is kind of special, as we expect it to have the 
235+ /// `FnMut(String) -> i32` signature. 
236+ pub  fn  register_print ( 
237+         & mut  self , 
238+         print_func :  impl  Into < HostFunction < i32 ,  ( String , ) > > , 
239+     )  -> & mut  Self  { 
240+         #[ cfg( not( all( target_os = "linux" ,  feature = "seccomp" ) ) ) ]  
241+         self . register ( "HostPrint" ,  print_func) ; 
242+ 
243+         #[ cfg( all( target_os = "linux" ,  feature = "seccomp" ) ) ]  
244+         self . register_with_syscalls ( 
245+             "HostPrint" , 
246+             print_func, 
247+             EXTRA_ALLOWED_SYSCALLS_FOR_WRITER_FUNC . iter ( ) . copied ( ) , 
248+         ) ; 
249+ 
250+         self 
251+     } 
252+ 
253+     /// Register a host function named "HostPrint" that will be called by the guest 
254+ /// when it wants to print to the console. 
255+ /// The "HostPrint" host function is kind of special, as we expect it to have the 
256+ /// `FnMut(String) -> i32` signature. 
257+ /// Unlike `register_print`, this variant takes a list of extra syscalls that will 
258+ /// allowed during the execution of the function handler. 
259+ #[ cfg( all( target_os = "linux" ,  feature = "seccomp" ) ) ]  
260+     pub  fn  register_print_with_syscalls ( 
261+         & mut  self , 
262+         print_func :  impl  Into < HostFunction < i32 ,  ( String , ) > > , 
263+         extra_allowed_syscalls :  impl  IntoIterator < Item  = crate :: sandbox:: ExtraAllowedSyscall > , 
264+     )  -> & mut  Self  { 
265+         self . register_with_syscalls ( 
266+             "HostPrint" , 
267+             print_func, 
268+             EXTRA_ALLOWED_SYSCALLS_FOR_WRITER_FUNC 
269+                 . iter ( ) 
270+                 . copied ( ) 
271+                 . chain ( extra_allowed_syscalls) , 
272+         ) 
273+     } 
274+ 
275+     /// Build a new sandbox configured to run the binary specified by `env`. 
276+ pub  fn  build < ' a ,  ' b > ( 
277+         & mut  self , 
278+         env :  impl  Into < GuestEnvironment < ' a ,  ' b > > , 
279+     )  -> Result < MultiUseSandbox >  { 
280+         #![ allow( deprecated) ]  
281+         let  mut  sandbox = UninitializedSandbox :: new ( env,  Some ( self . config ) ) ?; 
282+         #[ allow( clippy:: unwrap_used) ]  
283+         // unwrap is ok since no other thread will be holding the lock at this point 
284+         let  mut  host_functions = sandbox. host_funcs . try_lock ( ) . unwrap ( ) ; 
285+         for  ( name,  entry)  in  self . host_functions . iter ( )  { 
286+             host_functions. register_host_function ( 
287+                 name. to_string ( ) , 
288+                 entry. clone ( ) , 
289+                 sandbox. mgr . unwrap_mgr_mut ( ) , 
290+             ) ?; 
291+         } 
292+         drop ( host_functions) ; 
293+         sandbox. evolve ( ) 
294+     } 
295+ } 
296+ 
84297impl  Debug  for  UninitializedSandbox  { 
85298    fn  fmt ( & self ,  f :  & mut  std:: fmt:: Formatter < ' _ > )  -> std:: fmt:: Result  { 
86299        f. debug_struct ( "UninitializedSandbox" ) 
0 commit comments