@@ -295,10 +295,14 @@ where
295295
296296#[ cfg( test) ]  
297297mod  tests { 
298+     use  std:: thread; 
299+ 
300+     use  crate :: Result ; 
301+     use  crate :: { is_hypervisor_present,  HyperlightError } ; 
298302    use  hyperlight_common:: flatbuffer_wrappers:: function_types:: { 
299303        ParameterValue ,  ReturnType ,  ReturnValue , 
300304    } ; 
301-     use  hyperlight_testing:: simple_guest_as_string; 
305+     use  hyperlight_testing:: { callback_guest_as_string ,   simple_guest_as_string} ; 
302306
303307    use  crate :: func:: call_ctx:: MultiUseGuestCallContext ; 
304308    use  crate :: sandbox:: SandboxConfiguration ; 
@@ -384,4 +388,161 @@ mod tests {
384388            . unwrap ( ) ; 
385389        assert_eq ! ( res,  ReturnValue :: Int ( 0 ) ) ; 
386390    } 
391+ 
392+     #[ test]  
393+     // TODO: Investigate why this test fails with an incorrect error when run alongside other tests 
394+     #[ ignore]  
395+     fn  test_violate_seccomp_filters ( )  -> Result < ( ) >  { 
396+         if  cfg ! ( target_os = "windows" )  { 
397+             // This test is not applicable on Windows as seccomp is a Linux-specific feature. 
398+             return  Ok ( ( ) ) ; 
399+         } 
400+ 
401+         if  !is_hypervisor_present ( )  { 
402+             panic ! ( "Panic on create_multi_use_sandbox because no hypervisor is present" ) ; 
403+         } 
404+ 
405+         fn  make_get_pid_syscall ( )  -> Result < u64 >  { 
406+             let  pid = unsafe  {  libc:: syscall ( libc:: SYS_getpid )  } ; 
407+             Ok ( pid as  u64 ) 
408+         } 
409+ 
410+         // First, run  to make sure it fails. 
411+         { 
412+             let  mut  usbox = UninitializedSandbox :: new ( 
413+                 GuestBinary :: FilePath ( simple_guest_as_string ( ) . expect ( "Guest Binary Missing" ) ) , 
414+                 None , 
415+             ) 
416+             . unwrap ( ) ; 
417+ 
418+             usbox. register ( "MakeGetpidSyscall" ,  make_get_pid_syscall) ?; 
419+ 
420+             let  mut  sbox:  MultiUseSandbox  = usbox. evolve ( Noop :: default ( ) ) ?; 
421+ 
422+             let  res =
423+                 sbox. call_guest_function_by_name ( "ViolateSeccompFilters" ,  ReturnType :: ULong ,  None ) ; 
424+ 
425+             #[ cfg( feature = "seccomp" ) ]  
426+             match  res { 
427+                 Ok ( _)  => panic ! ( "Expected to fail due to seccomp violation" ) , 
428+                 Err ( e)  => match  e { 
429+                     HyperlightError :: DisallowedSyscall  => { } 
430+                     _ => panic ! ( "Expected DisallowedSyscall error: {}" ,  e) , 
431+                 } , 
432+             } 
433+ 
434+             #[ cfg( not( feature = "seccomp" ) ) ]  
435+             match  res { 
436+                 Ok ( _)  => ( ) , 
437+                 Err ( e)  => panic ! ( "Expected to succeed without seccomp: {}" ,  e) , 
438+             } 
439+         } 
440+ 
441+         // Second, run with allowing `SYS_getpid` 
442+         #[ cfg( feature = "seccomp" ) ]  
443+         { 
444+             let  mut  usbox = UninitializedSandbox :: new ( 
445+                 GuestBinary :: FilePath ( simple_guest_as_string ( ) . expect ( "Guest Binary Missing" ) ) , 
446+                 None , 
447+             ) 
448+             . unwrap ( ) ; 
449+ 
450+             usbox. register_with_extra_allowed_syscalls ( 
451+                 "MakeGetpidSyscall" , 
452+                 make_get_pid_syscall, 
453+                 vec ! [ libc:: SYS_getpid ] , 
454+             ) ?; 
455+             // ^^^ note, we are allowing SYS_getpid 
456+ 
457+             let  mut  sbox:  MultiUseSandbox  = usbox. evolve ( Noop :: default ( ) ) ?; 
458+ 
459+             let  res =
460+                 sbox. call_guest_function_by_name ( "ViolateSeccompFilters" ,  ReturnType :: ULong ,  None ) ; 
461+ 
462+             match  res { 
463+                 Ok ( _)  => { } 
464+                 Err ( e)  => panic ! ( "Expected to succeed due to seccomp violation: {}" ,  e) , 
465+             } 
466+         } 
467+ 
468+         Ok ( ( ) ) 
469+     } 
470+ 
471+     // This test is to capture the case where the guest execution is running a host function when cancelled and that host function 
472+     // is never going to return. 
473+     // The host function that is called will end after 5 seconds, but by this time the cancellation will have given up 
474+     // (using default timeout settings)  , so this tests looks for the error "Failed to cancel guest execution". 
475+     #[ test]  
476+     #[ ignore = "We cannot cancel host functions. TODO reenable this test when it's enabled" ]  
477+     fn  test_terminate_vcpu_calling_host_spinning_cpu ( )  { 
478+         // This test relies upon a Hypervisor being present so for now 
479+         // we will skip it if there isn't one. 
480+         if  !is_hypervisor_present ( )  { 
481+             println ! ( "Skipping test_call_guest_function_by_name because no hypervisor is present" ) ; 
482+             return ; 
483+         } 
484+         let  mut  usbox = UninitializedSandbox :: new ( 
485+             GuestBinary :: FilePath ( callback_guest_as_string ( ) . expect ( "Guest Binary Missing" ) ) , 
486+             None , 
487+         ) 
488+         . unwrap ( ) ; 
489+ 
490+         // Make this host call run for 5 seconds 
491+ 
492+         fn  spin ( )  -> Result < ( ) >  { 
493+             thread:: sleep ( std:: time:: Duration :: from_secs ( 5 ) ) ; 
494+             Ok ( ( ) ) 
495+         } 
496+ 
497+         #[ cfg( any( target_os = "windows" ,  not( feature = "seccomp" ) ) ) ]  
498+         usbox. register ( "Spin" ,  spin) . unwrap ( ) ; 
499+ 
500+         #[ cfg( all( target_os = "linux" ,  feature = "seccomp" ) ) ]  
501+         usbox
502+             . register_with_extra_allowed_syscalls ( "Spin" ,  spin,  vec ! [ libc:: SYS_clock_nanosleep ] ) 
503+             . unwrap ( ) ; 
504+ 
505+         let  sandbox:  MultiUseSandbox  = usbox. evolve ( Noop :: default ( ) ) . unwrap ( ) ; 
506+         let  mut  ctx = sandbox. new_call_context ( ) ; 
507+         let  result = ctx. call ( "CallHostSpin" ,  ReturnType :: Void ,  None ) ; 
508+ 
509+         assert ! ( result. is_err( ) ) ; 
510+         match  result. unwrap_err ( )  { 
511+             HyperlightError :: GuestExecutionHungOnHostFunctionCall ( )  => { } 
512+             e => panic ! ( 
513+                 "Expected HyperlightError::GuestExecutionHungOnHostFunctionCall but got {:?}" , 
514+                 e
515+             ) , 
516+         } 
517+     } 
518+ 
519+     #[ test]  
520+     fn  test_trigger_exception_on_guest ( )  { 
521+         let  usbox = UninitializedSandbox :: new ( 
522+             GuestBinary :: FilePath ( simple_guest_as_string ( ) . expect ( "Guest Binary Missing" ) ) , 
523+             None , 
524+         ) 
525+         . unwrap ( ) ; 
526+ 
527+         let  mut  multi_use_sandbox:  MultiUseSandbox  = usbox. evolve ( Noop :: default ( ) ) . unwrap ( ) ; 
528+ 
529+         let  res = multi_use_sandbox. call_guest_function_by_name ( 
530+             "TriggerException" , 
531+             ReturnType :: Void , 
532+             None , 
533+         ) ; 
534+ 
535+         assert ! ( res. is_err( ) ) ; 
536+ 
537+         match  res. unwrap_err ( )  { 
538+             HyperlightError :: GuestAborted ( _,  msg)  => { 
539+                 // msg should indicate we got an invalid opcode exception 
540+                 assert ! ( msg. contains( "InvalidOpcode" ) ) ; 
541+             } 
542+             e => panic ! ( 
543+                 "Expected HyperlightError::GuestExecutionError but got {:?}" , 
544+                 e
545+             ) , 
546+         } 
547+     } 
387548} 
0 commit comments