diff --git a/CHANGELOG.md b/CHANGELOG.md index a7c7c6ae7..52058d068 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Added ### Changed +* **Breaking:** Filesystem paths are now represented using `PathBuf`. `GuestBinary::FilePath` now stores a `PathBuf` instead of a `String`, and `MultiUseSandbox::generate_crashdump_to_dir` accepts `Into` instead of `Into`. Callers passing a `String` to `GuestBinary::FilePath` must convert it using `.into()`. ### Removed diff --git a/fuzz/fuzz_targets/guest_call.rs b/fuzz/fuzz_targets/guest_call.rs index bc0ff163f..decc65f1e 100644 --- a/fuzz/fuzz_targets/guest_call.rs +++ b/fuzz/fuzz_targets/guest_call.rs @@ -21,7 +21,7 @@ use std::sync::{Mutex, OnceLock}; use hyperlight_host::func::{ParameterValue, ReturnType}; use hyperlight_host::sandbox::uninitialized::GuestBinary; use hyperlight_host::{MultiUseSandbox, UninitializedSandbox}; -use hyperlight_testing::simple_guest_for_fuzzing_as_string; +use hyperlight_testing::simple_guest_for_fuzzing_as_pathbuf; use libfuzzer_sys::fuzz_target; static SANDBOX: OnceLock> = OnceLock::new(); @@ -31,7 +31,7 @@ fuzz_target!( init: { let u_sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_for_fuzzing_as_string().expect("Guest Binary Missing")), + GuestBinary::FilePath(simple_guest_for_fuzzing_as_pathbuf()), None, ) .unwrap(); diff --git a/fuzz/fuzz_targets/guest_trace.rs b/fuzz/fuzz_targets/guest_trace.rs index 3dfb61c95..1ef633804 100644 --- a/fuzz/fuzz_targets/guest_trace.rs +++ b/fuzz/fuzz_targets/guest_trace.rs @@ -25,7 +25,7 @@ use hyperlight_host::func::{ParameterValue, ReturnType, ReturnValue}; use hyperlight_host::sandbox::SandboxConfiguration; use hyperlight_host::sandbox::uninitialized::GuestBinary; use hyperlight_host::{MultiUseSandbox, UninitializedSandbox}; -use hyperlight_testing::simple_guest_for_fuzzing_as_string; +use hyperlight_testing::simple_guest_for_fuzzing_as_pathbuf; use libfuzzer_sys::arbitrary::Arbitrary; use libfuzzer_sys::{Corpus, fuzz_target}; @@ -71,12 +71,9 @@ fuzz_target!( let mut cfg = SandboxConfiguration::default(); // In local tests, 256 KiB seemed sufficient for deep recursion cfg.set_scratch_size(256 * 1024); - let path = simple_guest_for_fuzzing_as_string().expect("Guest Binary Missing"); - let u_sbox = UninitializedSandbox::new( - GuestBinary::FilePath(path), - Some(cfg), - ) - .unwrap(); + let path = simple_guest_for_fuzzing_as_pathbuf(); + let u_sbox = + UninitializedSandbox::new(GuestBinary::FilePath(path), Some(cfg)).unwrap(); let mu_sbox: MultiUseSandbox = u_sbox.evolve().unwrap(); diff --git a/fuzz/fuzz_targets/host_call.rs b/fuzz/fuzz_targets/host_call.rs index b0d37cf1a..71f9891e4 100644 --- a/fuzz/fuzz_targets/host_call.rs +++ b/fuzz/fuzz_targets/host_call.rs @@ -23,7 +23,7 @@ use hyperlight_host::func::{ParameterValue, ReturnType}; use hyperlight_host::sandbox::SandboxConfiguration; use hyperlight_host::sandbox::uninitialized::GuestBinary; use hyperlight_host::{HyperlightError, MultiUseSandbox, UninitializedSandbox}; -use hyperlight_testing::simple_guest_for_fuzzing_as_string; +use hyperlight_testing::simple_guest_for_fuzzing_as_pathbuf; use libfuzzer_sys::fuzz_target; static SANDBOX: OnceLock> = OnceLock::new(); @@ -37,7 +37,7 @@ fuzz_target!( cfg.set_input_data_size(64 * 1024); // 64 KB input buffer cfg.set_scratch_size(512 * 1024); // large scratch region to contain those buffers, any data copies, etc. let u_sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_for_fuzzing_as_string().expect("Guest Binary Missing")), + GuestBinary::FilePath(simple_guest_for_fuzzing_as_pathbuf()), Some(cfg) ) .unwrap(); diff --git a/fuzz/fuzz_targets/host_print.rs b/fuzz/fuzz_targets/host_print.rs index 59dc1ed13..6b2132a37 100644 --- a/fuzz/fuzz_targets/host_print.rs +++ b/fuzz/fuzz_targets/host_print.rs @@ -4,7 +4,7 @@ use std::sync::{Mutex, OnceLock}; use hyperlight_host::sandbox::uninitialized::GuestBinary; use hyperlight_host::{MultiUseSandbox, UninitializedSandbox}; -use hyperlight_testing::simple_guest_for_fuzzing_as_string; +use hyperlight_testing::simple_guest_for_fuzzing_as_pathbuf; use libfuzzer_sys::{Corpus, fuzz_target}; static SANDBOX: OnceLock> = OnceLock::new(); @@ -16,7 +16,7 @@ static SANDBOX: OnceLock> = OnceLock::new(); fuzz_target!( init: { let u_sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_for_fuzzing_as_string().expect("Guest Binary Missing")), + GuestBinary::FilePath(simple_guest_for_fuzzing_as_pathbuf()), None, ) .unwrap(); diff --git a/src/hyperlight_host/benches/benchmarks.rs b/src/hyperlight_host/benches/benchmarks.rs index 18d1ab4df..1982244bb 100644 --- a/src/hyperlight_host/benches/benchmarks.rs +++ b/src/hyperlight_host/benches/benchmarks.rs @@ -27,7 +27,7 @@ use hyperlight_host::GuestBinary; use hyperlight_host::mem::shared_mem::ExclusiveSharedMemory; use hyperlight_host::sandbox::{MultiUseSandbox, SandboxConfiguration, UninitializedSandbox}; use hyperlight_testing::sandbox_sizes::{LARGE_HEAP_SIZE, MEDIUM_HEAP_SIZE, SMALL_HEAP_SIZE}; -use hyperlight_testing::{c_simple_guest_as_string, simple_guest_as_string}; +use hyperlight_testing::{c_simple_guest_as_pathbuf, simple_guest_as_pathbuf}; /// Sandbox heap size configurations for benchmarking. /// Only affects heap size - all other configuration remains at defaults. @@ -86,7 +86,7 @@ impl SandboxSize { } fn create_uninit_sandbox_with_size(size: SandboxSize) -> UninitializedSandbox { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); UninitializedSandbox::new(GuestBinary::FilePath(path), size.config()).unwrap() } @@ -416,7 +416,7 @@ fn guest_call_benchmark_large_param(c: &mut Criterion) { config.set_scratch_size(6 * SIZE + 4 * (1024 * 1024)); // Big enough for the IO data regions and enough of the heap to be used let sandbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().unwrap()), + GuestBinary::FilePath(simple_guest_as_pathbuf()), Some(config), ) .unwrap(); @@ -494,7 +494,7 @@ fn function_call_serialization_benchmark(c: &mut Criterion) { fn sample_workloads_benchmark(c: &mut Criterion) { let mut group = c.benchmark_group("sample_workloads"); - fn bench_24k_in_8k_out(b: &mut criterion::Bencher, guest_path: String) { + fn bench_24k_in_8k_out(b: &mut criterion::Bencher, guest_path: std::path::PathBuf) { let mut cfg = SandboxConfiguration::default(); cfg.set_input_data_size(25 * 1024); @@ -514,11 +514,11 @@ fn sample_workloads_benchmark(c: &mut Criterion) { } group.bench_function("24K_in_8K_out_c", |b| { - bench_24k_in_8k_out(b, c_simple_guest_as_string().unwrap()); + bench_24k_in_8k_out(b, c_simple_guest_as_pathbuf()); }); group.bench_function("24K_in_8K_out_rust", |b| { - bench_24k_in_8k_out(b, simple_guest_as_string().unwrap()); + bench_24k_in_8k_out(b, simple_guest_as_pathbuf()); }); group.finish(); diff --git a/src/hyperlight_host/examples/crashdump/main.rs b/src/hyperlight_host/examples/crashdump/main.rs index 7b50459d0..8f42a01a8 100644 --- a/src/hyperlight_host/examples/crashdump/main.rs +++ b/src/hyperlight_host/examples/crashdump/main.rs @@ -73,6 +73,7 @@ limitations under the License. #[cfg(all(crashdump, target_os = "linux"))] use std::io::Write; +use std::path::Path; #[cfg(all(crashdump, target_os = "linux"))] use hyperlight_host::HyperlightError; @@ -86,8 +87,7 @@ fn main() -> hyperlight_host::Result<()> { env_logger::init(); } - let guest_path = - hyperlight_testing::simple_guest_as_string().expect("Cannot find simpleguest binary"); + let guest_path = hyperlight_testing::simple_guest_as_pathbuf(); println!("=== Hyperlight Crash Dump Example ===\n"); @@ -139,11 +139,11 @@ fn main() -> hyperlight_host::Result<()> { /// 3. The hypervisor rejects the write → `MemoryAccessViolation` /// 4. The crash dump is written automatically (no explicit call needed) #[cfg(all(crashdump, target_os = "linux"))] -fn guest_crash_auto_dump(guest_path: &str) -> hyperlight_host::Result<()> { +fn guest_crash_auto_dump(guest_path: &Path) -> hyperlight_host::Result<()> { let cfg = SandboxConfiguration::default(); let uninitialized_sandbox = - UninitializedSandbox::new(GuestBinary::FilePath(guest_path.to_string()), Some(cfg))?; + UninitializedSandbox::new(GuestBinary::FilePath(guest_path.to_path_buf()), Some(cfg))?; let mut sandbox: MultiUseSandbox = uninitialized_sandbox.evolve()?; @@ -173,7 +173,7 @@ fn guest_crash_auto_dump(guest_path: &str) -> hyperlight_host::Result<()> { /// Fallback when crashdump feature or Linux is not available. #[cfg(not(all(crashdump, target_os = "linux")))] -fn guest_crash_auto_dump(_guest_path: &str) -> hyperlight_host::Result<()> { +fn guest_crash_auto_dump(_guest_path: &Path) -> hyperlight_host::Result<()> { println!( "This part requires the `crashdump` feature and Linux.\n\ Re-run with: cargo run --example crashdump --features crashdump" @@ -204,11 +204,11 @@ fn create_mapping_file() -> std::path::PathBuf { /// Because the error is reported through the I/O path (not a VM-level /// fault), the automatic crash dump code in the VM run loop is not reached. /// To get a crash dump in this case, call `generate_crashdump()` explicitly. -fn guest_crash_with_on_demand_dump(guest_path: &str) -> hyperlight_host::Result<()> { +fn guest_crash_with_on_demand_dump(guest_path: &Path) -> hyperlight_host::Result<()> { let cfg = SandboxConfiguration::default(); let uninitialized_sandbox = - UninitializedSandbox::new(GuestBinary::FilePath(guest_path.to_string()), Some(cfg))?; + UninitializedSandbox::new(GuestBinary::FilePath(guest_path.to_path_buf()), Some(cfg))?; let mut sandbox: MultiUseSandbox = uninitialized_sandbox.evolve()?; @@ -245,13 +245,13 @@ fn guest_crash_with_on_demand_dump(guest_path: &str) -> hyperlight_host::Result< /// (e.g., during fuzzing or testing) and you don't want the overhead of /// writing core dump files. #[cfg(all(crashdump, target_os = "linux"))] -fn guest_crash_with_dump_disabled(guest_path: &str) -> hyperlight_host::Result<()> { +fn guest_crash_with_dump_disabled(guest_path: &Path) -> hyperlight_host::Result<()> { let mut cfg = SandboxConfiguration::default(); cfg.set_guest_core_dump(false); println!("Core dump disabled for this sandbox."); let uninitialized_sandbox = - UninitializedSandbox::new(GuestBinary::FilePath(guest_path.to_string()), Some(cfg))?; + UninitializedSandbox::new(GuestBinary::FilePath(guest_path.to_path_buf()), Some(cfg))?; let mut sandbox: MultiUseSandbox = uninitialized_sandbox.evolve()?; @@ -277,7 +277,7 @@ fn guest_crash_with_dump_disabled(guest_path: &str) -> hyperlight_host::Result<( /// Fallback when crashdump feature or Linux is not available. #[cfg(not(all(crashdump, target_os = "linux")))] -fn guest_crash_with_dump_disabled(_guest_path: &str) -> hyperlight_host::Result<()> { +fn guest_crash_with_dump_disabled(_guest_path: &Path) -> hyperlight_host::Result<()> { println!( "This part requires the `crashdump` feature and Linux.\n\ Re-run with: cargo run --example crashdump --features crashdump" @@ -387,8 +387,7 @@ mod tests { let data_file = create_test_data_file(dump_dir); // Create sandbox with default config (crashdump enabled) - let guest_path = - hyperlight_testing::simple_guest_as_string().expect("Cannot find simpleguest binary"); + let guest_path = hyperlight_testing::simple_guest_as_pathbuf(); let cfg = SandboxConfiguration::default(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(guest_path), Some(cfg)).unwrap(); @@ -428,7 +427,7 @@ mod tests { // IO-based errors (GuestAborted), so we call generate_crashdump() // explicitly — this is the recommended workflow for post-mortem // debugging anyway. - sbox.generate_crashdump_to_dir(dump_dir.to_string_lossy()) + sbox.generate_crashdump_to_dir(dump_dir) .expect("generate_crashdump should succeed"); // Find the generated hl_core_*.elf file @@ -489,7 +488,7 @@ mod tests { let dump_dir = tempfile::tempdir().expect("create temp dir"); let core_path = generate_crashdump_with_content(dump_dir.path()); - let guest_path = hyperlight_testing::simple_guest_as_string().expect("simpleguest binary"); + let guest_path = hyperlight_testing::simple_guest_as_pathbuf(); let cmd_file = dump_dir.path().join("gdb_reg_cmds.txt"); let out_file = dump_dir.path().join("gdb_reg_output.txt"); @@ -508,7 +507,7 @@ set logging enabled off quit ", out = out_file.display(), - binary = guest_path, + binary = guest_path.display(), core = core_path.display(), ); @@ -536,7 +535,7 @@ quit fn test_crashdump_gdb_memory() { let dump_dir = tempfile::tempdir().expect("create temp dir"); let core_path = generate_crashdump_with_content(dump_dir.path()); - let guest_path = hyperlight_testing::simple_guest_as_string().expect("simpleguest binary"); + let guest_path = hyperlight_testing::simple_guest_as_pathbuf(); let cmd_file = dump_dir.path().join("gdb_mem_cmds.txt"); let out_file = dump_dir.path().join("gdb_mem_output.txt"); @@ -557,7 +556,7 @@ set logging enabled off quit ", out = out_file.display(), - binary = guest_path, + binary = guest_path.display(), core = core_path.display(), addr = MAP_GUEST_BASE, ); diff --git a/src/hyperlight_host/examples/func_ctx/main.rs b/src/hyperlight_host/examples/func_ctx/main.rs index 8aedf0983..6348cdc0f 100644 --- a/src/hyperlight_host/examples/func_ctx/main.rs +++ b/src/hyperlight_host/examples/func_ctx/main.rs @@ -16,12 +16,12 @@ limitations under the License. use hyperlight_host::GuestBinary; use hyperlight_host::sandbox::UninitializedSandbox; -use hyperlight_testing::simple_guest_as_string; +use hyperlight_testing::simple_guest_as_pathbuf; fn main() { // create a new `MultiUseSandbox` configured to run the `simpleguest.exe` // test guest binary - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let mut sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None) .unwrap() .evolve() diff --git a/src/hyperlight_host/examples/guest-debugging/main.rs b/src/hyperlight_host/examples/guest-debugging/main.rs index 4ced2f8cf..dcc2c5da2 100644 --- a/src/hyperlight_host/examples/guest-debugging/main.rs +++ b/src/hyperlight_host/examples/guest-debugging/main.rs @@ -40,17 +40,13 @@ fn main() -> hyperlight_host::Result<()> { // Create an uninitialized sandbox with a guest binary and debug enabled let mut uninitialized_sandbox_dbg = UninitializedSandbox::new( - hyperlight_host::GuestBinary::FilePath( - hyperlight_testing::simple_guest_as_string().unwrap(), - ), + hyperlight_host::GuestBinary::FilePath(hyperlight_testing::simple_guest_as_pathbuf()), cfg, // sandbox configuration )?; // Create an uninitialized sandbox with a guest binary let mut uninitialized_sandbox = UninitializedSandbox::new( - hyperlight_host::GuestBinary::FilePath( - hyperlight_testing::simple_guest_as_string().unwrap(), - ), + hyperlight_host::GuestBinary::FilePath(hyperlight_testing::simple_guest_as_pathbuf()), None, // sandbox configuration )?; @@ -378,9 +374,7 @@ mod tests { // Build a sandbox the normal way and snapshot it in-memory. let mut producer: MultiUseSandbox = UninitializedSandbox::new( - hyperlight_host::GuestBinary::FilePath( - hyperlight_testing::simple_guest_as_string().unwrap(), - ), + hyperlight_host::GuestBinary::FilePath(hyperlight_testing::simple_guest_as_pathbuf()), None, ) .unwrap() diff --git a/src/hyperlight_host/examples/hello-world/main.rs b/src/hyperlight_host/examples/hello-world/main.rs index 03b43b071..0a0ab1ea8 100644 --- a/src/hyperlight_host/examples/hello-world/main.rs +++ b/src/hyperlight_host/examples/hello-world/main.rs @@ -20,9 +20,7 @@ use hyperlight_host::{MultiUseSandbox, UninitializedSandbox}; fn main() -> hyperlight_host::Result<()> { // Create an uninitialized sandbox with a guest binary let mut uninitialized_sandbox = UninitializedSandbox::new( - hyperlight_host::GuestBinary::FilePath( - hyperlight_testing::simple_guest_as_string().unwrap(), - ), + hyperlight_host::GuestBinary::FilePath(hyperlight_testing::simple_guest_as_pathbuf()), None, // default configuration )?; diff --git a/src/hyperlight_host/examples/logging/main.rs b/src/hyperlight_host/examples/logging/main.rs index fae852a8e..8c793dccb 100644 --- a/src/hyperlight_host/examples/logging/main.rs +++ b/src/hyperlight_host/examples/logging/main.rs @@ -19,7 +19,7 @@ use std::sync::{Arc, Barrier}; use hyperlight_host::sandbox::uninitialized::UninitializedSandbox; use hyperlight_host::{GuestBinary, Result}; -use hyperlight_testing::simple_guest_as_string; +use hyperlight_testing::simple_guest_as_pathbuf; fn fn_writer(_msg: String) -> Result { Ok(0) @@ -33,8 +33,7 @@ fn main() -> Result<()> { .parse_filters("none,hyperlight=info") .init(); // Get the path to a simple guest binary. - let hyperlight_guest_path = - simple_guest_as_string().expect("Cannot find the guest binary at the expected location."); + let hyperlight_guest_path = simple_guest_as_pathbuf(); for _ in 0..20 { let path = hyperlight_guest_path.clone(); diff --git a/src/hyperlight_host/examples/map-file-cow-test/main.rs b/src/hyperlight_host/examples/map-file-cow-test/main.rs index 2433b6ef5..8e4d1eff1 100644 --- a/src/hyperlight_host/examples/map-file-cow-test/main.rs +++ b/src/hyperlight_host/examples/map-file-cow-test/main.rs @@ -39,9 +39,7 @@ fn run_once(test_file: &Path, label: &str) -> hyperlight_host::Result<()> { config.set_scratch_size(64 * 1024 * 1024); let mut usbox = UninitializedSandbox::new( - hyperlight_host::GuestBinary::FilePath( - hyperlight_testing::simple_guest_as_string().unwrap(), - ), + hyperlight_host::GuestBinary::FilePath(hyperlight_testing::simple_guest_as_pathbuf()), Some(config), )?; eprintln!("[{label}] UninitializedSandbox::new OK"); diff --git a/src/hyperlight_host/examples/metrics/main.rs b/src/hyperlight_host/examples/metrics/main.rs index f92a60d10..61adbc0c5 100644 --- a/src/hyperlight_host/examples/metrics/main.rs +++ b/src/hyperlight_host/examples/metrics/main.rs @@ -19,7 +19,7 @@ use std::thread::{JoinHandle, spawn}; use hyperlight_host::sandbox::uninitialized::UninitializedSandbox; use hyperlight_host::{GuestBinary, Result}; -use hyperlight_testing::simple_guest_as_string; +use hyperlight_testing::simple_guest_as_pathbuf; // Run this rust example with the flag --features "function_call_metrics" to enable more metrics to be emitted @@ -42,8 +42,7 @@ fn main() { fn do_hyperlight_stuff() { // Get the path to a simple guest binary. - let hyperlight_guest_path = - simple_guest_as_string().expect("Cannot find the guest binary at the expected location."); + let hyperlight_guest_path = simple_guest_as_pathbuf(); let mut join_handles: Vec>> = vec![]; diff --git a/src/hyperlight_host/examples/tracing-chrome/main.rs b/src/hyperlight_host/examples/tracing-chrome/main.rs index d685dae2d..b251a9da2 100644 --- a/src/hyperlight_host/examples/tracing-chrome/main.rs +++ b/src/hyperlight_host/examples/tracing-chrome/main.rs @@ -15,7 +15,7 @@ limitations under the License. */ use hyperlight_host::sandbox::uninitialized::UninitializedSandbox; use hyperlight_host::{GuestBinary, Result}; -use hyperlight_testing::simple_guest_as_string; +use hyperlight_testing::simple_guest_as_pathbuf; use tracing_chrome::ChromeLayerBuilder; use tracing_subscriber::prelude::*; @@ -25,8 +25,7 @@ fn main() -> Result<()> { let (chrome_layer, _guard) = ChromeLayerBuilder::new().build(); tracing_subscriber::registry().with(chrome_layer).init(); - let simple_guest_path = - simple_guest_as_string().expect("Cannot find the guest binary at the expected location."); + let simple_guest_path = simple_guest_as_pathbuf(); // Create a new sandbox. let usandbox = UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_path), None)?; diff --git a/src/hyperlight_host/examples/tracing-otlp/main.rs b/src/hyperlight_host/examples/tracing-otlp/main.rs index 737b1b12d..49b61cc72 100644 --- a/src/hyperlight_host/examples/tracing-otlp/main.rs +++ b/src/hyperlight_host/examples/tracing-otlp/main.rs @@ -26,7 +26,7 @@ use std::thread::{JoinHandle, spawn}; use hyperlight_host::sandbox::uninitialized::UninitializedSandbox; use hyperlight_host::{GuestBinary, Result as HyperlightResult}; -use hyperlight_testing::simple_guest_as_string; +use hyperlight_testing::simple_guest_as_pathbuf; use opentelemetry::trace::TracerProvider; use opentelemetry::{KeyValue, global}; use opentelemetry_otlp::{Protocol, SpanExporter, WithExportConfig}; @@ -97,8 +97,7 @@ fn init_tracing_subscriber( fn run_example(wait_input: bool) -> HyperlightResult<()> { // Get the path to a simple guest binary. - let hyperlight_guest_path = - simple_guest_as_string().expect("Cannot find the guest binary at the expected location."); + let hyperlight_guest_path = simple_guest_as_pathbuf(); let mut join_handles: Vec>> = vec![]; diff --git a/src/hyperlight_host/examples/tracing/main.rs b/src/hyperlight_host/examples/tracing/main.rs index 49cf24e2a..d13313eed 100644 --- a/src/hyperlight_host/examples/tracing/main.rs +++ b/src/hyperlight_host/examples/tracing/main.rs @@ -20,7 +20,7 @@ use std::thread::{JoinHandle, spawn}; use hyperlight_host::sandbox::uninitialized::UninitializedSandbox; use hyperlight_host::{GuestBinary, Result}; -use hyperlight_testing::simple_guest_as_string; +use hyperlight_testing::simple_guest_as_pathbuf; use tracing_forest::ForestLayer; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; @@ -45,8 +45,7 @@ fn main() -> Result<()> { } fn run_example() -> Result<()> { // Get the path to a simple guest binary. - let hyperlight_guest_path = - simple_guest_as_string().expect("Cannot find the guest binary at the expected location."); + let hyperlight_guest_path = simple_guest_as_pathbuf(); let mut join_handles: Vec>> = vec![]; diff --git a/src/hyperlight_host/src/hypervisor/crashdump.rs b/src/hyperlight_host/src/hypervisor/crashdump.rs index b821fba5f..391c3673c 100644 --- a/src/hyperlight_host/src/hypervisor/crashdump.rs +++ b/src/hyperlight_host/src/hypervisor/crashdump.rs @@ -16,6 +16,7 @@ limitations under the License. use std::cmp::min; use std::io::Write; +use std::path::PathBuf; use chrono; use elfcore::{ @@ -50,8 +51,7 @@ pub(crate) struct CrashDumpContext { regs: [u64; 27], xsave: Vec, entry: u64, - binary: Option, - filename: Option, + binary: Option, } impl CrashDumpContext { @@ -60,8 +60,7 @@ impl CrashDumpContext { regs: [u64; 27], xsave: Vec, entry: u64, - binary: Option, - filename: Option, + binary: Option, ) -> Self { Self { regions, @@ -69,7 +68,6 @@ impl CrashDumpContext { xsave, entry, binary, - filename, } } } @@ -104,14 +102,19 @@ impl GuestView { .collect(); let filename = ctx - .filename - .as_ref() - .map_or("".to_string(), |s| s.to_string()); + .binary + .as_deref() + .and_then(|path| path.file_name()) + .map_or("".to_string(), |name| { + name.to_string_lossy().into_owned() + }); let cmd = ctx .binary - .as_ref() - .map_or("".to_string(), |s| s.to_string()); + .as_deref() + .map_or("".to_string(), |path| { + path.to_string_lossy().into_owned() + }); // The xsave state is checked as it can be empty let mut components = vec![]; @@ -271,7 +274,7 @@ impl ReadProcessMemory for GuestMemReader { pub(crate) fn generate_crashdump( hv: &HyperlightVm, mem_mgr: &mut SandboxMemoryManager, - override_dir: Option, + override_dir: Option, ) -> Result<()> { // Get crash context from hypervisor let ctx = hv @@ -279,7 +282,8 @@ pub(crate) fn generate_crashdump( .map_err(|e| new_error!("Failed to get crashdump context: {:?}", e))?; // Prefer the explicit override, then the env var, then the system temp dir - let core_dump_dir = override_dir.or_else(|| std::env::var("HYPERLIGHT_CORE_DUMP_DIR").ok()); + let core_dump_dir = + override_dir.or_else(|| std::env::var_os("HYPERLIGHT_CORE_DUMP_DIR").map(PathBuf::from)); // Compute file path on the filesystem let file_path = core_dump_file_path(core_dump_dir); @@ -294,8 +298,8 @@ pub(crate) fn generate_crashdump( if let Ok(nbytes) = checked_core_dump(ctx, create_dump_file) { if nbytes > 0 { - println!("Core dump created successfully: {}", file_path); - tracing::error!("Core dump file: {}", file_path); + println!("Core dump created successfully: {}", file_path.display()); + tracing::error!("Core dump file: {}", file_path.display()); } } else { tracing::error!("Failed to create core dump file"); @@ -316,8 +320,8 @@ pub(crate) fn generate_crashdump( /// * `dump_dir`: The environment variable value to check for the output directory. /// /// Returns: -/// * `String`: The file path for the core dump file. -fn core_dump_file_path(dump_dir: Option) -> String { +/// * `PathBuf`: The file path for the core dump file. +fn core_dump_file_path(dump_dir: Option) -> PathBuf { // Generate timestamp string for the filename using chrono let timestamp = chrono::Local::now() .format("%Y%m%d_T%H%M%S%.3f") @@ -328,12 +332,12 @@ fn core_dump_file_path(dump_dir: Option) -> String { // Check if the directory exists // If it doesn't exist, fall back to the system temp directory // This is to ensure that the core dump can be created even if the directory is not set - if std::path::Path::new(&dump_dir).exists() { - std::path::PathBuf::from(dump_dir) + if dump_dir.exists() { + dump_dir } else { tracing::warn!( "Directory \"{}\" does not exist, falling back to temp directory", - dump_dir + dump_dir.display() ); std::env::temp_dir() } @@ -344,9 +348,7 @@ fn core_dump_file_path(dump_dir: Option) -> String { // Create the filename with timestamp let filename = format!("hl_core_{}.elf", timestamp); - let file_path = output_dir.join(filename); - - file_path.to_string_lossy().to_string() + output_dir.join(filename) } /// Create core dump from Hypervisor context if the sandbox is configured to allow core dumps. @@ -395,16 +397,13 @@ mod test { #[test] fn test_crashdump_file_path_valid() { // Get CWD - let valid_dir = std::env::current_dir() - .unwrap() - .to_string_lossy() - .to_string(); + let valid_dir = std::env::current_dir().unwrap(); // Call the function let path = core_dump_file_path(Some(valid_dir.clone())); // Check if the path is correct - assert!(path.contains(&valid_dir)); + assert!(path.starts_with(&valid_dir)); } /// Test the core_dump_file_path function when the environment variable is set to an invalid @@ -412,13 +411,13 @@ mod test { #[test] fn test_crashdump_file_path_invalid() { // Call the function - let path = core_dump_file_path(Some("/tmp/not_existing_dir".to_string())); + let path = core_dump_file_path(Some(PathBuf::from("/tmp/not_existing_dir"))); // Get the temp directory - let temp_dir = std::env::temp_dir().to_string_lossy().to_string(); + let temp_dir = std::env::temp_dir(); // Check if the path is correct - assert!(path.contains(&temp_dir)); + assert!(path.starts_with(&temp_dir)); } /// Test the core_dump_file_path function when the environment is not set @@ -428,7 +427,7 @@ mod test { // Call the function let path = core_dump_file_path(None); - let temp_dir = std::env::temp_dir().to_string_lossy().to_string(); + let temp_dir = std::env::temp_dir(); // Check if the path is correct assert!(path.starts_with(&temp_dir)); @@ -454,8 +453,7 @@ mod test { [0; 27], vec![], 0, - Some("dummy_binary".to_string()), - Some("dummy_filename".to_string()), + Some(PathBuf::from("dummy_binary")), ); let get_writer = || Ok(Box::new(std::io::empty()) as Box); @@ -486,8 +484,7 @@ mod test { [0; 27], vec![], 0x1000, - Some("dummy_binary".to_string()), - Some("dummy_filename".to_string()), + Some(PathBuf::from("dummy_binary")), ); let get_writer = || Ok(Box::new(std::io::empty()) as Box); diff --git a/src/hyperlight_host/src/hypervisor/gdb/mod.rs b/src/hyperlight_host/src/hypervisor/gdb/mod.rs index 0a0685f71..5f82be0c3 100644 --- a/src/hyperlight_host/src/hypervisor/gdb/mod.rs +++ b/src/hyperlight_host/src/hypervisor/gdb/mod.rs @@ -375,14 +375,14 @@ mod tests { use std::os::linux::fs::MetadataExt; use std::sync::{Arc, Mutex}; - use hyperlight_testing::dummy_guest_as_string; + use hyperlight_testing::dummy_guest_as_pathbuf; use super::*; + use crate::log_then_return; use crate::mem::layout::SandboxMemoryLayout; use crate::mem::memory_region::{MemoryRegionFlags, MemoryRegionType}; use crate::sandbox::UninitializedSandbox; use crate::sandbox::uninitialized::GuestBinary; - use crate::{log_then_return, new_error}; #[cfg(target_os = "linux")] const BASE_VIRT: usize = 0x10000000 + SandboxMemoryLayout::BASE_ADDRESS; @@ -390,7 +390,7 @@ mod tests { /// Dummy memory region to test memory access /// This maps a file into memory and uses it as guest memory fn get_mem_access() -> crate::Result { - let filename = dummy_guest_as_string().map_err(|e| new_error!("{}", e))?; + let filename = dummy_guest_as_pathbuf(); let file = std::fs::File::options() .read(true) diff --git a/src/hyperlight_host/src/hypervisor/hyperlight_vm/x86_64.rs b/src/hyperlight_host/src/hypervisor/hyperlight_vm/x86_64.rs index 82206f787..a361c991e 100644 --- a/src/hyperlight_host/src/hypervisor/hyperlight_vm/x86_64.rs +++ b/src/hyperlight_host/src/hypervisor/hyperlight_vm/x86_64.rs @@ -16,8 +16,6 @@ limitations under the License. #[cfg(gdb)] use std::collections::HashMap; -#[cfg(crashdump)] -use std::path::Path; #[cfg(any(kvm, mshv3))] use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicU8; @@ -557,13 +555,6 @@ impl HyperlightVm { regs[25] = sregs.fs.selector as u64; // fs regs[26] = sregs.gs.selector as u64; // gs - // Get the filename from the binary path - let filename = self.rt_cfg.binary_path.clone().and_then(|path| { - Path::new(&path) - .file_name() - .and_then(|name| name.to_os_string().into_string().ok()) - }); - // Use the stored entry point address from the runtime config. // This is the original entry point (load_addr + ELF entry offset) // which GDB needs for AT_ENTRY to compute the PIE load offset. @@ -588,7 +579,6 @@ impl HyperlightVm { xsave.to_vec(), initialise, self.rt_cfg.binary_path.clone(), - filename, ))) } else { Ok(None) diff --git a/src/hyperlight_host/src/hypervisor/mod.rs b/src/hyperlight_host/src/hypervisor/mod.rs index 732f08563..e8f5a3d79 100644 --- a/src/hyperlight_host/src/hypervisor/mod.rs +++ b/src/hyperlight_host/src/hypervisor/mod.rs @@ -460,14 +460,14 @@ impl InterruptHandle for WindowsInterruptHandle { pub(crate) mod tests { use std::sync::{Arc, Mutex}; - use hyperlight_testing::dummy_guest_as_string; + use hyperlight_testing::dummy_guest_as_pathbuf; use crate::sandbox::uninitialized::GuestBinary; #[cfg(any(crashdump, gdb))] use crate::sandbox::uninitialized::SandboxRuntimeConfig; use crate::sandbox::uninitialized_evolve::set_up_hypervisor_partition; use crate::sandbox::{SandboxConfiguration, UninitializedSandbox}; - use crate::{Result, is_hypervisor_present, new_error}; + use crate::{Result, is_hypervisor_present}; #[cfg_attr(feature = "hw-interrupts", ignore)] #[test] @@ -479,7 +479,7 @@ pub(crate) mod tests { use crate::mem::ptr::RawPtr; use crate::sandbox::host_funcs::FunctionRegistry; - let filename = dummy_guest_as_string().map_err(|e| new_error!("{}", e))?; + let filename = dummy_guest_as_pathbuf(); let config: SandboxConfiguration = Default::default(); #[cfg(any(crashdump, gdb))] diff --git a/src/hyperlight_host/src/mem/exe.rs b/src/hyperlight_host/src/mem/exe.rs index 97874ae6e..9ee316642 100644 --- a/src/hyperlight_host/src/mem/exe.rs +++ b/src/hyperlight_host/src/mem/exe.rs @@ -16,6 +16,7 @@ limitations under the License. use std::fs::File; use std::io::Read; +use std::path::Path; #[cfg(feature = "mem_profile")] use std::sync::Arc; use std::vec::Vec; @@ -74,7 +75,7 @@ impl LoadInfo { } impl ExeInfo { - pub fn from_file(path: &str) -> Result { + pub fn from_file(path: &Path) -> Result { let mut file = File::open(path)?; let mut contents = Vec::new(); file.read_to_end(&mut contents)?; @@ -121,13 +122,13 @@ impl ExeInfo { #[cfg(test)] mod tests { - use hyperlight_testing::{dummy_guest_as_string, simple_guest_as_string}; + use hyperlight_testing::{dummy_guest_as_pathbuf, simple_guest_as_pathbuf}; use super::ExeInfo; /// Read the simpleguest binary and patch the version note descriptor to `"0.0.0"`. fn simpleguest_with_patched_version() -> Vec { - let path = simple_guest_as_string().expect("failed to locate simpleguest"); + let path = simple_guest_as_pathbuf(); let mut bytes = std::fs::read(path).expect("failed to read simpleguest"); let elf = goblin::elf::Elf::parse(&bytes).expect("failed to parse ELF"); @@ -160,7 +161,7 @@ mod tests { #[test] fn exe_info_exposes_guest_bin_version() { - let path = simple_guest_as_string().expect("failed to locate simpleguest"); + let path = simple_guest_as_pathbuf(); let info = ExeInfo::from_file(&path).expect("failed to load ELF"); let version = info @@ -171,7 +172,7 @@ mod tests { #[test] fn dummyguest_has_no_version_section() { - let path = dummy_guest_as_string().expect("failed to locate dummyguest"); + let path = dummy_guest_as_pathbuf(); let info = ExeInfo::from_file(&path).expect("failed to load ELF"); assert!( @@ -184,7 +185,7 @@ mod tests { /// should be accepted (no version check is performed). #[test] fn from_env_accepts_guest_without_version_note() { - let path = dummy_guest_as_string().expect("failed to locate dummyguest"); + let path = dummy_guest_as_pathbuf(); let result = crate::sandbox::snapshot::Snapshot::from_env( crate::GuestBinary::FilePath(path), @@ -212,7 +213,7 @@ mod tests { /// that it succeeds when the embedded version matches the host version. #[test] fn from_env_accepts_matching_version() { - let path = simple_guest_as_string().expect("failed to locate simpleguest"); + let path = simple_guest_as_pathbuf(); let result = crate::sandbox::snapshot::Snapshot::from_env( crate::GuestBinary::FilePath(path), diff --git a/src/hyperlight_host/src/mem/mgr.rs b/src/hyperlight_host/src/mem/mgr.rs index 1804d1c9f..77cb29112 100644 --- a/src/hyperlight_host/src/mem/mgr.rs +++ b/src/hyperlight_host/src/mem/mgr.rs @@ -751,7 +751,7 @@ impl SandboxMemoryManager { #[cfg(target_arch = "x86_64")] mod tests { use hyperlight_testing::sandbox_sizes::{LARGE_HEAP_SIZE, MEDIUM_HEAP_SIZE, SMALL_HEAP_SIZE}; - use hyperlight_testing::simple_guest_as_string; + use hyperlight_testing::simple_guest_as_pathbuf; use crate::GuestBinary; use crate::sandbox::SandboxConfiguration; @@ -760,7 +760,7 @@ mod tests { /// Build a Snapshot for the given configuration and verify the /// NULL page is not mapped in its page tables. fn verify_page_tables(name: &str, config: SandboxConfiguration) { - let path = simple_guest_as_string().expect("failed to get simple guest path"); + let path = simple_guest_as_pathbuf(); let snapshot = Snapshot::from_env(GuestBinary::FilePath(path), config) .unwrap_or_else(|e| panic!("{}: failed to create snapshot: {}", name, e)); diff --git a/src/hyperlight_host/src/metrics/mod.rs b/src/hyperlight_host/src/metrics/mod.rs index 8a2d93107..c6d11b3c5 100644 --- a/src/hyperlight_host/src/metrics/mod.rs +++ b/src/hyperlight_host/src/metrics/mod.rs @@ -94,7 +94,7 @@ mod tests { use std::thread; use std::time::Duration; - use hyperlight_testing::simple_guest_as_string; + use hyperlight_testing::simple_guest_as_pathbuf; use metrics::{Key, with_local_recorder}; use metrics_util::CompositeKey; @@ -106,11 +106,9 @@ mod tests { let recorder = metrics_util::debugging::DebuggingRecorder::new(); let snapshotter = recorder.snapshotter(); let snapshot = with_local_recorder(&recorder, || { - let uninit = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().unwrap()), - None, - ) - .unwrap(); + let uninit = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap(); let mut multi = uninit.evolve().unwrap(); let interrupt_handle = multi.interrupt_handle(); diff --git a/src/hyperlight_host/src/sandbox/initialized_multi_use.rs b/src/hyperlight_host/src/sandbox/initialized_multi_use.rs index 6f9e87e17..d2033f780 100644 --- a/src/hyperlight_host/src/sandbox/initialized_multi_use.rs +++ b/src/hyperlight_host/src/sandbox/initialized_multi_use.rs @@ -15,6 +15,8 @@ limitations under the License. */ use std::path::Path; +#[cfg(crashdump)] +use std::path::PathBuf; use std::sync::{Arc, Mutex}; use flatbuffers::FlatBufferBuilder; @@ -1012,7 +1014,7 @@ impl MultiUseSandbox { /// `unsafe { std::env::set_var(...) }`. #[cfg(crashdump)] #[instrument(err(Debug), skip_all, parent = Span::current())] - pub fn generate_crashdump_to_dir(&mut self, dir: impl Into) -> Result<()> { + pub fn generate_crashdump_to_dir(&mut self, dir: impl Into) -> Result<()> { crate::hypervisor::crashdump::generate_crashdump( &self.vm, &mut self.mem_mgr, @@ -1129,7 +1131,7 @@ mod tests { use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode; use hyperlight_testing::sandbox_sizes::{LARGE_HEAP_SIZE, MEDIUM_HEAP_SIZE, SMALL_HEAP_SIZE}; - use hyperlight_testing::simple_guest_as_string; + use hyperlight_testing::simple_guest_as_pathbuf; use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags, MemoryRegionType}; use crate::mem::shared_mem::{ExclusiveSharedMemory, GuestSharedMemory, SharedMemory as _}; @@ -1139,7 +1141,7 @@ mod tests { #[test] fn poison() { let mut sbox: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve() } @@ -1227,7 +1229,7 @@ mod tests { /// Make sure input/output buffers are properly reset after guest call (with host call) #[test] fn host_func_error() { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let mut sandbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); sandbox .register("HostError", || -> Result<()> { @@ -1253,7 +1255,7 @@ mod tests { #[test] fn call_host_func_expect_error() { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let sandbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); let mut sandbox = sandbox.evolve().unwrap(); sandbox @@ -1267,7 +1269,7 @@ mod tests { let mut cfg = SandboxConfiguration::default(); cfg.set_input_data_size(4096); cfg.set_output_data_size(4096); - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let mut sandbox = UninitializedSandbox::new(GuestBinary::FilePath(path), Some(cfg)).unwrap(); sandbox.register("HostAdd", |a: i32, b: i32| a + b).unwrap(); @@ -1288,7 +1290,7 @@ mod tests { #[test] fn test_call_guest_function_by_name() { let mut sbox: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve() } @@ -1327,7 +1329,7 @@ mod tests { cfg.set_scratch_size(min_scratch + 0x10000 + 0x10000); let mut sbox1: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), Some(cfg)).unwrap(); u_sbox.evolve() } @@ -1338,7 +1340,7 @@ mod tests { } let mut sbox2: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), Some(cfg)).unwrap(); u_sbox.evolve() } @@ -1359,7 +1361,7 @@ mod tests { #[test] fn snapshot_evolve_restore_handles_state_correctly() { let mut sbox: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve() } @@ -1379,11 +1381,9 @@ mod tests { #[test] fn test_trigger_exception_on_guest() { - let usbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap(); + let usbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap(); let mut multi_use_sandbox: MultiUseSandbox = usbox.evolve().unwrap(); @@ -1419,7 +1419,7 @@ mod tests { barrier.wait(); for _ in 0..SANDBOXES_PER_THREAD { - let guest_path = simple_guest_as_string().expect("Guest Binary Missing"); + let guest_path = simple_guest_as_pathbuf(); let uninit = UninitializedSandbox::new(GuestBinary::FilePath(guest_path), None).unwrap(); @@ -1442,13 +1442,11 @@ mod tests { #[test] fn test_mmap() { - let mut sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap() - .evolve() - .unwrap(); + let mut sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap() + .evolve() + .unwrap(); let expected = b"hello world"; let map_mem = page_aligned_memory(expected); @@ -1477,13 +1475,11 @@ mod tests { // Makes sure MemoryRegionFlags::READ | MemoryRegionFlags::EXECUTE executable but not writable #[test] fn test_mmap_write_exec() { - let mut sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap() - .evolve() - .unwrap(); + let mut sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap() + .evolve() + .unwrap(); #[cfg(target_arch = "x86_64")] let expected = &[0x90, 0x90, 0x90, 0xC3]; // NOOP slide to RET @@ -1560,7 +1556,7 @@ mod tests { #[test] fn snapshot_restore_handles_remapping_correctly() { let mut sbox: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -1628,7 +1624,7 @@ mod tests { #[test] fn snapshot_restore_across_sandboxes_preserves_mapped_region_contents() { let mut source: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -1653,7 +1649,7 @@ mod tests { let snapshot = source.snapshot().unwrap(); let mut target: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -1680,13 +1676,13 @@ mod tests { #[test] fn snapshot_restore_across_sandboxes() { let mut sandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; let mut sandbox2 = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -1702,7 +1698,7 @@ mod tests { #[test] fn snapshot_restore_rejects_incompatible_layout() { let mut sandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let mut cfg = SandboxConfiguration::default(); cfg.set_heap_size(0x10_000); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), Some(cfg)).unwrap(); @@ -1710,7 +1706,7 @@ mod tests { }; let mut sandbox2 = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let mut cfg = SandboxConfiguration::default(); cfg.set_heap_size(0x20_000); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), Some(cfg)).unwrap(); @@ -1726,7 +1722,7 @@ mod tests { /// rejected `restore` leaves the target usable. #[test] fn snapshot_restore_failure_leaves_target_usable() { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let mut cfg_a = SandboxConfiguration::default(); cfg_a.set_heap_size(0x10_000); let mut source = UninitializedSandbox::new(GuestBinary::FilePath(path), Some(cfg_a)) @@ -1734,7 +1730,7 @@ mod tests { .evolve() .unwrap(); - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let mut cfg_b = SandboxConfiguration::default(); cfg_b.set_heap_size(0x20_000); let mut target = UninitializedSandbox::new(GuestBinary::FilePath(path), Some(cfg_b)) @@ -1763,7 +1759,7 @@ mod tests { #[test] fn snapshot_restore_across_sandboxes_target_has_mapped_regions() { let mut source: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -1771,7 +1767,7 @@ mod tests { let snapshot = source.snapshot().unwrap(); let mut target: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -1792,7 +1788,7 @@ mod tests { #[test] fn snapshot_restore_across_sandboxes_both_have_different_mapped_regions() { let mut source: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -1814,7 +1810,7 @@ mod tests { let snapshot = source.snapshot().unwrap(); let mut target: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -1846,7 +1842,7 @@ mod tests { #[test] fn snapshot_restore_across_sandboxes_repeated() { let mut source: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -1854,7 +1850,7 @@ mod tests { let snapshot = source.snapshot().unwrap(); let mut target: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -1874,7 +1870,7 @@ mod tests { #[test] fn snapshot_restore_resets_debug_registers() { let mut sandbox: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -1910,7 +1906,7 @@ mod tests { #[test] fn stale_abort_buffer_does_not_leak_across_calls() { let mut sbox: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -1946,7 +1942,7 @@ mod tests { cfg.set_heap_size(heap_size); cfg.set_scratch_size(0x100000); - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), Some(cfg)) .unwrap_or_else(|e| panic!("Failed to create {} sandbox: {}", name, e)) .evolve() @@ -1959,7 +1955,7 @@ mod tests { /// Helper: create a MultiUseSandbox from the simple guest with default config. #[cfg(feature = "trace_guest")] fn sandbox_for_gva_tests() -> MultiUseSandbox { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); UninitializedSandbox::new(GuestBinary::FilePath(path), None) .unwrap() .evolve() @@ -2077,13 +2073,11 @@ mod tests { let (path, expected_bytes) = create_test_file("hyperlight_test_map_file_cow_basic.bin", expected); - let mut sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap() - .evolve() - .unwrap(); + let mut sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap() + .evolve() + .unwrap(); let guest_base: u64 = 0x1_0000_0000; let mapped_size = sbox.map_file_cow(&path, guest_base).unwrap(); @@ -2117,13 +2111,11 @@ mod tests { let content = &[0xBB; 4096]; let (path, _) = create_test_file("hyperlight_test_map_file_cow_readonly.bin", content); - let mut sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap() - .evolve() - .unwrap(); + let mut sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap() + .evolve() + .unwrap(); let guest_base: u64 = 0x1_0000_0000; sbox.map_file_cow(&path, guest_base).unwrap(); @@ -2152,7 +2144,7 @@ mod tests { let (path, _) = create_test_file("hyperlight_test_map_file_cow_poison.bin", &[0xCC; 4096]); let mut sbox: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve() } @@ -2188,21 +2180,17 @@ mod tests { let guest_base: u64 = 0x1_0000_0000; - let mut sbox1 = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap() - .evolve() - .unwrap(); + let mut sbox1 = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap() + .evolve() + .unwrap(); - let mut sbox2 = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap() - .evolve() - .unwrap(); + let mut sbox2 = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap() + .evolve() + .unwrap(); // Map the same file into both sandboxes sbox1.map_file_cow(&path, guest_base).unwrap(); @@ -2257,7 +2245,7 @@ mod tests { barrier.wait(); let mut sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), + GuestBinary::FilePath(simple_guest_as_pathbuf()), None, ) .unwrap() @@ -2293,13 +2281,11 @@ mod tests { let (path, _) = create_test_file("hyperlight_test_map_file_cow_cleanup.bin", &[0xDD; 4096]); { - let mut sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap() - .evolve() - .unwrap(); + let mut sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap() + .evolve() + .unwrap(); sbox.map_file_cow(&path, 0x1_0000_0000).unwrap(); // sandbox dropped here @@ -2318,13 +2304,11 @@ mod tests { let (path, expected_bytes) = create_test_file("hyperlight_test_map_file_cow_snapshot_remap.bin", expected); - let mut sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap() - .evolve() - .unwrap(); + let mut sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap() + .evolve() + .unwrap(); let guest_base: u64 = 0x1_0000_0000; @@ -2384,13 +2368,11 @@ mod tests { let (path, expected_bytes) = create_test_file("hyperlight_test_map_file_cow_snap_restore.bin", expected); - let mut sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap() - .evolve() - .unwrap(); + let mut sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap() + .evolve() + .unwrap(); let guest_base: u64 = 0x1_0000_0000; sbox.map_file_cow(&path, guest_base).unwrap(); @@ -2436,11 +2418,9 @@ mod tests { let guest_base: u64 = 0x1_0000_0000; - let mut u_sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap(); + let mut u_sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap(); // Map the file before evolving — this defers the VM-side work. let mapped_size = u_sbox.map_file_cow(&path, guest_base).unwrap(); @@ -2482,11 +2462,9 @@ mod tests { let guest_base: u64 = 0x1_0000_0000; { - let mut u_sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap(); + let mut u_sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap(); u_sbox.map_file_cow(&path, guest_base).unwrap(); // u_sbox dropped here without evolving — PreparedFileMapping::drop @@ -2509,11 +2487,9 @@ mod tests { let (path, _) = create_test_file("hyperlight_test_map_file_cow_unaligned.bin", &[0xBB; 4096]); - let mut u_sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap(); + let mut u_sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap(); // Use an intentionally unaligned address (page_size + 1). let unaligned_base: u64 = (page_size::get() + 1) as u64; @@ -2534,11 +2510,9 @@ mod tests { let _ = std::fs::remove_file(&path); std::fs::File::create(&path).unwrap(); // create empty file - let mut u_sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap(); + let mut u_sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap(); let guest_base: u64 = 0x1_0000_0000; let result = u_sbox.map_file_cow(&path, guest_base); @@ -2557,11 +2531,9 @@ mod tests { let guest_base: u64 = 0x1_0000_0000; - let mut u_sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap(); + let mut u_sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap(); // First mapping should succeed. u_sbox.map_file_cow(&path1, guest_base).unwrap(); @@ -2586,11 +2558,9 @@ mod tests { &[0xCC; 4096], ); - let mut u_sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap(); + let mut u_sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap(); // Use BASE_ADDRESS itself — smack in the middle of shared memory. let base_addr = crate::mem::layout::SandboxMemoryLayout::BASE_ADDRESS as u64; @@ -2607,7 +2577,7 @@ mod tests { #[test] fn map_region_rejects_overlapping_regions() { let mut sbox: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -2632,7 +2602,7 @@ mod tests { #[test] fn map_region_rejects_partial_overlap() { let mut sbox: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -2658,7 +2628,7 @@ mod tests { #[test] fn map_region_allows_adjacent_non_overlapping() { let mut sbox: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -2680,7 +2650,7 @@ mod tests { #[test] fn map_region_rejects_overlap_with_snapshot() { let mut sbox: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -2702,7 +2672,7 @@ mod tests { #[test] fn map_region_rejects_overlap_with_scratch() { let mut sbox: MultiUseSandbox = { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let u_sbox = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u_sbox.evolve().unwrap() }; @@ -2724,7 +2694,7 @@ mod tests { mod from_snapshot { use std::sync::Arc; - use hyperlight_testing::simple_guest_as_string; + use hyperlight_testing::simple_guest_as_pathbuf; use crate::func::Registerable; use crate::sandbox::SandboxConfiguration; @@ -2734,7 +2704,7 @@ mod tests { }; fn make_sandbox() -> MultiUseSandbox { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); UninitializedSandbox::new(GuestBinary::FilePath(path), None) .unwrap() .evolve() @@ -2743,7 +2713,7 @@ mod tests { /// Sandbox with an extra `Add(i32, i32) -> i32` host function. fn make_sandbox_with_add() -> MultiUseSandbox { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let mut u = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u.register_host_function("Add", |a: i32, b: i32| Ok(a + b)) .unwrap(); @@ -2771,7 +2741,7 @@ mod tests { #[test] fn round_trip_pre_init_snapshot() { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let snap = Snapshot::from_env(GuestBinary::FilePath(path), SandboxConfiguration::default()) .unwrap(); @@ -2866,7 +2836,7 @@ mod tests { fn restore_rejects_signature_mismatch() { let mut sbox_with_add = make_sandbox_with_add(); let snap = sbox_with_add.snapshot().unwrap(); - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let mut u = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u.register_host_function("Add", |a: String, b: String| Ok(format!("{a}{b}"))) .unwrap(); @@ -2893,7 +2863,7 @@ mod tests { source.call::("AddToStatic", 17i32).unwrap(); let snap = source.snapshot().unwrap(); - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let mut u = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u.register_host_function("Add", |a: i32, b: i32| Ok(a + b)) .unwrap(); @@ -2967,7 +2937,7 @@ mod tests { /// original sandbox's closure) is the one invoked at runtime. #[test] fn supplied_host_function_is_callable() { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let mut u = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u.register_host_function("Echo42", || Ok(1i64)).unwrap(); let mut sbox = u.evolve().unwrap(); @@ -2990,7 +2960,7 @@ mod tests { /// `HostFunctions` set is accepted. #[test] fn pre_init_snapshot_accepts_arbitrary_host_functions() { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let snap = Snapshot::from_env(GuestBinary::FilePath(path), SandboxConfiguration::default()) .unwrap(); diff --git a/src/hyperlight_host/src/sandbox/mod.rs b/src/hyperlight_host/src/sandbox/mod.rs index 066903657..822b1e388 100644 --- a/src/hyperlight_host/src/sandbox/mod.rs +++ b/src/hyperlight_host/src/sandbox/mod.rs @@ -58,7 +58,7 @@ mod tests { use std::thread; use crossbeam_queue::ArrayQueue; - use hyperlight_testing::simple_guest_as_string; + use hyperlight_testing::simple_guest_as_pathbuf; use crate::sandbox::uninitialized::GuestBinary; use crate::{MultiUseSandbox, UninitializedSandbox, new_error}; @@ -69,7 +69,7 @@ mod tests { let sandbox_queue = Arc::new(ArrayQueue::::new(10)); for i in 0..10 { - let simple_guest_path = simple_guest_as_string().expect("Guest Binary Missing"); + let simple_guest_path = simple_guest_as_pathbuf(); let unintializedsandbox = UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_path), None) .unwrap_or_else(|_| panic!("Failed to create UninitializedSandbox {}", i)); diff --git a/src/hyperlight_host/src/sandbox/outb.rs b/src/hyperlight_host/src/sandbox/outb.rs index 053176b41..4b00d52b4 100644 --- a/src/hyperlight_host/src/sandbox/outb.rs +++ b/src/hyperlight_host/src/sandbox/outb.rs @@ -249,7 +249,7 @@ pub(crate) fn handle_outb( mod tests { use hyperlight_common::flatbuffer_wrappers::guest_log_level::LogLevel; use hyperlight_testing::logger::{LOGGER, Logger}; - use hyperlight_testing::simple_guest_as_string; + use hyperlight_testing::simple_guest_as_pathbuf; use tracing_core::callsite::rebuild_interest_cache; use super::outb_log; @@ -283,7 +283,7 @@ mod tests { let sandbox_cfg = SandboxConfiguration::default(); let new_mgr = || { - let bin = GuestBinary::FilePath(simple_guest_as_string().unwrap()); + let bin = GuestBinary::FilePath(simple_guest_as_pathbuf()); let snapshot = crate::sandbox::snapshot::Snapshot::from_env(bin, sandbox_cfg).unwrap(); let mgr = SandboxMemoryManager::from_snapshot(&snapshot).unwrap(); let (hmgr, _) = mgr.build().unwrap(); @@ -393,7 +393,7 @@ mod tests { let sandbox_cfg = SandboxConfiguration::default(); tracing::subscriber::with_default(subscriber.clone(), || { let new_mgr = || { - let bin = GuestBinary::FilePath(simple_guest_as_string().unwrap()); + let bin = GuestBinary::FilePath(simple_guest_as_pathbuf()); let snapshot = crate::sandbox::snapshot::Snapshot::from_env(bin, sandbox_cfg).unwrap(); let mgr = SandboxMemoryManager::from_snapshot(&snapshot).unwrap(); diff --git a/src/hyperlight_host/src/sandbox/snapshot/file_tests.rs b/src/hyperlight_host/src/sandbox/snapshot/file_tests.rs index 691f6f920..e3f60ee18 100644 --- a/src/hyperlight_host/src/sandbox/snapshot/file_tests.rs +++ b/src/hyperlight_host/src/sandbox/snapshot/file_tests.rs @@ -20,7 +20,7 @@ limitations under the License. use std::sync::Arc; -use hyperlight_testing::simple_guest_as_string; +use hyperlight_testing::simple_guest_as_pathbuf; use serde_json::Value; use sha2::{Digest as _, Sha256}; @@ -29,7 +29,7 @@ use crate::sandbox::snapshot::{OciDigest, OciReference, OciTag, Snapshot}; use crate::{GuestBinary, HostFunctions, MultiUseSandbox, UninitializedSandbox}; fn create_test_sandbox() -> MultiUseSandbox { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); UninitializedSandbox::new(GuestBinary::FilePath(path), None) .unwrap() .evolve() @@ -104,7 +104,7 @@ fn from_snapshot_already_initialized_in_memory() { #[test] fn from_snapshot_in_memory_pre_init() { let snap = Snapshot::from_env( - GuestBinary::FilePath(simple_guest_as_string().unwrap()), + GuestBinary::FilePath(simple_guest_as_pathbuf()), crate::sandbox::SandboxConfiguration::default(), ) .unwrap(); @@ -210,7 +210,7 @@ fn snapshot_generation_round_trip() { #[test] fn pre_init_snapshot_cannot_be_persisted() { let snap = Snapshot::from_env( - GuestBinary::FilePath(simple_guest_as_string().unwrap()), + GuestBinary::FilePath(simple_guest_as_pathbuf()), crate::sandbox::SandboxConfiguration::default(), ) .unwrap(); @@ -563,7 +563,7 @@ fn call_snapshot_without_sregs_rejected() { /// Build a `MultiUseSandbox` with the default host functions plus a /// custom `Add(i32, i32) -> i32`. fn create_sandbox_with_custom_host_funcs() -> MultiUseSandbox { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let mut u = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u.register_host_function("Add", |a: i32, b: i32| Ok(a + b)) .unwrap(); @@ -660,7 +660,7 @@ fn from_snapshot_accepts_extra_host_functions() { #[test] fn from_snapshot_accepts_zero_arg_host_function() { - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let mut u = UninitializedSandbox::new(GuestBinary::FilePath(path), None).unwrap(); u.register_host_function("Zero", || Ok(7i64)).unwrap(); let mut sbox = u.evolve().unwrap(); @@ -2259,7 +2259,7 @@ fn index_json_too_large_on_write_rejected() { #[test] fn config_blob_too_large_on_write_rejected() { - let guest = simple_guest_as_string().unwrap(); + let guest = simple_guest_as_pathbuf(); let mut u = UninitializedSandbox::new(GuestBinary::FilePath(guest), None).unwrap(); // Each host function adds its name and signature to the config // JSON. Long names reach the 1 MiB cap with a modest count. @@ -2446,13 +2446,11 @@ fn round_trip_preserves_non_default_scratch_size() { let mut cfg = SandboxConfiguration::default(); let custom_scratch: usize = 256 * 1024; cfg.set_scratch_size(custom_scratch); - let mut sbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().unwrap()), - Some(cfg), - ) - .unwrap() - .evolve() - .unwrap(); + let mut sbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), Some(cfg)) + .unwrap() + .evolve() + .unwrap(); let snap = sbox.snapshot().unwrap(); let original = snap.layout().get_scratch_size(); assert_eq!(original, custom_scratch); @@ -2878,9 +2876,7 @@ fn from_snapshot_honors_guest_core_dump_enabled() { MultiUseSandbox::from_snapshot(snapshot, HostFunctions::default(), Some(config)).unwrap(); let dir = tempfile::tempdir().unwrap(); - sbox2 - .generate_crashdump_to_dir(dir.path().to_str().unwrap()) - .unwrap(); + sbox2.generate_crashdump_to_dir(dir.path()).unwrap(); let entries: Vec<_> = std::fs::read_dir(dir.path()) .unwrap() @@ -2909,9 +2905,7 @@ fn from_snapshot_honors_guest_core_dump_disabled() { MultiUseSandbox::from_snapshot(snapshot, HostFunctions::default(), Some(config)).unwrap(); let dir = tempfile::tempdir().unwrap(); - sbox2 - .generate_crashdump_to_dir(dir.path().to_str().unwrap()) - .unwrap(); + sbox2.generate_crashdump_to_dir(dir.path()).unwrap(); let entries: Vec<_> = std::fs::read_dir(dir.path()) .unwrap() @@ -2934,7 +2928,7 @@ fn round_trip_preserves_non_default_init_data_permissions() { use crate::mem::memory_region::MemoryRegionFlags; use crate::sandbox::uninitialized::{GuestBlob, GuestEnvironment}; - let path = simple_guest_as_string().unwrap(); + let path = simple_guest_as_pathbuf(); let data: &[u8] = b"perm-pinned-init-data"; let env = GuestEnvironment { guest_binary: GuestBinary::FilePath(path), diff --git a/src/hyperlight_host/src/sandbox/snapshot/mod.rs b/src/hyperlight_host/src/sandbox/snapshot/mod.rs index 9a638a98e..a64141570 100644 --- a/src/hyperlight_host/src/sandbox/snapshot/mod.rs +++ b/src/hyperlight_host/src/sandbox/snapshot/mod.rs @@ -294,7 +294,7 @@ impl Snapshot { let blob = env.init_data; let exe_info = match bin { - GuestBinary::FilePath(bin_path_str) => ExeInfo::from_file(&bin_path_str)?, + GuestBinary::FilePath(bin_path) => ExeInfo::from_file(&bin_path)?, GuestBinary::Buffer(buffer) => ExeInfo::from_buf(buffer)?, }; diff --git a/src/hyperlight_host/src/sandbox/uninitialized.rs b/src/hyperlight_host/src/sandbox/uninitialized.rs index 015db0acd..59f89cbac 100644 --- a/src/hyperlight_host/src/sandbox/uninitialized.rs +++ b/src/hyperlight_host/src/sandbox/uninitialized.rs @@ -16,7 +16,7 @@ limitations under the License. use std::fmt::Debug; use std::option::Option; -use std::path::Path; +use std::path::PathBuf; use std::sync::{Arc, Mutex}; use tracing::{Span, instrument}; @@ -39,7 +39,7 @@ use crate::{MultiUseSandbox, Result, new_error}; #[derive(Clone, Debug, Default)] pub(crate) struct SandboxRuntimeConfig { #[cfg(crashdump)] - pub(crate) binary_path: Option, + pub(crate) binary_path: Option, #[cfg(gdb)] pub(crate) debug_info: Option, #[cfg(crashdump)] @@ -97,7 +97,7 @@ pub enum GuestBinary<'a> { /// A buffer containing the GuestBinary Buffer(&'a [u8]), /// A path to the GuestBinary - FilePath(String), + FilePath(PathBuf), } impl<'a> GuestBinary<'a> { /// If the guest binary is identified by a file, canonicalise the path @@ -109,13 +109,9 @@ impl<'a> GuestBinary<'a> { /// into an invariant on one of those types. pub fn canonicalize(&mut self) -> Result<()> { if let GuestBinary::FilePath(p) = self { - let canon = Path::new(&p) + *p = p .canonicalize() - .map_err(|e| new_error!("GuestBinary not found: '{}': {}", p, e))? - .into_os_string() - .into_string() - .map_err(|e| new_error!("Error converting OsString to String: {:?}", e))?; - *self = GuestBinary::FilePath(canon) + .map_err(|e| new_error!("GuestBinary not found: '{}': {}", p.display(), e))?; } Ok(()) } @@ -181,7 +177,7 @@ impl UninitializedSandbox { fn from_snapshot( snapshot: Arc, cfg: Option, - #[cfg(crashdump)] binary_path: Option, + #[cfg(crashdump)] binary_path: Option, ) -> Result { #[cfg(feature = "build-metadata")] log_build_details(); @@ -414,15 +410,32 @@ mod tests { use crossbeam_queue::ArrayQueue; use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnValue}; - use hyperlight_testing::simple_guest_as_string; + use hyperlight_testing::simple_guest_as_pathbuf; use crate::sandbox::SandboxConfiguration; use crate::sandbox::uninitialized::{GuestBinary, GuestEnvironment}; use crate::{MultiUseSandbox, Result, UninitializedSandbox, new_error}; + #[cfg(unix)] + #[test] + fn guest_binary_loads_from_non_utf8_path() { + use std::ffi::OsString; + use std::os::unix::ffi::OsStringExt; + + let temp_dir = tempfile::tempdir().unwrap(); + let guest_path = temp_dir + .path() + .join(OsString::from_vec(b"guest-\xff".to_vec())); + fs::copy(simple_guest_as_pathbuf(), &guest_path).unwrap(); + + let sandbox = UninitializedSandbox::new(GuestBinary::FilePath(guest_path), None); + + assert!(sandbox.is_ok()); + } + #[test] fn test_load_extra_blob() { - let binary_path = simple_guest_as_string().unwrap(); + let binary_path = simple_guest_as_pathbuf(); let buffer = [0xde, 0xad, 0xbe, 0xef]; let guest_env = GuestEnvironment::new(GuestBinary::FilePath(binary_path.clone()), Some(&buffer)); @@ -441,14 +454,16 @@ mod tests { fn test_new_sandbox() { // Guest Binary exists at path - let binary_path = simple_guest_as_string().unwrap(); + let binary_path = simple_guest_as_pathbuf(); let sandbox = UninitializedSandbox::new(GuestBinary::FilePath(binary_path.clone()), None); assert!(sandbox.is_ok()); // Guest Binary does not exist at path let mut binary_path_does_not_exist = binary_path.clone(); - binary_path_does_not_exist.push_str(".nonexistent"); + binary_path_does_not_exist + .as_mut_os_string() + .push(".nonexistent"); let uninitialized_sandbox = UninitializedSandbox::new(GuestBinary::FilePath(binary_path_does_not_exist), None); assert!(uninitialized_sandbox.is_err()); @@ -475,14 +490,14 @@ mod tests { // Test with a valid guest binary buffer - let binary_path = simple_guest_as_string().unwrap(); + let binary_path = simple_guest_as_pathbuf(); let sandbox = UninitializedSandbox::new(GuestBinary::Buffer(&fs::read(binary_path).unwrap()), None); assert!(sandbox.is_ok()); // Test with a invalid guest binary buffer - let binary_path = simple_guest_as_string().unwrap(); + let binary_path = simple_guest_as_pathbuf(); let mut bytes = fs::read(binary_path).unwrap(); let _ = bytes.split_off(100); let sandbox = UninitializedSandbox::new(GuestBinary::Buffer(&bytes), None); @@ -492,11 +507,8 @@ mod tests { #[test] fn test_host_functions() { let uninitialized_sandbox = || { - UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .unwrap() + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .unwrap() }; // simple register + call @@ -610,11 +622,9 @@ mod tests { Ok(0) }; - let mut sandbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .expect("Failed to create sandbox"); + let mut sandbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .expect("Failed to create sandbox"); sandbox .register_print(writer) @@ -672,7 +682,7 @@ mod tests { // let writer_func = Arc::new(Mutex::new(writer)); // // let sandbox = UninitializedSandbox::new( - // GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), + // GuestBinary::FilePath(simple_guest_as_pathbuf()), // None, // None, // Some(&writer_func), @@ -699,11 +709,9 @@ mod tests { Ok(0) } - let mut sandbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .expect("Failed to create sandbox"); + let mut sandbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .expect("Failed to create sandbox"); sandbox .register_print(fn_writer) @@ -726,11 +734,9 @@ mod tests { let writer_closure = move |s| test_host_print.write(s); - let mut sandbox = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().expect("Guest Binary Missing")), - None, - ) - .expect("Failed to create sandbox"); + let mut sandbox = + UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), None) + .expect("Failed to create sandbox"); sandbox .register_print(writer_closure) @@ -765,7 +771,7 @@ mod tests { let sandbox_queue = Arc::new(ArrayQueue::::new(10)); for i in 0..10 { - let simple_guest_path = simple_guest_as_string().expect("Guest Binary Missing"); + let simple_guest_path = simple_guest_as_pathbuf(); let unintializedsandbox = { let err_string = format!("failed to create UninitializedSandbox {i}"); let err_str = err_string.as_str(); @@ -893,7 +899,8 @@ mod tests { // UninitializedSandbox::new by calling it once. This ensures the // callsite exists in the global registry regardless of whether // another thread already registered it. - let bad_path = simple_guest_as_string().unwrap() + "does_not_exist"; + let mut bad_path = simple_guest_as_pathbuf(); + bad_path.as_mut_os_string().push("does_not_exist"); let _ = UninitializedSandbox::new(GuestBinary::FilePath(bad_path.clone()), None); // Rebuild the interest cache. Now that the callsite is guaranteed @@ -990,8 +997,10 @@ mod tests { rebuild_interest_cache(); - let mut invalid_binary_path = simple_guest_as_string().unwrap(); - invalid_binary_path.push_str("does_not_exist"); + let mut invalid_binary_path = simple_guest_as_pathbuf(); + invalid_binary_path + .as_mut_os_string() + .push("does_not_exist"); let sbox = UninitializedSandbox::new(GuestBinary::FilePath(invalid_binary_path), None); assert!(sbox.is_err()); @@ -1062,10 +1071,7 @@ mod tests { valid_binary_path.push("sandbox"); valid_binary_path.push("initialized.rs"); - let sbox = UninitializedSandbox::new( - GuestBinary::FilePath(valid_binary_path.into_os_string().into_string().unwrap()), - None, - ); + let sbox = UninitializedSandbox::new(GuestBinary::FilePath(valid_binary_path), None); assert!(sbox.is_err()); // There should be 2 calls this time when we change to the log @@ -1098,7 +1104,7 @@ mod tests { let sbox = { let res = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().unwrap()), + GuestBinary::FilePath(simple_guest_as_pathbuf()), None, ); res.unwrap() @@ -1114,7 +1120,7 @@ mod tests { #[test] fn test_invalid_path() { let invalid_path = "some/path/that/does/not/exist"; - let sbox = UninitializedSandbox::new(GuestBinary::FilePath(invalid_path.to_string()), None); + let sbox = UninitializedSandbox::new(GuestBinary::FilePath(invalid_path.into()), None); println!("{:?}", sbox); #[cfg(target_os = "windows")] assert!( @@ -1130,7 +1136,7 @@ mod tests { fn test_from_snapshot_various_configurations() { use crate::sandbox::snapshot::Snapshot; - let binary_path = simple_guest_as_string().unwrap(); + let binary_path = simple_guest_as_pathbuf(); // Test 1: Create snapshot with default config, create multiple sandboxes from it { diff --git a/src/hyperlight_host/src/sandbox/uninitialized_evolve.rs b/src/hyperlight_host/src/sandbox/uninitialized_evolve.rs index a38d14409..bc932c029 100644 --- a/src/hyperlight_host/src/sandbox/uninitialized_evolve.rs +++ b/src/hyperlight_host/src/sandbox/uninitialized_evolve.rs @@ -183,7 +183,7 @@ pub(crate) fn set_up_hypervisor_partition( #[cfg(test)] mod tests { - use hyperlight_testing::simple_guest_as_string; + use hyperlight_testing::simple_guest_as_pathbuf; use super::evolve_impl_multi_use; use crate::UninitializedSandbox; @@ -191,11 +191,10 @@ mod tests { #[test] fn test_evolve() { - let guest_bin_paths = vec![simple_guest_as_string().unwrap()]; + let guest_bin_paths = vec![simple_guest_as_pathbuf()]; for guest_bin_path in guest_bin_paths { let u_sbox = - UninitializedSandbox::new(GuestBinary::FilePath(guest_bin_path.clone()), None) - .unwrap(); + UninitializedSandbox::new(GuestBinary::FilePath(guest_bin_path), None).unwrap(); evolve_impl_multi_use(u_sbox).unwrap(); } } diff --git a/src/hyperlight_host/tests/common/mod.rs b/src/hyperlight_host/tests/common/mod.rs index d58e60aa6..003ccdc67 100644 --- a/src/hyperlight_host/tests/common/mod.rs +++ b/src/hyperlight_host/tests/common/mod.rs @@ -14,19 +14,21 @@ See the License for the specific language governing permissions and limitations under the License. */ +use std::path::PathBuf; + use hyperlight_host::func::HostFunction; use hyperlight_host::sandbox::SandboxConfiguration; use hyperlight_host::{GuestBinary, MultiUseSandbox, UninitializedSandbox}; -use hyperlight_testing::{c_simple_guest_as_string, simple_guest_as_string}; +use hyperlight_testing::{c_simple_guest_as_pathbuf, simple_guest_as_pathbuf}; /// Returns the path to the Rust simple guest binary. -fn rust_guest_path() -> String { - simple_guest_as_string().unwrap() +fn rust_guest_path() -> PathBuf { + simple_guest_as_pathbuf() } /// Returns the path to the C simple guest binary. -fn c_guest_path() -> String { - c_simple_guest_as_string().unwrap() +fn c_guest_path() -> PathBuf { + c_simple_guest_as_pathbuf() } /// Creates a new Rust guest MultiUseSandbox. diff --git a/src/hyperlight_host/tests/sandbox_host_tests.rs b/src/hyperlight_host/tests/sandbox_host_tests.rs index e0daf969b..b1a1a9918 100644 --- a/src/hyperlight_host/tests/sandbox_host_tests.rs +++ b/src/hyperlight_host/tests/sandbox_host_tests.rs @@ -21,7 +21,7 @@ use hyperlight_host::sandbox::SandboxConfiguration; use hyperlight_host::{ GuestBinary, HyperlightError, MultiUseSandbox, Result, UninitializedSandbox, new_error, }; -use hyperlight_testing::simple_guest_as_string; +use hyperlight_testing::simple_guest_as_pathbuf; pub mod common; // pub to disable dead_code warning use crate::common::{ @@ -215,10 +215,7 @@ fn small_scratch_sandbox() { cfg.set_scratch_size(0x48000); cfg.set_input_data_size(0x24000); cfg.set_output_data_size(0x24000); - let a = UninitializedSandbox::new( - GuestBinary::FilePath(simple_guest_as_string().unwrap()), - Some(cfg), - ); + let a = UninitializedSandbox::new(GuestBinary::FilePath(simple_guest_as_pathbuf()), Some(cfg)); assert!(matches!( a.unwrap_err(), diff --git a/src/hyperlight_host/tests/snapshot_goldens/fixtures.rs b/src/hyperlight_host/tests/snapshot_goldens/fixtures.rs index d33b6bb3d..0b35fb325 100644 --- a/src/hyperlight_host/tests/snapshot_goldens/fixtures.rs +++ b/src/hyperlight_host/tests/snapshot_goldens/fixtures.rs @@ -18,13 +18,14 @@ limitations under the License. //! goldens push contains. Any change here is a snapshot content //! change and requires a goldens regen. +use std::path::PathBuf; use std::sync::Arc; use hyperlight_host::func::Registerable; use hyperlight_host::sandbox::SandboxConfiguration; use hyperlight_host::sandbox::snapshot::Snapshot; use hyperlight_host::{GuestBinary, MultiUseSandbox, UninitializedSandbox}; -use hyperlight_testing::simple_guest_as_string; +use hyperlight_testing::simple_guest_as_pathbuf; /// Heap pattern length used by the golden. Small enough to /// stay cheap, large enough to exercise non-trivial heap state. @@ -47,8 +48,8 @@ fn golden_config() -> SandboxConfiguration { cfg } -fn simpleguest_path() -> String { - simple_guest_as_string().expect("simpleguest_path") +fn simpleguest_path() -> PathBuf { + simple_guest_as_pathbuf() } pub(crate) fn generate() -> Arc { diff --git a/src/hyperlight_host/tests/wit_test.rs b/src/hyperlight_host/tests/wit_test.rs index 1839c9236..df3342568 100644 --- a/src/hyperlight_host/tests/wit_test.rs +++ b/src/hyperlight_host/tests/wit_test.rs @@ -18,7 +18,7 @@ use std::sync::{Arc, Mutex}; use hyperlight_common::resource::BorrowedResourceGuard; use hyperlight_host::{GuestBinary, MultiUseSandbox, UninitializedSandbox}; -use hyperlight_testing::wit_guest_as_string; +use hyperlight_testing::wit_guest_as_pathbuf; extern crate alloc; mod bindings { @@ -285,7 +285,7 @@ impl test::wit::TestImports for Host { } fn sb() -> TestSandbox { - let path = wit_guest_as_string().unwrap(); + let path = wit_guest_as_pathbuf(); let guest_path = GuestBinary::FilePath(path); let uninit = UninitializedSandbox::new(guest_path, None).unwrap(); test::wit::Test::instantiate(uninit, Host {}) diff --git a/src/hyperlight_testing/src/lib.rs b/src/hyperlight_testing/src/lib.rs index aa3af3237..4c7afb971 100644 --- a/src/hyperlight_testing/src/lib.rs +++ b/src/hyperlight_testing/src/lib.rs @@ -65,24 +65,39 @@ pub fn rust_guest_as_pathbuf(guest: &str) -> PathBuf { } /// Get a fully qualified OS-specific path to the simpleguest elf binary +pub fn simple_guest_as_pathbuf() -> PathBuf { + rust_guest_as_pathbuf("simpleguest") +} + +/// Get a fully qualified OS-specific path to the simpleguest elf binary as a string pub fn simple_guest_as_string() -> Result { - let buf = rust_guest_as_pathbuf("simpleguest"); + let buf = simple_guest_as_pathbuf(); buf.to_str() .map(|s| s.to_string()) .ok_or_else(|| anyhow!("couldn't convert simple guest PathBuf to string")) } /// Get a fully-qualified OS-specific path to the witguest elf binary +pub fn wit_guest_as_pathbuf() -> PathBuf { + rust_guest_as_pathbuf("witguest") +} + +/// Get a fully-qualified OS-specific path to the witguest elf binary as a string pub fn wit_guest_as_string() -> Result { - let buf = rust_guest_as_pathbuf("witguest"); + let buf = wit_guest_as_pathbuf(); buf.to_str() .map(|s| s.to_string()) .ok_or_else(|| anyhow!("couldn't convert wit guest PathBuf to string")) } /// Get a fully qualified OS-specific path to the dummyguest elf binary +pub fn dummy_guest_as_pathbuf() -> PathBuf { + rust_guest_as_pathbuf("dummyguest") +} + +/// Get a fully qualified OS-specific path to the dummyguest elf binary as a string pub fn dummy_guest_as_string() -> Result { - let buf = rust_guest_as_pathbuf("dummyguest"); + let buf = dummy_guest_as_pathbuf(); buf.to_str() .map(|s| s.to_string()) .ok_or_else(|| anyhow!("couldn't convert dummy guest PathBuf to string")) @@ -101,8 +116,12 @@ pub fn c_guest_as_pathbuf(guest: &str) -> PathBuf { ) } +pub fn c_simple_guest_as_pathbuf() -> PathBuf { + c_guest_as_pathbuf("simpleguest") +} + pub fn c_simple_guest_as_string() -> Result { - let buf = c_guest_as_pathbuf("simpleguest"); + let buf = c_simple_guest_as_pathbuf(); buf.to_str() .map(|s| s.to_string()) .ok_or_else(|| anyhow!("couldn't convert simple guest PathBuf to string")) @@ -112,7 +131,7 @@ pub fn c_simple_guest_as_string() -> Result { /// in the same directory as the parent executable. This will be used in /// fuzzing scenarios where pre-built binaries will be built and submitted to /// a fuzzing framework. -pub fn simple_guest_for_fuzzing_as_string() -> Result { +pub fn simple_guest_for_fuzzing_as_pathbuf() -> PathBuf { let exe_dir = env::current_exe() .ok() .and_then(|path| path.parent().map(|p| p.to_path_buf())); @@ -121,14 +140,22 @@ pub fn simple_guest_for_fuzzing_as_string() -> Result { let guest_path = exe_dir.join("simpleguest"); if guest_path.exists() { - return Ok(guest_path - .to_str() - .ok_or(anyhow!("Invalid path string"))? - .to_string()); + return guest_path; } } - simple_guest_as_string() + simple_guest_as_pathbuf() +} + +/// Get a fully qualified path to a simple guest binary as a string, preferring a binary +/// in the same directory as the parent executable. +pub fn simple_guest_for_fuzzing_as_string() -> Result { + let guest_path = simple_guest_for_fuzzing_as_pathbuf(); + + Ok(guest_path + .to_str() + .ok_or(anyhow!("Invalid path string"))? + .to_string()) } /// Standard sandbox heap sizes for benchmarking and testing.