From 88c7fe78ab2cdb736cc008224ca56ea2480617f3 Mon Sep 17 00:00:00 2001 From: Simon Davies Date: Mon, 16 Mar 2026 20:53:06 +0000 Subject: [PATCH] map types public Signed-off-by: Simon Davies --- src/hyperlight_host/src/hypervisor/mod.rs | 2 +- src/hyperlight_host/src/mem/memory_region.rs | 8 +- src/hyperlight_host/tests/integration_test.rs | 80 +++++++++++++++++++ 3 files changed, 85 insertions(+), 5 deletions(-) diff --git a/src/hyperlight_host/src/hypervisor/mod.rs b/src/hyperlight_host/src/hypervisor/mod.rs index a582ddb09..18c13c242 100644 --- a/src/hyperlight_host/src/hypervisor/mod.rs +++ b/src/hyperlight_host/src/hypervisor/mod.rs @@ -31,7 +31,7 @@ pub(crate) mod surrogate_process; pub(crate) mod surrogate_process_manager; /// Safe wrappers around windows types like `PSTR` #[cfg(target_os = "windows")] -pub(crate) mod wrappers; +pub mod wrappers; #[cfg(crashdump)] pub(crate) mod crashdump; diff --git a/src/hyperlight_host/src/mem/memory_region.rs b/src/hyperlight_host/src/mem/memory_region.rs index ba193e533..4fc15c2ba 100644 --- a/src/hyperlight_host/src/mem/memory_region.rs +++ b/src/hyperlight_host/src/mem/memory_region.rs @@ -129,7 +129,7 @@ impl TryFrom for MemoryRegionFlags { // and crash dumps. Not part of the public API. #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] /// The type of memory region -pub(crate) enum MemoryRegionType { +pub enum MemoryRegionType { /// The region contains the guest's code Code, /// The region contains the guest's init data @@ -156,7 +156,7 @@ impl MemoryRegionType { /// `MappedFile` regions use read-only file-backed mappings with no /// guard pages; all other region types use the standard sandbox /// shared memory mapping with guard pages. - pub(crate) fn surrogate_mapping(&self) -> SurrogateMapping { + pub fn surrogate_mapping(&self) -> SurrogateMapping { match self { MemoryRegionType::MappedFile => SurrogateMapping::ReadOnlyFile, _ => SurrogateMapping::SandboxMemory, @@ -203,7 +203,7 @@ impl MemoryRegionKind for HostGuestMemoryRegion { /// behaviour when projected into the surrogate process via `MapViewOfFileNuma2`. #[cfg(target_os = "windows")] #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] -pub(crate) enum SurrogateMapping { +pub enum SurrogateMapping { /// Standard sandbox shared memory: mapped with `PAGE_READWRITE` protection /// and guard pages (`PAGE_NOACCESS`) set on the first and last pages. SandboxMemory, @@ -293,7 +293,7 @@ pub struct MemoryRegion_ { /// memory access flags for the given region pub flags: MemoryRegionFlags, /// the type of memory region - pub(crate) region_type: MemoryRegionType, + pub region_type: MemoryRegionType, } /// A memory region that tracks both host and guest addresses. diff --git a/src/hyperlight_host/tests/integration_test.rs b/src/hyperlight_host/tests/integration_test.rs index 80f997360..a6e71a24d 100644 --- a/src/hyperlight_host/tests/integration_test.rs +++ b/src/hyperlight_host/tests/integration_test.rs @@ -1768,3 +1768,83 @@ fn interrupt_cancel_delete_race() { handle.join().unwrap(); } } + +/// Compile-time regression guard for public visibility of memory +/// region types. +/// +/// This test MUST live in an integration test (not a unit test) +/// because integration tests are compiled as separate crates and can +/// only access items marked `pub`. A unit test inside the crate +/// would also see `pub(crate)` items, defeating the purpose. +/// +/// If any of these types or fields revert to `pub(crate)`, this test +/// will fail to **compile** — catching the regression before CI even +/// runs the test binary. +#[test] +fn memory_region_types_are_publicly_accessible() { + use hyperlight_host::mem::memory_region::{ + HostGuestMemoryRegion, MemoryRegion_, MemoryRegionFlags, MemoryRegionKind, MemoryRegionType, + }; + + // This test is a compile-time guard. If it compiles, it passes. + // Every line below would cause a compile error if the referenced + // type, variant, or field reverted to pub(crate). + + // MemoryRegionType enum and all its variants are pub + let _rt = MemoryRegionType::Code; + let _rt = MemoryRegionType::InitData; + let _rt = MemoryRegionType::Peb; + let _rt = MemoryRegionType::Heap; + let _rt = MemoryRegionType::Scratch; + let _rt = MemoryRegionType::Snapshot; + let _rt = MemoryRegionType::MappedFile; + + // MemoryRegionFlags is pub and combinable + let _flags = MemoryRegionFlags::READ | MemoryRegionFlags::WRITE | MemoryRegionFlags::EXECUTE; + + // SurrogateMapping enum and MemoryRegionType::surrogate_mapping() + // are pub (Windows only). + #[cfg(target_os = "windows")] + { + use hyperlight_host::mem::memory_region::SurrogateMapping; + + let mapping = MemoryRegionType::MappedFile.surrogate_mapping(); + let _: SurrogateMapping = mapping; + let _ = SurrogateMapping::SandboxMemory; + let _ = SurrogateMapping::ReadOnlyFile; + } + + // MemoryRegion_ struct and all its fields are pub (struct literal + // construction requires every field to be pub). + #[cfg(not(target_os = "windows"))] + { + let base: ::HostBaseType = 0x1000; + let _region = MemoryRegion_:: { + guest_region: 0x1000..0x2000, + host_region: base..::add(base, 0x1000), + flags: MemoryRegionFlags::READ, + region_type: MemoryRegionType::Code, + }; + } + + #[cfg(target_os = "windows")] + { + use hyperlight_host::hypervisor::wrappers::HandleWrapper; + use hyperlight_host::mem::memory_region::HostRegionBase; + use windows::Win32::Foundation::HANDLE; + + let host_base = HostRegionBase { + from_handle: HandleWrapper::from(HANDLE(std::ptr::null_mut())), + handle_base: 0x1000, + handle_size: 0x1000, + offset: 0, + }; + let _region = MemoryRegion_:: { + guest_region: 0x1000..0x2000, + host_region: host_base + ..::add(host_base, 0x1000), + flags: MemoryRegionFlags::READ, + region_type: MemoryRegionType::Code, + }; + } +}