Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
### Added

### Changed
* Core dumps no longer record the guest binary path. The process name and command line are always `<unknown>`, as they already were for sandboxes created from snapshots by @ludfjig in https://github.com/hyperlight-dev/hyperlight/pull/1975

### Removed

Expand Down
2 changes: 1 addition & 1 deletion docs/how-to-debug-a-hyperlight-guest.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ After the core dump has been created, to inspect the state of the guest, load th

#### Using gdb

Load the core dump alongside the guest binary that was running when the crash occurred:
Load the core dump alongside the guest binary that was running when the crash occurred. Core dumps do not record which guest binary that was, so keep track of the guest each sandbox runs:

```bash
gdb <guest-binary> -c <core-dump-file>
Expand Down
42 changes: 8 additions & 34 deletions src/hyperlight_host/src/hypervisor/crashdump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ const CORE_DUMP_PID: i32 = 1;
/// The page size of the core dump
const CORE_DUMP_PAGE_SIZE: usize = 0x1000;

/// Process name and command line in the core dump. Sandboxes do not
/// record which guest binary they run.
const UNKNOWN_PROCESS: &str = "<unknown>";

/// Structure to hold the crash dump context
/// This structure contains the information needed to create a core dump
#[derive(Debug)]
Expand All @@ -38,7 +42,6 @@ pub(crate) struct CrashDumpContext {
regs: [u64; 27],
xsave: Vec<u8>,
entry: u64,
binary: Option<PathBuf>,
}

impl CrashDumpContext {
Expand All @@ -47,14 +50,12 @@ impl CrashDumpContext {
regs: [u64; 27],
xsave: Vec<u8>,
entry: u64,
binary: Option<PathBuf>,
) -> Self {
Self {
regions,
regs,
xsave,
entry,
binary,
}
}
}
Expand Down Expand Up @@ -88,21 +89,6 @@ impl GuestView {
})
.collect();

let filename = ctx
.binary
.as_deref()
.and_then(|path| path.file_name())
.map_or("<unknown>".to_string(), |name| {
name.to_string_lossy().into_owned()
});

let cmd = ctx
.binary
.as_deref()
.map_or("<unknown>".to_string(), |path| {
path.to_string_lossy().into_owned()
});

// The xsave state is checked as it can be empty
let mut components = vec![];
if !ctx.xsave.is_empty() {
Expand All @@ -122,7 +108,7 @@ impl GuestView {
tid: 1,
uid: 0, // User ID
gid: 0, // Group ID
comm: filename,
comm: UNKNOWN_PROCESS.to_string(),
Comment thread
jsturtevant marked this conversation as resolved.
ppid: 0, // Parent PID
pgrp: 0, // Process group ID
nice: 0, // Nice value
Expand All @@ -135,7 +121,7 @@ impl GuestView {
session: 0, // Session ID of the process
sighold: 0, // Blocked signal
sigpend: 0, // Pending signal
cmd_line: cmd,
cmd_line: UNKNOWN_PROCESS.to_string(),

arch_state: Box::new(ArchState {
gpr_state: ctx.regs.to_vec(),
Expand Down Expand Up @@ -435,13 +421,7 @@ mod test {
#[test]
fn test_crashdump_write_fails_when_no_regions() {
// Create a dummy context
let ctx = CrashDumpContext::new(
vec![],
[0; 27],
vec![],
0,
Some(PathBuf::from("dummy_binary")),
);
let ctx = CrashDumpContext::new(vec![], [0; 27], vec![], 0);

let get_writer = || Ok(Box::new(std::io::empty()) as Box<dyn Write>);

Expand All @@ -466,13 +446,7 @@ mod test {
region_type: crate::mem::memory_region::MemoryRegionType::Code,
}];
// Create a dummy context
let ctx = CrashDumpContext::new(
regions,
[0; 27],
vec![],
0x1000,
Some(PathBuf::from("dummy_binary")),
);
let ctx = CrashDumpContext::new(regions, [0; 27], vec![], 0x1000);

let get_writer = || Ok(Box::new(std::io::empty()) as Box<dyn Write>);

Expand Down
3 changes: 0 additions & 3 deletions src/hyperlight_host/src/hypervisor/hyperlight_vm/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ use crate::sandbox::host_funcs::FunctionRegistry;
use crate::sandbox::snapshot::NextAction;
#[cfg(feature = "mem_profile")]
use crate::sandbox::trace::MemTraceInfo;
#[cfg(crashdump)]
use crate::sandbox::uninitialized::SandboxRuntimeConfig;

impl HyperlightVm {
#[allow(clippy::too_many_arguments)]
Expand All @@ -52,7 +50,6 @@ impl HyperlightVm {
page_size: usize,
#[cfg_attr(target_os = "windows", allow(unused_variables))] config: &SandboxConfiguration,
#[cfg(gdb)] _gdb_conn: Option<DebugCommChannel<DebugResponse, DebugMsg>>,
#[cfg(crashdump)] _rt_cfg: SandboxRuntimeConfig,
#[cfg(feature = "mem_profile")] _trace_info: MemTraceInfo,
) -> std::result::Result<Self, CreateHyperlightVmError> {
// TODO: support gdb on aarch64
Expand Down
18 changes: 2 additions & 16 deletions src/hyperlight_host/src/hypervisor/hyperlight_vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ use crate::sandbox::outb::{HandleOutbError, handle_outb};
use crate::sandbox::snapshot::NextAction;
#[cfg(feature = "mem_profile")]
use crate::sandbox::trace::MemTraceInfo;
#[cfg(crashdump)]
use crate::sandbox::uninitialized::SandboxRuntimeConfig;

/// Get the logging level filter to pass to the guest entrypoint
///
Expand Down Expand Up @@ -399,7 +397,7 @@ pub(crate) struct HyperlightVm {
#[cfg(feature = "mem_profile")]
pub(super) trace_info: MemTraceInfo,
#[cfg(crashdump)]
pub(super) rt_cfg: SandboxRuntimeConfig,
pub(super) guest_core_dump: bool,
/// MSRs restored on snapshot restore.
#[cfg(target_arch = "x86_64")]
pub(super) msr_reset: crate::hypervisor::regs::MsrResetState,
Expand Down Expand Up @@ -576,18 +574,6 @@ impl HyperlightVm {
self.next_action = next_action
}

/// Set the guest ELF entry point used to fill `AT_ENTRY` in
/// crashdumps.
#[cfg(crashdump)]
pub(crate) fn set_crashdump_entry_point(&mut self, entry_point: u64) {
self.rt_cfg.entry_point = Some(entry_point);
}

#[cfg(crashdump)]
pub(crate) fn clear_crashdump_binary_path(&mut self) {
self.rt_cfg.binary_path = None;
}

pub(crate) fn interrupt_handle(&self) -> Arc<dyn InterruptHandle> {
self.interrupt_handle.clone()
}
Expand Down Expand Up @@ -786,7 +772,7 @@ impl HyperlightVm {
}
Err(e) => {
#[cfg(crashdump)]
if self.rt_cfg.guest_core_dump {
if self.guest_core_dump {
crate::hypervisor::crashdump::generate_crashdump(self, mem_mgr, None)
.map_err(|e| RunVmError::CrashdumpGeneration(Box::new(e)))?;
}
Expand Down
33 changes: 9 additions & 24 deletions src/hyperlight_host/src/hypervisor/hyperlight_vm/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ use crate::sandbox::host_funcs::FunctionRegistry;
use crate::sandbox::snapshot::NextAction;
#[cfg(feature = "mem_profile")]
use crate::sandbox::trace::MemTraceInfo;
#[cfg(crashdump)]
use crate::sandbox::uninitialized::SandboxRuntimeConfig;

#[cfg(gdb)]
type BoxedVm = Box<dyn DebuggableVm>;
Expand All @@ -65,7 +63,6 @@ impl HyperlightVm {
page_size: usize,
#[cfg_attr(target_os = "windows", allow(unused_variables))] config: &SandboxConfiguration,
#[cfg(gdb)] gdb_conn: Option<DebugCommChannel<DebugResponse, DebugMsg>>,
#[cfg(crashdump)] rt_cfg: SandboxRuntimeConfig,
#[cfg(feature = "mem_profile")] trace_info: MemTraceInfo,
) -> std::result::Result<Self, CreateHyperlightVmError> {
let mut vm: BoxedVm = match get_available_hypervisor() {
Expand Down Expand Up @@ -136,7 +133,7 @@ impl HyperlightVm {
#[cfg(feature = "mem_profile")]
trace_info,
#[cfg(crashdump)]
rt_cfg,
guest_core_dump: config.get_guest_core_dump(),
msr_reset,
};

Expand Down Expand Up @@ -521,7 +518,7 @@ impl HyperlightVm {
mem_mgr: &mut SandboxMemoryManager<HostSharedMemory>,
) -> std::result::Result<Option<crate::hypervisor::crashdump::CrashDumpContext>, CrashDumpError>
{
if self.rt_cfg.guest_core_dump {
if self.guest_core_dump {
let mut regs = [0; 27];

let vcpu_regs = self.vm.regs()?;
Expand Down Expand Up @@ -557,17 +554,12 @@ impl HyperlightVm {
regs[25] = sregs.fs.selector as u64; // fs
regs[26] = sregs.gs.selector as u64; // gs

// 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.
// We cannot use self.next_action here because it transitions from
// Initialise(addr) to Call(dispatch_addr) after guest init.
let initialise = self.rt_cfg.entry_point.unwrap_or_else(|| {
tracing::warn!(
"entry_point was never set in SandboxRuntimeConfig; AT_ENTRY will be 0"
);
0
});
// GDB derives the PIE load offset from AT_ENTRY. `next_action`
// holds the dispatch address after init, so use the ELF entry.
let entry = mem_mgr.original_entrypoint;
if entry == 0 {
tracing::warn!("Guest entry point is unknown; AT_ENTRY will be 0");
}
let mmap_regions: Vec<MemoryRegion> = self.get_mapped_regions().cloned().collect();
let root_pt = self.get_root_pt()?;

Expand All @@ -579,8 +571,7 @@ impl HyperlightVm {
regions,
regs,
xsave.to_vec(),
initialise,
self.rt_cfg.binary_path.clone(),
entry,
)))
} else {
Ok(None)
Expand Down Expand Up @@ -880,8 +871,6 @@ mod tests {
use crate::mem::shared_mem::{ExclusiveSharedMemory, ReadonlySharedMemory};
use crate::sandbox::SandboxConfiguration;
use crate::sandbox::host_funcs::FunctionRegistry;
#[cfg(any(crashdump, gdb))]
use crate::sandbox::uninitialized::SandboxRuntimeConfig;
use crate::sandbox::uninitialized_evolve::set_up_hypervisor_partition;

/// Test context holding an initialized VM with memory manager.
Expand Down Expand Up @@ -1472,8 +1461,6 @@ mod tests {
/// both `hyperlight_vm()` and `create_test_vm_context()`.
fn create_test_vm_context(code: &[u8]) -> TestVmContext {
let config: SandboxConfiguration = Default::default();
#[cfg(any(crashdump, gdb))]
let rt_cfg: SandboxRuntimeConfig = Default::default();

let (layout, pt_bytes) = create_test_layout(code.len());

Expand Down Expand Up @@ -1506,8 +1493,6 @@ mod tests {
&config,
stack_top_gva,
page_size::get(),
#[cfg(any(crashdump, gdb))]
rt_cfg,
crate::mem::exe::LoadInfo::dummy(),
)
.unwrap();
Expand Down
6 changes: 0 additions & 6 deletions src/hyperlight_host/src/hypervisor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,8 +470,6 @@ pub(crate) mod tests {
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};
Expand All @@ -489,8 +487,6 @@ pub(crate) mod tests {
let filename = dummy_guest_as_pathbuf();

let config: SandboxConfiguration = Default::default();
#[cfg(any(crashdump, gdb))]
let rt_cfg: SandboxRuntimeConfig = Default::default();
let sandbox =
UninitializedSandbox::new(GuestBinary::FilePath(filename.clone()), Some(config))?;
let (mut mem_mgr, gshm) = sandbox.mgr.build().unwrap();
Expand All @@ -502,8 +498,6 @@ pub(crate) mod tests {
&config,
exn_stack_top_gva,
page_size::get(),
#[cfg(any(crashdump, gdb))]
rt_cfg,
sandbox.load_info,
)?;

Expand Down
36 changes: 2 additions & 34 deletions src/hyperlight_host/src/sandbox/initialized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,32 +287,8 @@ impl Sandbox {
#[cfg(target_os = "linux")]
crate::signal_handlers::setup_signal_handlers(&config)?;

// Runtime config for the restored sandbox. `guest_core_dump`
// (crashdump) and `guest_debug_info` (gdb) come from the caller's
// config. `binary_path` stays `None`. `set_up_hypervisor_partition`
// fills `entry_point` from the manager's entry point so crashdumps
// carry the correct `AT_ENTRY`.
#[cfg(any(crashdump, gdb))]
let rt_cfg = crate::sandbox::uninitialized::SandboxRuntimeConfig {
#[cfg(crashdump)]
binary_path: None,
#[cfg(gdb)]
debug_info: config.get_guest_debug_info(),
#[cfg(crashdump)]
guest_core_dump: config.get_guest_core_dump(),
#[cfg(crashdump)]
entry_point: None,
};

let mut vm = set_up_hypervisor_partition(
gshm,
&config,
stack_top_gva,
page_size,
#[cfg(any(crashdump, gdb))]
rt_cfg,
load_info,
)?;
let mut vm =
set_up_hypervisor_partition(gshm, &config, stack_top_gva, page_size, load_info)?;

let seed = {
let mut rng = rand::rng();
Expand Down Expand Up @@ -670,14 +646,6 @@ impl Sandbox {

self.vm.set_stack_top(snapshot.stack_top_gva());
self.vm.set_next_action(snapshot.next_action());
// Carry the guest ELF entry point across restore so a later
// crashdump fills `AT_ENTRY` from the restored image.
#[cfg(crashdump)]
{
self.vm
.set_crashdump_entry_point(snapshot.original_entrypoint());
self.vm.clear_crashdump_binary_path();
}

self.mem_mgr
.request_libc_rng_reseed(rand::random::<u32>())?;
Expand Down
Loading
Loading