Skip to content

Commit 2543f60

Browse files
committed
Add back tests that were deleted
Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent 0604b95 commit 2543f60

File tree

3 files changed

+234
-3
lines changed

3 files changed

+234
-3
lines changed

src/hyperlight_host/src/hypervisor/mod.rs

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

src/hyperlight_host/src/sandbox/initialized_multi_use.rs

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

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>> {

0 commit comments

Comments
 (0)