Hyperlight
Hyperlight is a lightweight Virtual Machine Manager (VMM) designed to be embedded within applications. It enables safe execution of untrusted code within micro virtual machines with very low latency and minimal overhead.
> Note: Hyperlight is a nascent project with an evolving API and no guaranteed support. Assistance is provided on a best-effort basis by the developers.
---
## Overview
Hyperlight is a library for creating _micro virtual machines_ — or _sandboxes_ — specifically optimized for securely running untrusted code with minimal impact. It supports both Windows and Linux, utilizing [Windows Hypervisor Platform](https://docs.microsoft.com/en-us/virtualization/api/#windows-hypervisor-platform) on Windows, and either Microsoft Hypervisor (mshv) or [KVM](https://linux-kvm.org/page/Main_Page) on Linux.
These micro VMs operate without a kernel or operating system, keeping overhead low. Instead, guests are built specifically for Hyperlight using the Hyperlight Guest library, which provides a controlled set of APIs that facilitate interaction between host and guest:
- The host can call functions implemented and exposed by the guest (known as _guest functions_).
- Once running, the guest can call functions implemented and exposed by the host (known as _host functions_).
By default, Hyperlight restricts guest access to a minimal API. The only _host function_ available by default allows the guest to print messages, which are displayed on the host console or redirected to stdout, as configured. Hosts can choose to expose additional host functions, expanding the guest’s capabilities as needed.
Below is an example demonstrating the use of the Hyperlight host library in Rust to execute a simple guest application and am example of a simple guest application using the Hyperlight guest library in also written in Rust.
### Host
```rust
use std::{thread, sync::{Arc, Mutex}};
use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnType};
use hyperlight_host::{UninitializedSandbox, MultiUseSandbox, func::HostFunction0, sandbox_state::transition::Noop, sandbox_state::sandbox::EvolvableSandbox};
fn main() -> hyperlight_host::Result<()> {
// Create an uninitialized sandbox with a guest binary
let mut uninitialized_sandbox = UninitializedSandbox::new(
hyperlight_host::GuestBinary::FilePath(hyperlight_testing::simple_guest_as_string().unwrap()),
None, // default configuration
None, // default run options
None, // default host print function
)?;
// Register a host function
fn sleep_5_secs() -> hyperlight_host::Result<()> {
thread::sleep(std::time::Duration::from_secs(5));
Ok(())
}
let host_function = Arc::new(Mutex::new(sleep_5_secs));
// Registering a host function makes it available to be called by the guest
host_function.register(&mut uninitialized_sandbox, "Sleep5Secs")?;
// Note: This function is unused by the guest code below, it's just here for demonstration purposes
// Initialize sandbox to be able to call host functions
let mut multi_use_sandbox: MultiUseSandbox = uninitialized_sandbox.evolve(Noop::default())?;
// Call a function in the guest
let message = "Hello, World! I am executing inside of a VM :)\n".to_string();
// in order to call a function it first must be defined in the guest and exposed so that
// the host can call it
let result = multi_use_sandbox.call_guest_function_by_name(
"PrintOutput",
ReturnType::Int,
Some(vec![ParameterValue::String(message.clone())]),
);
assert!(result.is_ok());
Ok(())
}
```
### Guest
```rust
#![no_std]
#![no_main]
extern crate alloc;
use alloc::string::ToString;
use alloc::vec::Vec;
use hyperlight_common::flatbuffer_wrappers::function_call::FunctionCall;
use hyperlight_common::flatbuffer_wrappers::function_types::{
ParameterType, ParameterValue, ReturnType,
};
use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
use hyperlight_common::flatbuffer_wrappers::util::get_flatbuffer_result_from_int;
use hyperlight_guest::error::{HyperlightGuestError, Result};
use hyperlight_guest::guest_function_definition::GuestFunctionDefinition;
use hyperlight_guest::guest_function_register::register_function;
use hyperlight_guest::host_function_call::{
call_host_function, get_host_value_return_as_int,
};
fn print_output(function_call: &FunctionCall) -> Result