hyperlight_host/
lib.rs

1/*
2Copyright 2024 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
17use std::sync::Once;
18
19/// This crate contains an SDK that is used to execute specially-
20/// compiled binaries within a very lightweight hypervisor environment.
21use log::info;
22/// The `built` crate is used to generate a `built.rs` file that contains
23/// information about the build environment. This information is used to
24/// populate the `built_info` module, which is re-exported here.
25pub(crate) mod built_info {
26    include!(concat!(env!("OUT_DIR"), "/built.rs"));
27}
28/// Dealing with errors, including errors across VM boundaries
29#[deny(dead_code, missing_docs, unused_mut)]
30pub mod error;
31/// Wrappers for host and guest functions.
32#[deny(dead_code, missing_docs, unused_mut)]
33pub mod func;
34/// Wrappers for hypervisor implementations
35#[deny(dead_code, missing_docs, unused_mut)]
36pub mod hypervisor;
37/// Functionality to establish and manage an individual sandbox's
38/// memory.
39///
40/// The following structs are not used other than to calculate the size of the memory needed
41/// and also to illustrate the layout of the memory:
42///
43/// - `HostFunctionDefinitions`
44/// - `HostExceptionData`
45/// - `GuestError`
46/// - `CodeAndOutBPointers`
47/// - `InputData`
48/// - `OutputData`
49/// - `GuestHeap`
50/// - `GuestStack`
51///
52/// the start of the guest  memory contains the page tables and is always located at the Virtual Address 0x00200000 when
53/// running in a Hypervisor:
54///
55/// Virtual Address
56///
57/// 0x200000    PML4
58/// 0x201000    PDPT
59/// 0x202000    PD
60/// 0x203000    The guest PE code (When the code has been loaded using LoadLibrary to debug the guest this will not be
61/// present and code length will be zero;
62///
63/// The pointer passed to the Entrypoint in the Guest application is the 0x200000 + size of page table + size of code,
64/// at this address structs below are laid out in this order
65#[deny(dead_code, missing_docs, unused_mut)]
66pub mod mem;
67/// Metric definitions and helpers
68#[deny(dead_code, missing_docs, unused_mut)]
69pub mod metrics;
70/// The main sandbox implementations. Do not use this module directly in code
71/// outside this file. Types from this module needed for public consumption are
72/// re-exported below.
73#[deny(dead_code, missing_docs, unused_mut)]
74pub mod sandbox;
75/// `trait`s and other functionality for dealing with defining sandbox
76/// states and moving between them
77pub mod sandbox_state;
78#[cfg(all(feature = "seccomp", target_os = "linux"))]
79pub(crate) mod seccomp;
80/// Signal handling for Linux
81#[cfg(target_os = "linux")]
82pub(crate) mod signal_handlers;
83/// Utilities for testing including interacting with `simpleguest.exe`
84/// and `callbackguest.exe`, our two most basic guest binaries for testing
85#[deny(missing_docs, unused_mut)]
86#[cfg(test)]
87pub(crate) mod testing;
88
89/// The re-export for the `HyperlightError` type
90pub use error::HyperlightError;
91/// The re-export for the set_registry function
92pub use metrics::set_metrics_registry;
93/// The re-export for the `is_hypervisor_present` type
94pub use sandbox::is_hypervisor_present;
95/// The re-export for the `GuestBinary` type
96pub use sandbox::uninitialized::GuestBinary;
97/// Re-export for `HypervisorWrapper` trait
98/// Re-export for `MemMgrWrapper` type
99/// A sandbox that can call be used to make multiple calls to guest functions,
100/// and otherwise reused multiple times
101pub use sandbox::MultiUseSandbox;
102/// The re-export for the `SandboxRunOptions` type
103pub use sandbox::SandboxRunOptions;
104/// The re-export for the `UninitializedSandbox` type
105pub use sandbox::UninitializedSandbox;
106
107/// The re-export for the `MultiUseGuestCallContext` type`
108pub use crate::func::call_ctx::MultiUseGuestCallContext;
109
110/// The universal `Result` type used throughout the Hyperlight codebase.
111pub type Result<T> = core::result::Result<T, error::HyperlightError>;
112
113// Logs an error then returns with it , more or less equivalent to the bail! macro in anyhow
114// but for HyperlightError instead of anyhow::Error
115#[macro_export]
116macro_rules! log_then_return {
117    ($msg:literal $(,)?) => {{
118        let __args = std::format_args!($msg);
119        let __err_msg = match __args.as_str() {
120            Some(msg) => String::from(msg),
121            None => std::format!($msg),
122        };
123        let __err = $crate::HyperlightError::Error(__err_msg);
124        log::error!("{}", __err);
125        return Err(__err);
126    }};
127    ($err:expr $(,)?) => {
128        log::error!("{}", $err);
129        return Err($err);
130    };
131    ($err:stmt $(,)?) => {
132        log::error!("{}", $err);
133        return Err($err);
134    };
135    ($fmtstr:expr, $($arg:tt)*) => {
136           let __err_msg = std::format!($fmtstr, $($arg)*);
137           let __err = $crate::error::HyperlightError::Error(__err_msg);
138           log::error!("{}", __err);
139           return Err(__err);
140    };
141}
142
143// same as log::debug!, but will additionally print to stdout if the print_debug feature is enabled
144#[macro_export]
145macro_rules! debug {
146    ($($arg:tt)+) =>
147    {
148        #[cfg(print_debug)]
149        println!($($arg)+);
150        log::debug!($($arg)+);
151    }
152}
153
154// LOG_ONCE is used to log information about the crate version once
155static LOG_ONCE: Once = Once::new();
156
157pub(crate) fn log_build_details() {
158    LOG_ONCE.call_once(|| {
159        info!("Package name: {}", built_info::PKG_NAME);
160        info!("Package version: {}", built_info::PKG_VERSION);
161        info!("Package features: {:?}", built_info::FEATURES);
162        info!("Target triple: {}", built_info::TARGET);
163        info!("Optimization level: {}", built_info::OPT_LEVEL);
164        info!("Profile: {}", built_info::PROFILE);
165        info!("Debug: {}", built_info::DEBUG);
166        info!("Rustc: {}", built_info::RUSTC);
167        info!("Built at: {}", built_info::BUILT_TIME_UTC);
168        match built_info::CI_PLATFORM.unwrap_or("") {
169            "" => info!("Not built on  a CI platform"),
170            other => info!("Built on : {}", other),
171        }
172        match built_info::GIT_COMMIT_HASH.unwrap_or("") {
173            "" => info!("No git commit hash found"),
174            other => info!("Git commit hash: {}", other),
175        }
176
177        let git = match built_info::GIT_HEAD_REF.unwrap_or("") {
178            "" => {
179                info!("No git head ref found");
180                false
181            }
182            other => {
183                info!("Git head ref: {}", other);
184                true
185            }
186        };
187        match built_info::GIT_VERSION.unwrap_or("") {
188            "" => info!("No git version found"),
189            other => info!("Git version: {}", other),
190        }
191        match built_info::GIT_DIRTY.unwrap_or(false) {
192            true => info!("Repo had uncommitted changes"),
193            false => {
194                if git {
195                    info!("Repo had no uncommitted changes")
196                } else {
197                    info!("No git repo found")
198                }
199            }
200        }
201    });
202}