hyperlight_host/lib.rs
1/*
2Copyright 2025 The Hyperlight Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16#![warn(dead_code, missing_docs, unused_mut)]
17//! Hyperlight host runtime for executing guest code in lightweight virtual machines.
18//!
19//! This crate provides the host-side runtime for Hyperlight, enabling safe execution
20//! of untrusted guest code within micro virtual machines with minimal overhead.
21//! The runtime manages sandbox creation, guest function calls, memory isolation,
22//! and host-guest communication.
23//!
24//! The primary entry points are [`UninitializedSandbox`] for initial setup and
25//! [`MultiUseSandbox`] for executing guest functions.
26//!
27//! ## Guest Requirements
28//!
29//! Hyperlight requires specially compiled guest binaries and cannot run regular
30//! container images or executables. Guests must be built using either the Rust
31//! API ([`hyperlight_guest`] with optional use of [`hyperlight_guest_bin`]),
32//! or with the C API (`hyperlight_guest_capi`).
33//!
34//! [`hyperlight_guest`]: https://docs.rs/hyperlight_guest
35//! [`hyperlight_guest_bin`]: https://docs.rs/hyperlight_guest_bin
36//!
37
38#![cfg_attr(not(any(test, debug_assertions)), warn(clippy::panic))]
39#![cfg_attr(not(any(test, debug_assertions)), warn(clippy::expect_used))]
40#![cfg_attr(not(any(test, debug_assertions)), warn(clippy::unwrap_used))]
41#![cfg_attr(any(test, debug_assertions), allow(clippy::disallowed_macros))]
42
43#[cfg(feature = "build-metadata")]
44use std::sync::Once;
45
46#[cfg(feature = "build-metadata")]
47/// The `built` crate is used to generate a `built.rs` file that contains
48/// information about the build environment. This information is used to
49/// populate the `built_info` module, which is re-exported here.
50pub(crate) mod built_info {
51 include!(concat!(env!("OUT_DIR"), "/built.rs"));
52}
53/// Dealing with errors, including errors across VM boundaries
54pub mod error;
55/// Wrappers for host and guest functions.
56pub mod func;
57/// Wrappers for hypervisor implementations
58pub mod hypervisor;
59/// Functionality to establish and manage an individual sandbox's
60/// memory.
61///
62/// - Virtual Address
63///
64/// 0x0000 PML4
65/// 0x1000 PDPT
66/// 0x2000 PD
67/// 0x3000 The guest PE code (When the code has been loaded using LoadLibrary to debug the guest this will not be
68/// present and code length will be zero;
69///
70/// - The pointer passed to the Entrypoint in the Guest application is the size of page table + size of code,
71/// at this address structs below are laid out in this order
72pub mod mem;
73/// Metric definitions and helpers
74pub mod metrics;
75/// The main sandbox implementations. Do not use this module directly in code
76/// outside this file. Types from this module needed for public consumption are
77/// re-exported below.
78pub mod sandbox;
79#[cfg(all(feature = "seccomp", target_os = "linux"))]
80pub(crate) mod seccomp;
81/// Signal handling for Linux
82#[cfg(target_os = "linux")]
83pub(crate) mod signal_handlers;
84/// Utilities for testing including interacting with `simpleguest.exe`
85/// and `callbackguest.exe`, our two most basic guest binaries for testing
86#[cfg(test)]
87pub(crate) mod testing;
88
89/// The re-export for the `HyperlightError` type
90pub use error::HyperlightError;
91/// Re-export for `HypervisorWrapper` trait
92/// Re-export for `MemMgrWrapper` type
93/// A sandbox that can call be used to make multiple calls to guest functions,
94/// and otherwise reused multiple times
95pub use sandbox::MultiUseSandbox;
96/// The re-export for the `UninitializedSandbox` type
97pub use sandbox::UninitializedSandbox;
98/// The re-export for the `is_hypervisor_present` type
99pub use sandbox::is_hypervisor_present;
100/// The re-export for the `GuestBinary` type
101pub use sandbox::uninitialized::GuestBinary;
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 log::error!("{}", __err);
118 return Err(__err);
119 }};
120 ($err:expr $(,)?) => {
121 log::error!("{}", $err);
122 return Err($err);
123 };
124 ($err:stmt $(,)?) => {
125 log::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 log::error!("{}", __err);
132 return Err(__err);
133 };
134}
135
136/// Same as log::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 log::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 log::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}