From 98889bea69ed914c56bd60f73e74253ca92e7fc4 Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Thu, 19 Mar 2026 16:43:13 -0700 Subject: [PATCH 1/2] Remove Linux-only restriction from map_region on MultiUseSandbox The map_region method and its tests were gated behind #[cfg(target_os = "linux")] but the underlying VM trait (VirtualMachine::map_memory) has implementations for KVM, MSHV, and WHP (Windows). The method itself contains no platform-specific code. - Remove #[cfg(target_os = "linux")] from map_region, its imports (log_then_return, MemoryRegionFlags), and all related tests/helpers - Fix region_for_memory helper to use platform-correct host base type (HostRegionBase on Windows, usize on Linux) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: James Sturtevant --- .../src/sandbox/initialized_multi_use.rs | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/src/hyperlight_host/src/sandbox/initialized_multi_use.rs b/src/hyperlight_host/src/sandbox/initialized_multi_use.rs index 8f147c11c..a1296a0f6 100644 --- a/src/hyperlight_host/src/sandbox/initialized_multi_use.rs +++ b/src/hyperlight_host/src/sandbox/initialized_multi_use.rs @@ -32,20 +32,16 @@ use super::file_mapping::prepare_file_cow; use super::host_funcs::FunctionRegistry; use super::snapshot::Snapshot; use crate::HyperlightError::{self, SnapshotSandboxMismatch}; -use crate::Result; use crate::func::{ParameterTuple, SupportedReturnType}; use crate::hypervisor::InterruptHandle; use crate::hypervisor::hyperlight_vm::{HyperlightVm, HyperlightVmError}; -#[cfg(target_os = "linux")] -use crate::log_then_return; -use crate::mem::memory_region::MemoryRegion; -#[cfg(target_os = "linux")] -use crate::mem::memory_region::MemoryRegionFlags; +use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags}; use crate::mem::mgr::SandboxMemoryManager; use crate::mem::shared_mem::{HostSharedMemory, SharedMemory as _}; use crate::metrics::{ METRIC_GUEST_ERROR, METRIC_GUEST_ERROR_LABEL_CODE, maybe_time_and_emit_guest_call, }; +use crate::{Result, log_then_return}; /// A fully initialized sandbox that can execute guest functions multiple times. /// @@ -525,7 +521,6 @@ impl MultiUseSandbox { /// The caller must ensure the host memory region remains valid and unmodified /// for the lifetime of `self`. #[instrument(err(Debug), skip(self, rgn), parent = Span::current())] - #[cfg(target_os = "linux")] pub unsafe fn map_region(&mut self, rgn: &MemoryRegion) -> Result<()> { if self.poisoned { return Err(crate::HyperlightError::PoisonedSandbox); @@ -914,9 +909,7 @@ mod tests { use hyperlight_testing::sandbox_sizes::{LARGE_HEAP_SIZE, MEDIUM_HEAP_SIZE, SMALL_HEAP_SIZE}; use hyperlight_testing::simple_guest_as_string; - #[cfg(target_os = "linux")] use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags, MemoryRegionType}; - #[cfg(target_os = "linux")] use crate::mem::shared_mem::{ExclusiveSharedMemory, GuestSharedMemory, SharedMemory as _}; use crate::sandbox::SandboxConfiguration; use crate::{GuestBinary, HyperlightError, MultiUseSandbox, Result, UninitializedSandbox}; @@ -955,7 +948,6 @@ mod tests { } // map_region should fail when poisoned - #[cfg(target_os = "linux")] { let map_mem = allocate_guest_memory(); let guest_base = 0x0; @@ -965,7 +957,6 @@ mod tests { } // map_file_cow should fail when poisoned - #[cfg(target_os = "linux")] { let temp_file = std::env::temp_dir().join("test_poison_map_file.bin"); let res = sbox.map_file_cow(&temp_file, 0x0, None).unwrap_err(); @@ -1227,7 +1218,6 @@ mod tests { } } - #[cfg(target_os = "linux")] #[test] fn test_mmap() { let mut sbox = UninitializedSandbox::new( @@ -1263,7 +1253,6 @@ mod tests { } // Makes sure MemoryRegionFlags::READ | MemoryRegionFlags::EXECUTE executable but not writable - #[cfg(target_os = "linux")] #[test] fn test_mmap_write_exec() { let mut sbox = UninitializedSandbox::new( @@ -1312,7 +1301,6 @@ mod tests { }; } - #[cfg(target_os = "linux")] fn page_aligned_memory(src: &[u8]) -> GuestSharedMemory { use hyperlight_common::mem::PAGE_SIZE_USIZE; @@ -1326,29 +1314,33 @@ mod tests { guest_mem } - #[cfg(target_os = "linux")] fn region_for_memory( mem: &GuestSharedMemory, guest_base: usize, flags: MemoryRegionFlags, ) -> MemoryRegion { - let ptr = mem.base_addr(); + #[cfg(not(windows))] + let host_base = mem.base_addr(); + #[cfg(windows)] + let host_base = mem.host_region_base(); let len = mem.mem_size(); + let host_end = + ::add( + host_base, len, + ); MemoryRegion { - host_region: ptr..(ptr + len), + host_region: host_base..host_end, guest_region: guest_base..(guest_base + len), flags, region_type: MemoryRegionType::Heap, } } - #[cfg(target_os = "linux")] fn allocate_guest_memory() -> GuestSharedMemory { page_aligned_memory(b"test data for snapshot") } #[test] - #[cfg(target_os = "linux")] fn snapshot_restore_handles_remapping_correctly() { let mut sbox: MultiUseSandbox = { let path = simple_guest_as_string().unwrap(); From a61a7a8b11f7b647dc45b0eeaf68aa15dbca73a6 Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Thu, 19 Mar 2026 17:54:25 -0700 Subject: [PATCH 2/2] Add cross-platform host_region_base/end helpers to SharedMemory Replace platform-conditional #[cfg] blocks and verbose turbofish calls with host_region_base() and host_region_end() on SharedMemory. This simplifies mapping_at() and the test region_for_memory helper. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: James Sturtevant --- src/hyperlight_host/src/mem/shared_mem.rs | 38 ++++++++++++------- .../src/sandbox/initialized_multi_use.rs | 10 +---- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/hyperlight_host/src/mem/shared_mem.rs b/src/hyperlight_host/src/mem/shared_mem.rs index 5c4a1a63f..367722f6d 100644 --- a/src/hyperlight_host/src/mem/shared_mem.rs +++ b/src/hyperlight_host/src/mem/shared_mem.rs @@ -721,14 +721,9 @@ impl GuestSharedMemory { ), }; let guest_base = guest_base as usize; - #[cfg(not(windows))] - let host_base = self.base_addr(); - #[cfg(windows)] - let host_base = self.host_region_base(); - let host_end = ::add(host_base, self.mem_size()); MemoryRegion { guest_region: guest_base..(guest_base + self.mem_size()), - host_region: host_base..host_end, + host_region: self.host_region_base()..self.host_region_end(), region_type, flags, } @@ -779,15 +774,30 @@ pub trait SharedMemory { } /// Extract a base address that can be mapped into a VM for this - /// SharedMemory - #[cfg(target_os = "windows")] - fn host_region_base(&self) -> super::memory_region::HostRegionBase { - super::memory_region::HostRegionBase { - from_handle: self.region().handle.into(), - handle_base: self.region().ptr as usize, - handle_size: self.region().size, - offset: PAGE_SIZE_USIZE, + /// SharedMemory. + /// + /// On Linux this returns a raw `usize` pointer. On Windows it + /// returns a [`HostRegionBase`](super::memory_region::HostRegionBase) + /// that carries the file-mapping handle metadata needed by WHP. + fn host_region_base(&self) -> ::HostBaseType { + #[cfg(not(windows))] + { + self.base_addr() } + #[cfg(windows)] + { + super::memory_region::HostRegionBase { + from_handle: self.region().handle.into(), + handle_base: self.region().ptr as usize, + handle_size: self.region().size, + offset: PAGE_SIZE_USIZE, + } + } + } + + /// Return the end address of the host region (base + usable size). + fn host_region_end(&self) -> ::HostBaseType { + ::add(self.host_region_base(), self.mem_size()) } /// Run some code with exclusive access to the SharedMemory diff --git a/src/hyperlight_host/src/sandbox/initialized_multi_use.rs b/src/hyperlight_host/src/sandbox/initialized_multi_use.rs index a1296a0f6..3c206dc65 100644 --- a/src/hyperlight_host/src/sandbox/initialized_multi_use.rs +++ b/src/hyperlight_host/src/sandbox/initialized_multi_use.rs @@ -1319,17 +1319,9 @@ mod tests { guest_base: usize, flags: MemoryRegionFlags, ) -> MemoryRegion { - #[cfg(not(windows))] - let host_base = mem.base_addr(); - #[cfg(windows)] - let host_base = mem.host_region_base(); let len = mem.mem_size(); - let host_end = - ::add( - host_base, len, - ); MemoryRegion { - host_region: host_base..host_end, + host_region: mem.host_region_base()..mem.host_region_end(), guest_region: guest_base..(guest_base + len), flags, region_type: MemoryRegionType::Heap,