Skip to content

Commit 5163490

Browse files
committed
Add back tests that were deleted
Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent 26a1cfa commit 5163490

File tree

4 files changed

+248
-3
lines changed

4 files changed

+248
-3
lines changed

src/hyperlight_host/src/hypervisor/mod.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,3 +366,76 @@ impl InterruptHandle for LinuxInterruptHandle {
366366
self.dropped.load(Ordering::Relaxed)
367367
}
368368
}
369+
370+
#[cfg(all(test, any(target_os = "windows", kvm)))]
371+
pub(crate) mod tests {
372+
use std::sync::{Arc, Mutex};
373+
374+
use hyperlight_testing::dummy_guest_as_string;
375+
376+
use super::handlers::{MemAccessHandler, OutBHandler};
377+
#[cfg(gdb)]
378+
use crate::hypervisor::DbgMemAccessHandlerCaller;
379+
use crate::mem::ptr::RawPtr;
380+
use crate::sandbox::uninitialized::GuestBinary;
381+
use crate::sandbox::uninitialized_evolve::set_up_hypervisor_partition;
382+
use crate::sandbox::UninitializedSandbox;
383+
use crate::{is_hypervisor_present, new_error, Result};
384+
385+
#[cfg(gdb)]
386+
struct DbgMemAccessHandler {}
387+
388+
#[cfg(gdb)]
389+
impl DbgMemAccessHandlerCaller for DbgMemAccessHandler {
390+
fn read(&mut self, _offset: usize, _data: &mut [u8]) -> Result<()> {
391+
Ok(())
392+
}
393+
394+
fn write(&mut self, _offset: usize, _data: &[u8]) -> Result<()> {
395+
Ok(())
396+
}
397+
398+
fn get_code_offset(&mut self) -> Result<usize> {
399+
Ok(0)
400+
}
401+
}
402+
403+
#[test]
404+
fn test_initialise() -> Result<()> {
405+
if !is_hypervisor_present() {
406+
return Ok(());
407+
}
408+
409+
let outb_handler: Arc<Mutex<OutBHandler>> = {
410+
let func: Box<dyn FnMut(u16, u32) -> Result<()> + Send> =
411+
Box::new(|_, _| -> Result<()> { Ok(()) });
412+
Arc::new(Mutex::new(OutBHandler::from(func)))
413+
};
414+
let mem_access_handler = {
415+
let func: Box<dyn FnMut() -> Result<()> + Send> = Box::new(|| -> Result<()> { Ok(()) });
416+
Arc::new(Mutex::new(MemAccessHandler::from(func)))
417+
};
418+
#[cfg(gdb)]
419+
let dbg_mem_access_handler = Arc::new(Mutex::new(DbgMemAccessHandler {}));
420+
421+
let filename = dummy_guest_as_string().map_err(|e| new_error!("{}", e))?;
422+
423+
let sandbox = UninitializedSandbox::new(GuestBinary::FilePath(filename.clone()), None)?;
424+
let (_hshm, mut gshm) = sandbox.mgr.build();
425+
let mut vm = set_up_hypervisor_partition(
426+
&mut gshm,
427+
#[cfg(gdb)]
428+
&sandbox.debug_info,
429+
)?;
430+
vm.initialise(
431+
RawPtr::from(0x230000),
432+
1234567890,
433+
4096,
434+
outb_handler,
435+
mem_access_handler,
436+
None,
437+
#[cfg(gdb)]
438+
dbg_mem_access_handler,
439+
)
440+
}
441+
}

src/hyperlight_host/src/sandbox/initialized_multi_use.rs

Lines changed: 164 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,16 +295,21 @@ where
295295

296296
#[cfg(test)]
297297
mod tests {
298+
use std::thread;
299+
298300
use hyperlight_common::flatbuffer_wrappers::function_types::{
299301
ParameterValue, ReturnType, ReturnValue,
300302
};
301-
use hyperlight_testing::simple_guest_as_string;
303+
use hyperlight_testing::{callback_guest_as_string, simple_guest_as_string};
302304

303305
use crate::func::call_ctx::MultiUseGuestCallContext;
304306
use crate::sandbox::SandboxConfiguration;
305307
use crate::sandbox_state::sandbox::{DevolvableSandbox, EvolvableSandbox};
306308
use crate::sandbox_state::transition::{MultiUseContextCallback, Noop};
307-
use crate::{GuestBinary, MultiUseSandbox, UninitializedSandbox};
309+
use crate::{
310+
is_hypervisor_present, GuestBinary, HyperlightError, MultiUseSandbox, Result,
311+
UninitializedSandbox,
312+
};
308313

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

src/hyperlight_host/src/sandbox/uninitialized_evolve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ pub(super) fn evolve_impl_multi_use(u_sbox: UninitializedSandbox) -> Result<Mult
141141
)
142142
}
143143

144-
fn set_up_hypervisor_partition(
144+
pub(crate) fn set_up_hypervisor_partition(
145145
mgr: &mut SandboxMemoryManager<GuestSharedMemory>,
146146
#[cfg(gdb)] debug_info: &Option<DebugInfo>,
147147
) -> Result<Box<dyn Hypervisor>> {

src/hyperlight_host/tests/integration_test.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ fn kill_running_vm() {
5252
.unwrap_err();
5353
assert!(matches!(res, HyperlightError::ExecutionCanceledByHost()));
5454

55+
// Make sure we can still call guest functions after the VM was interrupted
56+
sbox1
57+
.call_guest_function_by_name(
58+
"Echo",
59+
ReturnType::Int,
60+
Some(vec![ParameterValue::String("hello\n".to_string())]),
61+
)
62+
.unwrap();
63+
64+
// drop vm to make sure other thread can detect it
5565
drop(sbox1);
5666
thread.join().expect("Thread should finish");
5767
}

0 commit comments

Comments
 (0)