hyperlight_host/lib.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2025 The Hyperlight Authors.
3#![warn(dead_code, missing_docs, unused_mut)]
4//! Hyperlight host runtime for executing guest code in lightweight virtual machines.
5//!
6//! This crate provides the host-side runtime for Hyperlight, enabling safe execution
7//! of untrusted guest code within micro virtual machines with minimal overhead.
8//! The runtime manages sandbox creation, guest function calls, memory isolation,
9//! and host-guest communication.
10//!
11//! The primary entry point is [`SandboxBuilder`], which produces a
12//! [`MultiUseSandbox`] for executing guest functions.
13//!
14//! ## Guest Requirements
15//!
16//! Hyperlight requires specially compiled guest binaries and cannot run regular
17//! container images or executables. Guests must be built using either the Rust
18//! API ([`hyperlight_guest`] with optional use of [`hyperlight_guest_bin`]),
19//! or with the C API (`hyperlight_guest_capi`).
20//!
21//! [`hyperlight_guest`]: https://docs.rs/hyperlight_guest
22//! [`hyperlight_guest_bin`]: https://docs.rs/hyperlight_guest_bin
23//!
24
25#![cfg_attr(not(any(test, debug_assertions)), warn(clippy::panic))]
26#![cfg_attr(not(any(test, debug_assertions)), warn(clippy::expect_used))]
27#![cfg_attr(not(any(test, debug_assertions)), warn(clippy::unwrap_used))]
28
29#[cfg(feature = "build-metadata")]
30use std::sync::Once;
31
32#[cfg(feature = "build-metadata")]
33/// The `built` crate is used to generate a `built.rs` file that contains
34/// information about the build environment. This information is used to
35/// populate the `built_info` module, which is re-exported here.
36pub(crate) mod built_info {
37 include!(concat!(env!("OUT_DIR"), "/built.rs"));
38}
39/// Dealing with errors, including errors across VM boundaries
40pub mod error;
41/// Wrappers for host and guest functions.
42pub mod func;
43/// Wrappers for hypervisor implementations
44pub mod hypervisor;
45/// Functionality to establish and manage an individual sandbox's
46/// memory.
47///
48/// - Virtual Address
49///
50/// 0x0000 PML4
51/// 0x1000 PDPT
52/// 0x2000 PD
53/// 0x3000 The guest PE code (When the code has been loaded using LoadLibrary to debug the guest this will not be
54/// present and code length will be zero;
55///
56/// - The pointer passed to the Entrypoint in the Guest application is the size of page table + size of code,
57/// at this address structs below are laid out in this order
58pub mod mem;
59/// Metric definitions and helpers
60pub mod metrics;
61/// The main sandbox implementations. Do not use this module directly in code
62/// outside this file. Types from this module needed for public consumption are
63/// re-exported below.
64pub mod sandbox;
65/// Signal handling for Linux
66#[cfg(target_os = "linux")]
67pub(crate) mod signal_handlers;
68/// Utilities for testing including interacting with `simpleguest` testing guest binary
69#[cfg(test)]
70pub(crate) mod testing;
71
72/// The re-export for the `HyperlightError` type
73pub use error::HyperlightError;
74/// The re-export for the `is_hypervisor_present` type
75pub use hypervisor::virtual_machine::is_hypervisor_present;
76/// A sandbox that can call be used to make multiple calls to guest functions,
77/// and otherwise reused multiple times
78pub use sandbox::MultiUseSandbox;
79/// The lifecycle state of a [`MultiUseSandbox`].
80pub use sandbox::SandboxStatus;
81/// The re-export for the `UninitializedSandbox` type
82pub use sandbox::UninitializedSandbox;
83/// The re-export for the `SandboxBuilder` type
84pub use sandbox::builder::SandboxBuilder;
85/// A collection of host functions that can be supplied to a sandbox
86/// constructor (e.g. [`MultiUseSandbox::from_snapshot`]).
87pub use sandbox::host_funcs::HostFunctions;
88/// The re-export for the `GuestBinary` type
89pub use sandbox::uninitialized::GuestBinary;
90
91/// Unstable, internal API surface exposed solely for Hyperlight's own
92/// integration tests. Not part of the public API: anything here may
93/// change or disappear without notice. Do not depend on it.
94#[doc(hidden)]
95pub mod __private {
96 /// Short golden-tag token for the host CPU vendor, or `None` if the
97 /// goldens do not cover it. See the snapshot golden tests.
98 pub fn host_cpu_vendor_golden_tag() -> Option<&'static str> {
99 crate::sandbox::snapshot::host_cpu_vendor_golden_tag()
100 }
101}
102
103/// The universal `Result` type used throughout the Hyperlight codebase.
104pub type Result<T> = core::result::Result<T, error::HyperlightError>;
105
106/// Logs an error then returns with it, more or less equivalent to the bail! macro in anyhow
107/// but for HyperlightError instead of anyhow::Error
108#[macro_export]
109macro_rules! log_then_return {
110 ($msg:literal $(,)?) => {{
111 let __args = std::format_args!($msg);
112 let __err_msg = match __args.as_str() {
113 Some(msg) => String::from(msg),
114 None => std::format!($msg),
115 };
116 let __err = $crate::HyperlightError::Error(__err_msg);
117 tracing::error!("{}", __err);
118 return Err(__err);
119 }};
120 ($err:expr $(,)?) => {
121 tracing::error!("{}", $err);
122 return Err($err);
123 };
124 ($err:stmt $(,)?) => {
125 tracing::error!("{}", $err);
126 return Err($err);
127 };
128 ($fmtstr:expr, $($arg:tt)*) => {
129 let __err_msg = std::format!($fmtstr, $($arg)*);
130 let __err = $crate::error::HyperlightError::Error(__err_msg);
131 tracing::error!("{}", __err);
132 return Err(__err);
133 };
134}
135
136/// Same as tracing::debug!, but will additionally print to stdout if the print_debug feature is enabled
137#[macro_export]
138macro_rules! debug {
139 ($($arg:tt)+) =>
140 {
141 #[cfg(print_debug)]
142 println!($($arg)+);
143 tracing::debug!($($arg)+);
144 }
145}
146
147// LOG_ONCE is used to log information about the crate version once
148#[cfg(feature = "build-metadata")]
149static LOG_ONCE: Once = Once::new();
150
151#[cfg(feature = "build-metadata")]
152pub(crate) fn log_build_details() {
153 use tracing::info;
154 LOG_ONCE.call_once(|| {
155 info!("Package name: {}", built_info::PKG_NAME);
156 info!("Package version: {}", built_info::PKG_VERSION);
157 info!("Package features: {:?}", built_info::FEATURES);
158 info!("Target triple: {}", built_info::TARGET);
159 info!("Optimization level: {}", built_info::OPT_LEVEL);
160 info!("Profile: {}", built_info::PROFILE);
161 info!("Debug: {}", built_info::DEBUG);
162 info!("Rustc: {}", built_info::RUSTC);
163 info!("Built at: {}", built_info::BUILT_TIME_UTC);
164 match built_info::CI_PLATFORM.unwrap_or("") {
165 "" => info!("Not built on a CI platform"),
166 other => info!("Built on : {}", other),
167 }
168 match built_info::GIT_COMMIT_HASH.unwrap_or("") {
169 "" => info!("No git commit hash found"),
170 other => info!("Git commit hash: {}", other),
171 }
172
173 let git = match built_info::GIT_HEAD_REF.unwrap_or("") {
174 "" => {
175 info!("No git head ref found");
176 false
177 }
178 other => {
179 info!("Git head ref: {}", other);
180 true
181 }
182 };
183 match built_info::GIT_VERSION.unwrap_or("") {
184 "" => info!("No git version found"),
185 other => info!("Git version: {}", other),
186 }
187 match built_info::GIT_DIRTY.unwrap_or(false) {
188 true => info!("Repo had uncommitted changes"),
189 false => {
190 if git {
191 info!("Repo had no uncommitted changes")
192 } else {
193 info!("No git repo found")
194 }
195 }
196 }
197 });
198}