diff --git a/Cargo.lock b/Cargo.lock index 75194011..f0b7a636 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -583,6 +583,19 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "elfcore" +version = "1.1.5" +source = "git+https://github.com/dblnz/elfcore.git?branch=split-linux-impl-from-elfcore#4e7fd38b9c393c3b143e0d77d198d111f1afed8d" +dependencies = [ + "libc", + "nix 0.26.4", + "smallvec", + "thiserror 1.0.69", + "tracing", + "zerocopy 0.7.35", +] + [[package]] name = "env_filter" version = "0.1.3" @@ -1055,6 +1068,7 @@ dependencies = [ "crossbeam", "crossbeam-channel", "crossbeam-queue", + "elfcore", "env_logger", "flatbuffers", "gdbstub", @@ -1071,6 +1085,7 @@ dependencies = [ "mshv-bindings 0.3.2", "mshv-ioctls 0.2.1", "mshv-ioctls 0.3.2", + "nix 0.29.0", "once_cell", "opentelemetry", "opentelemetry-otlp", @@ -1653,6 +1668,29 @@ dependencies = [ "vmm-sys-util 0.13.0", ] +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.9.0", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nom" version = "7.1.3" diff --git a/src/hyperlight_host/Cargo.toml b/src/hyperlight_host/Cargo.toml index 8e6b8a46..227d11ce 100644 --- a/src/hyperlight_host/Cargo.toml +++ b/src/hyperlight_host/Cargo.toml @@ -48,6 +48,8 @@ strum = { version = "0.27", features = ["derive"] } tempfile = { version = "3.19", optional = true } serde_yaml = "0.9" anyhow = "1.0" +elfcore = { git = "https://github.com/dblnz/elfcore.git", branch = "split-linux-impl-from-elfcore" } +nix = { version = "0.29.0", features = ["process"] } [target.'cfg(windows)'.dependencies] windows = { version = "0.61", features = [ @@ -118,7 +120,7 @@ cfg_aliases = "0.2.1" built = { version = "0.7.7", features = ["chrono", "git2"] } [features] -default = ["kvm", "mshv2", "seccomp"] +default = ["crashdump", "gdb", "kvm", "mshv2", "seccomp"] seccomp = ["dep:seccompiler"] function_call_metrics = [] executable_heap = [] diff --git a/src/hyperlight_host/src/hypervisor/crashdump.rs b/src/hyperlight_host/src/hypervisor/crashdump.rs index a70dc34c..52cd72c5 100644 --- a/src/hyperlight_host/src/hypervisor/crashdump.rs +++ b/src/hyperlight_host/src/hypervisor/crashdump.rs @@ -1,44 +1,226 @@ -use std::io::Write; +use std::cmp::min; +use elfcore::{ + ArchComponentState, ArchState, CoreDumpBuilder, CoreError, Elf64_Auxv, Pid, ProcessInfoSource, + ReadProcessMemory, ThreadView, VaProtection, VaRegion, +}; use tempfile::NamedTempFile; use super::Hypervisor; +use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags}; use crate::{new_error, Result}; -/// Dump registers + memory regions + raw memory to a tempfile -#[cfg(crashdump)] -pub(crate) fn crashdump_to_tempfile(hv: &dyn Hypervisor) -> Result<()> { - let mut temp_file = NamedTempFile::with_prefix("mem")?; - let hv_details = format!("{:#x?}", hv); +// amd64 notes +pub const NT_X86_XSTATE: u32 = 0x202; - // write hypervisor details such as registers, info about mapped memory regions, etc. - temp_file.write_all(hv_details.as_bytes())?; - temp_file.write_all(b"================ MEMORY DUMP =================\n")?; +#[derive(Debug)] +pub(crate) struct CrashDumpContext<'a> { + regions: &'a [MemoryRegion], + regs: [u64; 27], + xsave: Vec, + entry: u64, + binary: Option, + filename: Option, +} - // write the raw memory dump for each memory region - for region in hv.get_memory_regions() { - if region.host_region.start == 0 || region.host_region.is_empty() { - continue; +impl<'a> CrashDumpContext<'a> { + pub(crate) fn new( + regions: &'a [MemoryRegion], + regs: [u64; 27], + xsave: Vec, + entry: u64, + binary: Option, + filename: Option, + ) -> Self { + Self { + regions, + regs, + xsave, + entry, + binary, + filename, } - // SAFETY: we got this memory region from the hypervisor so should never be invalid - let region_slice = unsafe { - std::slice::from_raw_parts( - region.host_region.start as *const u8, - region.host_region.len(), - ) + } +} + +struct GuestView { + regions: Vec, + threads: Vec, + aux_vector: Vec, +} + +impl GuestView { + fn new(ctx: &CrashDumpContext) -> Self { + let regions = ctx + .regions + .iter() + .filter(|r| !r.host_region.is_empty()) + .map(|r| VaRegion { + begin: r.guest_region.start as u64, + end: r.guest_region.end as u64, + offset: r.host_region.start as u64, + protection: VaProtection { + is_private: false, + read: r.flags.contains(MemoryRegionFlags::READ), + write: r.flags.contains(MemoryRegionFlags::WRITE), + execute: r.flags.contains(MemoryRegionFlags::EXECUTE), + }, + mapped_file_name: None, + }) + .collect(); + let mut filename = ctx.filename.clone().unwrap_or("".to_string()); + filename.push('\0'); + println!("{:X?}", filename); + let mut cmd = ctx.binary.clone().unwrap_or("".to_string()); + cmd.push('\0'); + println!("{:X?}", cmd); + + let thread = ThreadView { + flags: 0, // Kernel flags for the process + tid: Pid::from_raw(1), + uid: 0, // User ID + gid: 0, // Group ID + comm: filename, + ppid: 0, // Parent PID + pgrp: 0, // Process group ID + nice: 0, // Nice value + state: 0, // Process state + utime: 0, // User time + stime: 0, // System time + cutime: 0, // Children User time + cstime: 0, // Children User time + cursig: 0, // Current signal + session: 0, // Session ID of the process + sighold: 0, // Blocked signal + sigpend: 0, // Pending signal + cmd_line: cmd, + + arch_state: Box::new(ArchState { + gpr_state: ctx.regs.to_vec(), + components: vec![ArchComponentState { + name: "XSAVE", + note_type: NT_X86_XSTATE, + note_name: b"LINUX", + data: ctx.xsave.clone(), + }], + }), }; - temp_file.write_all(region_slice)?; + + // Create the auxv vector + // The first entry is AT_ENTRY, which is the entry point of the program + // The entry point is the address where the program starts executing + // This helps the debugger to know that the entry is changed by an offset + // so the symbols can be loaded correctly. + // The second entry is AT_NULL, which marks the end of the vector + let auxv = vec![ + Elf64_Auxv { + a_type: 9, // AT_ENTRY + a_val: ctx.entry, + }, + Elf64_Auxv { + a_type: 0, // AT_NULL + a_val: 0, + }, + ]; + + Self { + regions, + threads: vec![thread], + aux_vector: auxv, + } + } +} + +impl ProcessInfoSource for GuestView { + fn get_pid(&self) -> Pid { + Pid::from_raw(1) + } + fn get_threads(&self) -> &[elfcore::ThreadView] { + &self.threads } - temp_file.flush()?; + fn get_page_size(&self) -> usize { + 0x1000 + } + fn get_aux_vector(&self) -> Option<&[elfcore::Elf64_Auxv]> { + Some(&self.aux_vector) + } + fn get_va_regions(&self) -> &[elfcore::VaRegion] { + &self.regions + } + fn get_mapped_files(&self) -> Option<&[elfcore::MappedFile]> { + None + } +} + +struct GuestMemReader { + regions: Vec, +} + +impl GuestMemReader { + fn new(ctx: &CrashDumpContext) -> Self { + Self { + regions: ctx.regions.to_vec(), + } + } +} + +impl ReadProcessMemory for GuestMemReader { + fn read_process_memory( + &mut self, + base: usize, + buf: &mut [u8], + ) -> std::result::Result { + let mut size = 0; + + for r in self.regions.iter() { + if base >= r.guest_region.start && base < r.guest_region.end { + let offset = base - r.guest_region.start; + + let region_slice = unsafe { + std::slice::from_raw_parts( + r.host_region.start as *const u8, + r.host_region.len(), + ) + }; + + let start = offset; + let end = offset + min(buf.len(), region_slice.len()); + buf.copy_from_slice(®ion_slice[start..end]); + size = end - start; + break; + } + } + + std::result::Result::Ok(size) + } +} + +/// Create core dump file from the hypervisor information +pub(crate) fn crashdump_to_tempfile(hv: &dyn Hypervisor) -> Result<()> { + let temp_file = NamedTempFile::with_prefix("hl")?; + + let ctx = hv + .get_crashdump_context() + .map_err(|e| new_error!("Could not create crashdump context: {:?}", e))?; + + let gv = GuestView::new(&ctx); + let memory_reader = GuestMemReader::new(&ctx); + + let cdb = CoreDumpBuilder::from_source( + Box::new(gv) as Box, + Box::new(memory_reader) as Box, + ); + + cdb.write(&temp_file) + .map_err(|e| new_error!("Write Error: {:?}", e))?; - // persist the tempfile to disk let persist_path = temp_file.path().with_extension("dmp"); temp_file .persist(&persist_path) .map_err(|e| new_error!("Failed to persist crashdump file: {:?}", e))?; - println!("Memory dumped to file: {:?}", persist_path); - log::error!("Memory dumped to file: {:?}", persist_path); + println!("Core dump file: {:?}", persist_path); + log::error!("Core dump file: {:?}", persist_path); Ok(()) } diff --git a/src/hyperlight_host/src/hypervisor/gdb/kvm_debug.rs b/src/hyperlight_host/src/hypervisor/gdb/kvm_debug.rs index 6e8f9d36..50bc183d 100644 --- a/src/hyperlight_host/src/hypervisor/gdb/kvm_debug.rs +++ b/src/hyperlight_host/src/hypervisor/gdb/kvm_debug.rs @@ -86,7 +86,7 @@ impl KvmDebug { self.dbg_cfg.arch.debugreg = [0; 8]; for (k, addr) in addrs.iter().enumerate() { self.dbg_cfg.arch.debugreg[k] = *addr; - self.dbg_cfg.arch.debugreg[7] |= 1 << (k * 2); + self.dbg_cfg.arch.debugreg[7] |= 0x03 << (k * 2); } if !addrs.is_empty() { diff --git a/src/hyperlight_host/src/hypervisor/hyperv_linux.rs b/src/hyperlight_host/src/hypervisor/hyperv_linux.rs index 6e1e8ec6..4bae6e9e 100644 --- a/src/hyperlight_host/src/hypervisor/hyperv_linux.rs +++ b/src/hyperlight_host/src/hypervisor/hyperv_linux.rs @@ -25,6 +25,8 @@ extern crate mshv_bindings3 as mshv_bindings; extern crate mshv_ioctls3 as mshv_ioctls; use std::fmt::{Debug, Formatter}; +#[cfg(crashdump)] +use std::path::Path; use log::{error, LevelFilter}; #[cfg(mshv2)] @@ -49,6 +51,8 @@ use mshv_bindings::{ use mshv_ioctls::{Mshv, VcpuFd, VmFd}; use tracing::{instrument, Span}; +#[cfg(crashdump)] +use super::crashdump; use super::fpu::{FP_CONTROL_WORD_DEFAULT, FP_TAG_WORD_DEFAULT, MXCSR_DEFAULT}; #[cfg(gdb)] use super::gdb::{DebugCommChannel, DebugMsg, DebugResponse, GuestDebug, MshvDebug}; @@ -63,6 +67,7 @@ use crate::hypervisor::hypervisor_handler::HypervisorHandler; use crate::hypervisor::HyperlightExit; use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags}; use crate::mem::ptr::{GuestPtr, RawPtr}; +use crate::sandbox::uninitialized::SandboxMetadata; #[cfg(gdb)] use crate::HyperlightError; use crate::{log_then_return, new_error, Result}; @@ -299,6 +304,8 @@ pub(super) struct HypervLinuxDriver { debug: Option, #[cfg(gdb)] gdb_conn: Option>, + #[allow(dead_code)] + metadata: SandboxMetadata, } impl HypervLinuxDriver { @@ -317,6 +324,7 @@ impl HypervLinuxDriver { rsp_ptr: GuestPtr, pml4_ptr: GuestPtr, #[cfg(gdb)] gdb_conn: Option>, + metadata: SandboxMetadata, ) -> Result { let mshv = Mshv::new()?; let pr = Default::default(); @@ -396,6 +404,7 @@ impl HypervLinuxDriver { debug, #[cfg(gdb)] gdb_conn, + metadata, }) } @@ -663,8 +672,56 @@ impl Hypervisor for HypervLinuxDriver { } #[cfg(crashdump)] - fn get_memory_regions(&self) -> &[MemoryRegion] { - &self.mem_regions + fn get_crashdump_context(&self) -> Result { + let mut regs = [0; 27]; + + let vcpu_regs = self.vcpu_fd.get_regs()?; + let sregs = self.vcpu_fd.get_sregs()?; + let xsave = self.vcpu_fd.get_xsave()?; + + regs[0] = vcpu_regs.r15; // r15 + regs[1] = vcpu_regs.r14; // r14 + regs[2] = vcpu_regs.r13; // r13 + regs[3] = vcpu_regs.r12; // r12 + regs[4] = vcpu_regs.rbp; // rbp + regs[5] = vcpu_regs.rbx; // rbx + regs[6] = vcpu_regs.r11; // r11 + regs[7] = vcpu_regs.r10; // r10 + regs[8] = vcpu_regs.r9; // r9 + regs[9] = vcpu_regs.r8; // r8 + regs[10] = vcpu_regs.rax; // rax + regs[11] = vcpu_regs.rcx; // rcx + regs[12] = vcpu_regs.rdx; // rdx + regs[13] = vcpu_regs.rsi; // rsi + regs[14] = vcpu_regs.rdi; // rdi + regs[15] = 0; // orig rax + regs[16] = vcpu_regs.rip; // rip + regs[17] = sregs.cs.selector as u64; // cs + regs[18] = vcpu_regs.rflags; // eflags + regs[19] = vcpu_regs.rsp; // rsp + regs[20] = sregs.ss.selector as u64; // ss + regs[21] = sregs.fs.base; // fs_base + regs[22] = sregs.gs.base; // gs_base + regs[23] = sregs.ds.selector as u64; // ds + regs[24] = sregs.es.selector as u64; // es + regs[25] = sregs.fs.selector as u64; // fs + regs[26] = sregs.gs.selector as u64; // gs + + let filename = self.metadata.binary_path.clone().map(|path| { + Path::new(&path) + .file_name() + .map(|name| name.to_os_string().into_string().unwrap()) + .unwrap() + }); + + Ok(crashdump::CrashDumpContext::new( + &self.mem_regions, + regs, + xsave.buffer.to_vec(), + self.entrypoint, + self.metadata.binary_path.clone(), + filename, + )) } #[cfg(gdb)] @@ -784,6 +841,7 @@ mod tests { pml4_ptr, #[cfg(gdb)] None, + SandboxMetadata { binary_path: None }, ) .unwrap(); } diff --git a/src/hyperlight_host/src/hypervisor/hyperv_windows.rs b/src/hyperlight_host/src/hypervisor/hyperv_windows.rs index 47fbaaa9..1c5cae51 100644 --- a/src/hyperlight_host/src/hypervisor/hyperv_windows.rs +++ b/src/hyperlight_host/src/hypervisor/hyperv_windows.rs @@ -487,8 +487,8 @@ impl Hypervisor for HypervWindowsDriver { } #[cfg(crashdump)] - fn get_memory_regions(&self) -> &[MemoryRegion] { - &self.mem_regions + fn get_crashdump_context(&self) -> Result { + unimplemented!("Not implemented for HyperV"); } } diff --git a/src/hyperlight_host/src/hypervisor/hypervisor_handler.rs b/src/hyperlight_host/src/hypervisor/hypervisor_handler.rs index 7b30d7c6..0a4262c5 100644 --- a/src/hyperlight_host/src/hypervisor/hypervisor_handler.rs +++ b/src/hyperlight_host/src/hypervisor/hypervisor_handler.rs @@ -55,6 +55,7 @@ use crate::sandbox::config::DebugInfo; use crate::sandbox::hypervisor::{get_available_hypervisor, HypervisorType}; #[cfg(feature = "function_call_metrics")] use crate::sandbox::metrics::SandboxMetric::GuestFunctionCallDurationMicroseconds; +use crate::sandbox::uninitialized::SandboxMetadata; #[cfg(target_os = "linux")] use crate::signal_handlers::setup_signal_handlers; use crate::HyperlightError::{ @@ -242,6 +243,7 @@ impl HypervisorHandler { &mut self, sandbox_memory_manager: SandboxMemoryManager, #[cfg(gdb)] debug_info: Option, + metadata: SandboxMetadata, ) -> Result<()> { let configuration = self.configuration.clone(); #[cfg(target_os = "windows")] @@ -308,6 +310,7 @@ impl HypervisorHandler { configuration.outb_handler.clone(), #[cfg(gdb)] &debug_info, + &metadata, )?); } let hv = hv.as_mut().ok_or_else(|| new_error!("Hypervisor not set"))?; @@ -855,6 +858,7 @@ fn set_up_hypervisor_partition( #[allow(unused_variables)] // parameter only used for in-process mode outb_handler: OutBHandlerWrapper, #[cfg(gdb)] debug_info: &Option, + metadata: &SandboxMetadata, ) -> Result> { let mem_size = u64::try_from(mgr.shared_mem.mem_size())?; let mut regions = mgr.layout.get_memory_regions(&mgr.shared_mem)?; @@ -944,6 +948,7 @@ fn set_up_hypervisor_partition( pml4_ptr, #[cfg(gdb)] gdb_conn, + metadata.clone(), )?; Ok(Box::new(hv)) } @@ -957,6 +962,7 @@ fn set_up_hypervisor_partition( rsp_ptr.absolute()?, #[cfg(gdb)] gdb_conn, + metadata.clone(), )?; Ok(Box::new(hv)) } diff --git a/src/hyperlight_host/src/hypervisor/inprocess.rs b/src/hyperlight_host/src/hypervisor/inprocess.rs index 0a87c30d..59b0f76a 100644 --- a/src/hyperlight_host/src/hypervisor/inprocess.rs +++ b/src/hyperlight_host/src/hypervisor/inprocess.rs @@ -19,11 +19,11 @@ use std::os::raw::c_void; use log::LevelFilter; +#[cfg(crashdump)] +use super::crashdump; #[cfg(gdb)] use super::handlers::DbgMemAccessHandlerWrapper; use super::{HyperlightExit, Hypervisor}; -#[cfg(crashdump)] -use crate::mem::memory_region::MemoryRegion; use crate::sandbox::leaked_outb::LeakedOutBWrapper; use crate::Result; @@ -134,7 +134,7 @@ impl<'a> Hypervisor for InprocessDriver<'a> { } #[cfg(crashdump)] - fn get_memory_regions(&self) -> &[MemoryRegion] { - unimplemented!("get_memory_regions is not supported since we are in in-process mode") + fn get_crashdump_context(&self) -> Result { + unimplemented!("get_crashdump_context is not supported since we are in in-process mode"); } } diff --git a/src/hyperlight_host/src/hypervisor/kvm.rs b/src/hyperlight_host/src/hypervisor/kvm.rs index e106755c..06102a0a 100644 --- a/src/hyperlight_host/src/hypervisor/kvm.rs +++ b/src/hyperlight_host/src/hypervisor/kvm.rs @@ -16,6 +16,8 @@ limitations under the License. use std::convert::TryFrom; use std::fmt::Debug; +#[cfg(crashdump)] +use std::path::Path; #[cfg(gdb)] use std::sync::{Arc, Mutex}; @@ -25,6 +27,8 @@ use kvm_ioctls::{Kvm, VcpuExit, VcpuFd, VmFd}; use log::LevelFilter; use tracing::{instrument, Span}; +#[cfg(crashdump)] +use super::crashdump; use super::fpu::{FP_CONTROL_WORD_DEFAULT, FP_TAG_WORD_DEFAULT, MXCSR_DEFAULT}; #[cfg(gdb)] use super::gdb::{DebugCommChannel, DebugMsg, DebugResponse, GuestDebug, KvmDebug, VcpuStopReason}; @@ -38,6 +42,7 @@ use super::{ use crate::hypervisor::hypervisor_handler::HypervisorHandler; use crate::mem::memory_region::{MemoryRegion, MemoryRegionFlags}; use crate::mem::ptr::{GuestPtr, RawPtr}; +use crate::sandbox::uninitialized::SandboxMetadata; #[cfg(gdb)] use crate::HyperlightError; use crate::{log_then_return, new_error, Result}; @@ -286,6 +291,8 @@ pub(super) struct KVMDriver { debug: Option, #[cfg(gdb)] gdb_conn: Option>, + #[allow(dead_code)] + metadata: SandboxMetadata, } impl KVMDriver { @@ -299,6 +306,7 @@ impl KVMDriver { entrypoint: u64, rsp: u64, #[cfg(gdb)] gdb_conn: Option>, + metadata: SandboxMetadata, ) -> Result { let kvm = Kvm::new()?; @@ -350,6 +358,7 @@ impl KVMDriver { debug, #[cfg(gdb)] gdb_conn, + metadata, }; Ok(ret) @@ -582,8 +591,61 @@ impl Hypervisor for KVMDriver { } #[cfg(crashdump)] - fn get_memory_regions(&self) -> &[MemoryRegion] { - &self.mem_regions + fn get_crashdump_context(&self) -> Result { + let mut regs = [0; 27]; + + let vcpu_regs = self.vcpu_fd.get_regs()?; + let sregs = self.vcpu_fd.get_sregs()?; + let xsave = self.vcpu_fd.get_xsave()?; + + regs[0] = vcpu_regs.r15; // r15 + regs[1] = vcpu_regs.r14; // r14 + regs[2] = vcpu_regs.r13; // r13 + regs[3] = vcpu_regs.r12; // r12 + regs[4] = vcpu_regs.rbp; // rbp + regs[5] = vcpu_regs.rbx; // rbx + regs[6] = vcpu_regs.r11; // r11 + regs[7] = vcpu_regs.r10; // r10 + regs[8] = vcpu_regs.r9; // r9 + regs[9] = vcpu_regs.r8; // r8 + regs[10] = vcpu_regs.rax; // rax + regs[11] = vcpu_regs.rcx; // rcx + regs[12] = vcpu_regs.rdx; // rdx + regs[13] = vcpu_regs.rsi; // rsi + regs[14] = vcpu_regs.rdi; // rdi + regs[15] = 0; // orig rax + regs[16] = vcpu_regs.rip; // rip + regs[17] = sregs.cs.selector as u64; // cs + regs[18] = vcpu_regs.rflags; // eflags + regs[19] = vcpu_regs.rsp; // rsp + regs[20] = sregs.ss.selector as u64; // ss + regs[21] = sregs.fs.base; // fs_base + regs[22] = sregs.gs.base; // gs_base + regs[23] = sregs.ds.selector as u64; // ds + regs[24] = sregs.es.selector as u64; // es + regs[25] = sregs.fs.selector as u64; // fs + regs[26] = sregs.gs.selector as u64; // gs + + let filename = self.metadata.binary_path.clone().map(|path| { + Path::new(&path) + .file_name() + .map(|name| name.to_os_string().into_string().unwrap()) + .unwrap() + }); + + Ok(crashdump::CrashDumpContext::new( + &self.mem_regions, + regs, + xsave.region.into_iter().fold(vec![], |mut acc, item| { + let bytes = item.to_le_bytes(); + acc.append(&mut bytes.to_vec()); + + acc + }), + self.entrypoint, + self.metadata.binary_path.clone(), + filename, + )) } #[cfg(gdb)] diff --git a/src/hyperlight_host/src/hypervisor/mod.rs b/src/hyperlight_host/src/hypervisor/mod.rs index bec42f35..6fc28c92 100644 --- a/src/hyperlight_host/src/hypervisor/mod.rs +++ b/src/hyperlight_host/src/hypervisor/mod.rs @@ -237,7 +237,7 @@ pub(crate) trait Hypervisor: Debug + Sync + Send { fn get_partition_handle(&self) -> windows::Win32::System::Hypervisor::WHV_PARTITION_HANDLE; #[cfg(crashdump)] - fn get_memory_regions(&self) -> &[MemoryRegion]; + fn get_crashdump_context(&self) -> Result; #[cfg(gdb)] /// handles the cases when the vCPU stops due to a Debug event @@ -351,7 +351,7 @@ pub(crate) mod tests { HvHandlerConfig, HypervisorHandler, HypervisorHandlerAction, }; use crate::mem::ptr::RawPtr; - use crate::sandbox::uninitialized::GuestBinary; + use crate::sandbox::uninitialized::{GuestBinary, SandboxMetadata}; use crate::sandbox::{SandboxConfiguration, UninitializedSandbox}; use crate::{new_error, Result}; @@ -413,6 +413,7 @@ pub(crate) mod tests { gshm, #[cfg(gdb)] None, + SandboxMetadata { binary_path: None }, )?; hv_handler.execute_hypervisor_handler_action(HypervisorHandlerAction::Initialise) diff --git a/src/hyperlight_host/src/sandbox/uninitialized.rs b/src/hyperlight_host/src/sandbox/uninitialized.rs index c1527a5c..a7c3438f 100644 --- a/src/hyperlight_host/src/sandbox/uninitialized.rs +++ b/src/hyperlight_host/src/sandbox/uninitialized.rs @@ -39,6 +39,11 @@ use crate::sandbox_state::sandbox::EvolvableSandbox; use crate::sandbox_state::transition::Noop; use crate::{log_build_details, log_then_return, new_error, MultiUseSandbox, Result}; +#[derive(Clone, Debug, Default)] +pub(crate) struct SandboxMetadata { + pub(crate) binary_path: Option, +} + /// A preliminary `Sandbox`, not yet ready to execute guest code. /// /// Prior to initializing a full-fledged `Sandbox`, you must create one of @@ -58,6 +63,7 @@ pub struct UninitializedSandbox { pub(crate) max_guest_log_level: Option, #[cfg(gdb)] pub(crate) debug_info: Option, + pub(crate) metadata: SandboxMetadata, } impl crate::sandbox_state::sandbox::UninitializedSandbox for UninitializedSandbox { @@ -136,17 +142,22 @@ impl UninitializedSandbox { #[cfg(target_os = "windows")] check_windows_version()?; + // If the guest binary is a file make sure the path is saved + let mut metadata = SandboxMetadata::default(); + // If the guest binary is a file make sure it exists let guest_binary = match guest_binary { GuestBinary::FilePath(binary_path) => { let path = Path::new(&binary_path) .canonicalize() .map_err(|e| new_error!("GuestBinary not found: '{}': {}", binary_path, e))?; - GuestBinary::FilePath( - path.into_os_string() - .into_string() - .map_err(|e| new_error!("Error converting OsString to String: {:?}", e))?, - ) + let path = path + .into_os_string() + .into_string() + .map_err(|e| new_error!("Error converting OsString to String: {:?}", e))?; + + metadata.binary_path = Some(path.clone()); + GuestBinary::FilePath(path) } buffer @ GuestBinary::Buffer(_) => buffer, }; @@ -200,6 +211,7 @@ impl UninitializedSandbox { max_guest_log_level: None, #[cfg(gdb)] debug_info, + metadata, }; // TODO: These only here to accommodate some writer functions. diff --git a/src/hyperlight_host/src/sandbox/uninitialized_evolve.rs b/src/hyperlight_host/src/sandbox/uninitialized_evolve.rs index 6ddba5e2..d5648f10 100644 --- a/src/hyperlight_host/src/sandbox/uninitialized_evolve.rs +++ b/src/hyperlight_host/src/sandbox/uninitialized_evolve.rs @@ -23,6 +23,7 @@ use tracing::{instrument, Span}; #[cfg(gdb)] use super::mem_access::dbg_mem_access_handler_wrapper; +use super::uninitialized::SandboxMetadata; use crate::hypervisor::hypervisor_handler::{ HvHandlerConfig, HypervisorHandler, HypervisorHandlerAction, }; @@ -74,6 +75,7 @@ where u_sbox.max_guest_log_level, #[cfg(gdb)] u_sbox.debug_info, + u_sbox.metadata, )?; { @@ -111,6 +113,7 @@ fn hv_init( max_wait_for_cancellation: Duration, max_guest_log_level: Option, #[cfg(gdb)] debug_info: Option, + metadata: SandboxMetadata, ) -> Result { let outb_hdl = outb_handler_wrapper(hshm.clone(), host_funcs); let mem_access_hdl = mem_access_handler_wrapper(hshm.clone()); @@ -149,6 +152,7 @@ fn hv_init( gshm, #[cfg(gdb)] debug_info, + metadata, )?; hv_handler diff --git a/src/tests/rust_guests/callbackguest/Cargo.lock b/src/tests/rust_guests/callbackguest/Cargo.lock index 45c7e59a..e6539664 100644 --- a/src/tests/rust_guests/callbackguest/Cargo.lock +++ b/src/tests/rust_guests/callbackguest/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "autocfg" diff --git a/src/tests/rust_guests/simpleguest/Cargo.lock b/src/tests/rust_guests/simpleguest/Cargo.lock index 7a007753..9d1d1c7e 100644 --- a/src/tests/rust_guests/simpleguest/Cargo.lock +++ b/src/tests/rust_guests/simpleguest/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "autocfg"