SEV SNP Runner in LiteBox: Architecture, Boot Sequence, and Runtime Services
The SEV SNP runner is a minimal no_std binary that executes inside an AMD SEV-SNP virtual machine to bootstrap the LiteBox sandbox, bridging guest-side code to the host VMM through the GHCB protocol.
The SEV SNP runner serves as the secure foundation for Microsoft's LiteBox project, enabling confidential computing by running Linux user-mode programs within AMD SEV-SNP protected virtual machines. This no_std Rust binary functions as both a bootloader and runtime environment, managing everything from initial VM setup to graceful termination through SEV-SNP hypercalls.
What Is the SEV SNP Runner?
The SEV SNP runner (litebox_runner_snp) is a specialized, no_std executable designed specifically for AMD SEV-SNP (Secure Encrypted Virtualization-Secure Nested Paging) environments. Unlike traditional hypervisor-based runners, this component operates entirely within the encrypted guest VM, providing the minimal runtime necessary to bootstrap the LiteBox sandbox.
The runner fulfills three critical roles:
- Bootstrapper: Initializes the GHCB (Guest-Host Communication Block) and establishes the encrypted memory environment using the SEV encryption bit (
PRIVATE_PTE_MASK = 1 << 51). - Bridge: Translates between guest-side Linux ABI expectations and host VMM services through SEV-SNP hypercalls.
- Runtime: Manages page faults, system calls, thread scheduling, network I/O, and clean VM termination via the SEV-SNP termination protocol.
Architectural Components
The SEV SNP runner consists of tightly integrated assembly and Rust components that handle the transition from bare-metal VM startup to high-level sandbox execution.
| Component | Role | Source Location |
|---|---|---|
entry.S |
Assembly entry points including _start, sandbox_kernel_start, sandbox_process_start, and entry_SYSCALL_64. Handles stack alignment and ISR vector setup. |
litebox_runner_snp/src/entry.S |
main.rs |
Core Rust logic implementing page_fault_handler, sandbox_process_init, and sandbox_tun_read_write. Constructs the LinuxShim and manages program loading. |
litebox_runner_snp/src/main.rs |
globals.rs |
Defines SEV-SNP termination constants (SM_TERM_EXCEPTION, SM_TERM_INVALID_PARAM, etc.) used for hypercall-based shutdown. |
litebox_runner_snp/src/globals.rs |
snp_impl.rs |
Implements HostSnpInterface providing GHCB-based communication, memory allocation callbacks, and the terminate hypercall. |
litebox_platform_linux_kernel/src/host/snp/snp_impl.rs |
platform_multiplex.rs |
Compile-time platform selection that routes to SnpLinuxKernel when the platform_linux_snp feature is enabled. |
litebox_platform_multiplex/src/lib.rs |
Boot Sequence: From CPU Reset to Guest Execution
The SEV SNP runner follows a strict three-phase boot process that transitions from assembly initialization to Rust-based runtime management.
Phase 1: Assembly Entry Point
When the SEV-SNP VM boots, execution begins at _start in litebox_runner_snp/src/entry.S. This assembly routine performs critical early setup:
- Aligns the stack pointer to satisfy System V AMD64 ABI requirements.
- Disables interrupts to prevent early exception handling before the IDT is ready.
- Jumps to
sandbox_kernel_initto enter the Rust runtime.
Phase 2: Kernel Initialization
The sandbox_kernel_init function in main.rs receives the vmpl2_boot_params structure from the host VMM, which contains the GHCB page address and CPU frequency. This phase:
- Validates and maps the GHCB page via
GhcbProtocol::setup_ghcb_page, establishing the encrypted communication channel. - Stores the GHCB reference in
HostSnpInterfacefor future hypercalls. - Invokes
HostSnpInterface::return_to_hostto trigger a VM-exit, allowing the host to complete kernel setup.
Phase 3: Process Initialization
After the host resumes the VM, execution continues at sandbox_process_start → sandbox_process_init. This final boot phase:
- Reads the current CR3 register to obtain the guest page-directory base.
- Constructs the
SnpLinuxKernelplatform implementation (litebox_platform_linux_kernel::host::snp::snp_impl::SnpLinuxKernel). - Builds a
LinuxShimusingLinuxShimBuilderto wire LiteBox core services to the host. - Parses
argvand environment variables fromboot_params. - Loads the guest ELF binary via
shim.load_program. - Transfers control to
run_threadinsnp_impl.rs, entering the guest program's entry point.
Runtime Services and System Integration
Once booted, the SEV SNP runner provides comprehensive runtime services that allow unmodified Linux binaries to execute securely within the encrypted VM.
Page Fault Handling
The page_fault_handler in litebox_runner_snp/src/main.rs manages memory access violations. When a fault occurs:
- The handler queries the
page_managerfrom theLinuxShimto resolve the fault. - For kernel-space faults, it searches the exception table (
exception_table::search_exception_tables) to determine if the fault is recoverable. - Unrecoverable faults trigger
HostSnpInterface::terminatewithSM_SEV_TERM_SET(0x3) andSM_TERM_EXCEPTION, causing the VMM to shut down the VM.
System Call Dispatch
System calls from the guest binary flow through a dedicated assembly stub:
- The
entry_SYSCALL_64vector inentry.Ssaves guest registers to the stack. - Control transfers to
do_syscall_64, which forwards tosnp_impl::handle_syscall. - The Rust handler interprets the syscall using
litebox::syscallsand routes requests to the host via GHCB when necessary.
Thread Lifecycle Management
The runner manages guest threads through structures defined in snp_impl.rs:
run_thread: Installs the shim in thread-local storage and invokes the shim'sinitmethod.ACTIVE_THREAD_COUNT: Tracks running threads; incremented on thread creation and decremented on exit.- Reinvocation: The shim returns
ResumeGuestto continue execution orExitThreadto terminate the thread. - Shutdown: When
all_threads_exited()returns true, the main loop insandbox_tun_read_writeterminates and returns control to the host.
Network I/O Bridge
Network operations bridge the guest and host through sandbox_tun_read_write in main.rs:
- The shim's
perform_network_interactionmethod determines if the operation can complete immediately or requires waiting. - Return values
CallAgainImmediatelyorWaitOnDeviceOrSocketInteractiondrive the polling loop. - The loop continues until all threads exit, ensuring asynchronous network I/O does not block VM termination.
Graceful Termination
The SEV SNP runner implements clean shutdown through the AMD SEV-SNP termination protocol:
- Error Handling: Fatal errors (invalid boot parameters, missing GHCB, unhandled exceptions) invoke
HostSnpInterface::terminate. - Termination Sets: The runner uses
SM_SEV_TERM_SET(0x3) with specific reason codes fromglobals.rssuch asSM_TERM_EXCEPTION,SM_TERM_INVALID_PARAM, orSM_TERM_NO_GHCB. - VM Exit: The termination hypercall triggers a SEV-SNP "VM exit with termination request," allowing the host VMM to cleanly shut down the VM and log the termination reason.
SEV-SNP Specific Implementation Details
The runner leverages AMD-specific confidential computing features to maintain isolation between the guest and hypervisor while enabling necessary communication.
GHCB Communication Protocol
The Guest-Host Communication Block (GHCB) serves as the sole communication channel between the encrypted guest and the host VMM:
- Setup: During initialization,
GhcbProtocol::setup_ghcb_pagevalidates the GHCB page address provided invmpl2_boot_paramsand maps it for use. - Debug Output: The
ghcb_printsfunction writes to the GHCB console buffer, making debug messages visible to the host without breaking encryption boundaries. - Hypercalls: All host requests—including memory allocation, I/O, and termination—flow through GHCB-based protocols defined in
HostSnpInterface.
Memory Encryption
The runner ensures all guest memory remains encrypted using the VM-derived key:
- Encryption Bit: The
SnpLinuxKernelmemory provider setsPRIVATE_PTE_MASK = 1 << 51, the AMD-defined encryption bit for SEV-SNP. - Secure Allocation: Guest physical pages are allocated through
HostSnpInterface::alloc, which routes requests to the VMM via GHCB to ensure proper encryption metadata. - Isolation: The
freecallback similarly routes through the GHCB, ensuring the hypervisor cannot observe decrypted memory contents during deallocation.
Termination Constants
The globals.rs file defines constants that map directly to the AMD SEV-SNP specification:
SM_SEV_TERM_SET = 0x3: Identifies the termination set for SEV-SNP specific reasons.- Reason Codes:
SM_TERM_EXCEPTION,SM_TERM_INVALID_PARAM,SM_TERM_NO_GHCB, and others provide granular error reporting to the host VMM. - Protocol Compliance: By using these constants with
HostSnpInterface::terminate, the runner ensures the VMM can interpret shutdown reasons according to the AMD SEV-SNP standard.
Building and Running the SEV SNP Runner
To deploy the SEV SNP runner inside an encrypted VM, you must build it as a no_std binary using the custom target configuration provided in the repository.
Building the Runner
The build process requires nightly Rust to support the custom target and no_std environment:
# Build the runner (no_std, custom target)
cargo +nightly build --manifest-path litebox_runner_snp/Cargo.toml \
--target litebox_runner_snp/target.json -Zbuild-std=core,alloc
The resulting ELF (e.g., target/litebox_runner_snp/release/litebox_runner_snp) must be copied into the guest VM image. The host VMM boots the VM and passes the vmpl2_boot_params structure containing the GHCB page address and boot arguments.
Runtime Initialization Flow
The following simplified excerpt from litebox_runner_snp/src/main.rs demonstrates how the runner initializes the platform and transfers control to the guest program:
#[unsafe(no_mangle)]
pub extern "C" fn sandbox_process_init(
_pt_regs: &mut litebox_common_linux::PtRegs,
boot_params: &'static litebox_platform_linux_kernel::host::snp::snp_impl::vmpl2_boot_params,
) -> ! {
// 1️⃣ Initialise the platform (GHCB, CPU frequency, etc.)
ghcb_prints("sandbox_kernel_init called\n");
// 2️⃣ Build the LiteBox shim
let mut shim_builder = litebox_shim_linux::LinuxShimBuilder::new();
let litebox = shim_builder.litebox();
let in_mem_fs = litebox::fs::in_mem::FileSystem::new(litebox);
shim_builder.set_fs(shim_builder.default_fs(in_mem_fs, /* ... */));
// 3️⃣ Parse argv / env from the boot params
let (program, argv, envp) = parse_args(boot_params).expect("invalid args");
// 4️⃣ Load the guest ELF and store the shim globally
let shim = shim_builder.build();
unsafe { SHIM = Some(shim) };
// 5️⃣ Load the program and start the first thread
let program = SHIM.as_ref().unwrap()
.load_program(platform.init_task(boot_params), &program, argv, envp)
.expect("load failed");
// 6️⃣ Transfer control to the guest thread (never returns)
unsafe {
litebox_platform_linux_kernel::host::snp::snp_impl::run_thread(
alloc::boxed::Box::new(program.entrypoints),
_pt_regs,
)
}
}
This initialization sequence demonstrates how the SEV SNP runner transitions from bare-metal VM state to executing a sandboxed Linux binary, with all host communication routed through the GHCB protocol established during the kernel initialization phase.
Summary
The SEV SNP runner is the critical no_std binary that enables LiteBox to operate within AMD SEV-SNP confidential computing environments. Key takeaways include:
- Minimal Footprint: The runner is a
no_stdRust binary compiled with a custom target, eliminating standard library dependencies that could compromise the trusted computing base. - GHCB-Based Communication: All host interactions—including memory allocation, debug output, and VM termination—flow through the Guest-Host Communication Block protocol defined in
snp_impl.rs. - Three-Phase Boot: The runner progresses from assembly entry (
_start) to kernel initialization (sandbox_kernel_init) to process initialization (sandbox_process_init) before transferring control to the guest program viarun_thread. - Encrypted Memory: The runner ensures all guest pages are marked with the SEV encryption bit (
PRIVATE_PTE_MASK = 1 << 51), maintaining confidentiality even from the hypervisor. - Standardized Termination: Error handling uses AMD SEV-SNP termination constants (
SM_SEV_TERM_SET = 0x3) to communicate shutdown reasons to the VMM via theterminatehypercall.
Frequently Asked Questions
What is the primary purpose of the SEV SNP runner in LiteBox?
The SEV SNP runner serves as the secure bootstrapper and runtime environment for LiteBox inside AMD SEV-SNP virtual machines. It is a no_std binary that initializes the GHCB communication channel, sets up encrypted memory pages using the SEV encryption bit, and bridges Linux user-mode system calls to the host VMM while maintaining strict confidentiality guarantees against a potentially malicious hypervisor.
How does the SEV SNP runner communicate with the host VMM?
All communication flows through the Guest-Host Communication Block (GHCB) protocol implemented in snp_impl.rs. During initialization, GhcbProtocol::setup_ghcb_page validates the GHCB page address provided in vmpl2_boot_params and maps it for use. The runner then uses this channel for debug output via ghcb_prints, memory allocation requests through HostSnpInterface::alloc, and VM termination via the terminate hypercall. This protocol ensures that all host interactions follow AMD SEV-SNP security specifications.
What happens when the SEV SNP runner encounters a fatal error?
Fatal errors trigger the SEV-SNP termination protocol defined in globals.rs. The runner invokes HostSnpInterface::terminate with SM_SEV_TERM_SET (0x3) and a specific reason code such as SM_TERM_EXCEPTION for unhandled page faults or SM_TERM_INVALID_PARAM for boot parameter errors. This generates a SEV-SNP "VM exit with termination request" that forces the VMM to shut down the VM cleanly while preserving the error code for host-side logging and debugging.
How is the SEV SNP runner different from standard LiteBox runners?
Unlike standard runners that may execute within a traditional Linux environment or rely on the Rust standard library, the SEV SNP runner is built with no_std and targets a custom JSON target specification (litebox_runner_snp/target.json). It operates exclusively within the SEV-SNP trust boundary, managing memory encryption explicitly via PRIVATE_PTE_MASK and using GHCB-based hypercalls rather than standard system calls. This design eliminates dependencies on the host operating system, reducing the attack surface for confidential computing workloads.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →