Skip to content

Commit 27ba8a0

Browse files
committed
crashdump: allow crashdump toggle at sandbox level
- this allows a user to configure the crash dump feature at sandbox level - create a SandboxRuntimeConfig struct to contain all the configuration a sandbox would need at runtime to avoid passing the information as multiple functions arguments Signed-off-by: Doru Blânzeanu <[email protected]>
1 parent e88b55f commit 27ba8a0

File tree

9 files changed

+319
-267
lines changed

9 files changed

+319
-267
lines changed

src/hyperlight_host/src/hypervisor/crashdump.rs

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -251,47 +251,51 @@ pub(crate) fn crashdump_to_tempfile(hv: &dyn Hypervisor) -> Result<()> {
251251
.crashdump_context()
252252
.map_err(|e| new_error!("Failed to get crashdump context: {:?}", e))?;
253253

254-
// Set up data sources for the core dump
255-
let guest_view = GuestView::new(&ctx);
256-
let memory_reader = GuestMemReader::new(&ctx);
257-
258-
// Create and write core dump
259-
let core_builder = CoreDumpBuilder::from_source(guest_view, memory_reader);
260-
261-
// Generate timestamp string for the filename using chrono
262-
let timestamp = chrono::Local::now().format("%Y%m%d_%H%M%S").to_string();
263-
264-
// Determine the output directory based on environment variable
265-
let output_dir = if let Ok(dump_dir) = std::env::var("HYPERLIGHT_CORE_DUMP_DIR") {
266-
// Create the directory if it doesn't exist
267-
let path = std::path::Path::new(&dump_dir);
268-
if !path.exists() {
269-
std::fs::create_dir_all(path)
270-
.map_err(|e| new_error!("Failed to create core dump directory: {:?}", e))?;
271-
}
272-
std::path::PathBuf::from(dump_dir)
273-
} else {
274-
// Fall back to the system temp directory
275-
std::env::temp_dir()
276-
};
254+
// If the returned a context it means we can create a core dump
255+
// This is the case when the sandbox has been configured at runtime to allow core dumps
256+
if let Some(ctx) = ctx {
257+
// Set up data sources for the core dump
258+
let guest_view = GuestView::new(&ctx);
259+
let memory_reader = GuestMemReader::new(&ctx);
260+
261+
// Create and write core dump
262+
let core_builder = CoreDumpBuilder::from_source(guest_view, memory_reader);
263+
264+
// Generate timestamp string for the filename using chrono
265+
let timestamp = chrono::Local::now().format("%Y%m%d_%H%M%S").to_string();
266+
267+
// Determine the output directory based on environment variable
268+
let output_dir = if let Ok(dump_dir) = std::env::var("HYPERLIGHT_CORE_DUMP_DIR") {
269+
// Create the directory if it doesn't exist
270+
let path = std::path::Path::new(&dump_dir);
271+
if !path.exists() {
272+
std::fs::create_dir_all(path)
273+
.map_err(|e| new_error!("Failed to create core dump directory: {:?}", e))?;
274+
}
275+
std::path::PathBuf::from(dump_dir)
276+
} else {
277+
// Fall back to the system temp directory
278+
std::env::temp_dir()
279+
};
277280

278-
// Create the filename with timestamp
279-
let filename = format!("hl_core_{}.elf", timestamp);
280-
let file_path = output_dir.join(filename);
281+
// Create the filename with timestamp
282+
let filename = format!("hl_core_{}.elf", timestamp);
283+
let file_path = output_dir.join(filename);
281284

282-
// Create the file
283-
let file = std::fs::File::create(&file_path)
284-
.map_err(|e| new_error!("Failed to create core dump file: {:?}", e))?;
285+
// Create the file
286+
let file = std::fs::File::create(&file_path)
287+
.map_err(|e| new_error!("Failed to create core dump file: {:?}", e))?;
285288

286-
// Write the core dump directly to the file
287-
core_builder
288-
.write(&file)
289-
.map_err(|e| new_error!("Failed to write core dump: {:?}", e))?;
289+
// Write the core dump directly to the file
290+
core_builder
291+
.write(&file)
292+
.map_err(|e| new_error!("Failed to write core dump: {:?}", e))?;
290293

291-
let path_string = file_path.to_string_lossy().to_string();
294+
let path_string = file_path.to_string_lossy().to_string();
292295

293-
println!("Core dump created successfully: {}", path_string);
294-
log::error!("Core dump file: {}", path_string);
296+
println!("Core dump created successfully: {}", path_string);
297+
log::error!("Core dump file: {}", path_string);
298+
}
295299

296300
Ok(())
297301
}

src/hyperlight_host/src/hypervisor/hyperv_linux.rs

Lines changed: 67 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use mshv_bindings::{
4949
use mshv_ioctls::{Mshv, VcpuFd, VmFd};
5050
use tracing::{instrument, Span};
5151
#[cfg(crashdump)]
52-
use {super::crashdump, crate::sandbox::uninitialized::SandboxMetadata, std::path::Path};
52+
use {super::crashdump, crate::sandbox::uninitialized::SandboxRuntimeConfig, std::path::Path};
5353

5454
use super::fpu::{FP_CONTROL_WORD_DEFAULT, FP_TAG_WORD_DEFAULT, MXCSR_DEFAULT};
5555
#[cfg(gdb)]
@@ -301,7 +301,7 @@ pub(super) struct HypervLinuxDriver {
301301
#[cfg(gdb)]
302302
gdb_conn: Option<DebugCommChannel<DebugResponse, DebugMsg>>,
303303
#[cfg(crashdump)]
304-
metadata: SandboxMetadata,
304+
rt_cfg: SandboxRuntimeConfig,
305305
}
306306

307307
impl HypervLinuxDriver {
@@ -320,7 +320,7 @@ impl HypervLinuxDriver {
320320
rsp_ptr: GuestPtr,
321321
pml4_ptr: GuestPtr,
322322
#[cfg(gdb)] gdb_conn: Option<DebugCommChannel<DebugResponse, DebugMsg>>,
323-
#[cfg(crashdump)] metadata: SandboxMetadata,
323+
#[cfg(crashdump)] rt_cfg: SandboxRuntimeConfig,
324324
) -> Result<Self> {
325325
let mshv = Mshv::new()?;
326326
let pr = Default::default();
@@ -401,7 +401,7 @@ impl HypervLinuxDriver {
401401
#[cfg(gdb)]
402402
gdb_conn,
403403
#[cfg(crashdump)]
404-
metadata,
404+
rt_cfg,
405405
})
406406
}
407407

@@ -686,57 +686,61 @@ impl Hypervisor for HypervLinuxDriver {
686686
}
687687

688688
#[cfg(crashdump)]
689-
fn crashdump_context(&self) -> Result<super::crashdump::CrashDumpContext> {
690-
let mut regs = [0; 27];
691-
692-
let vcpu_regs = self.vcpu_fd.get_regs()?;
693-
let sregs = self.vcpu_fd.get_sregs()?;
694-
let xsave = self.vcpu_fd.get_xsave()?;
695-
696-
// Set up the registers for the crash dump
697-
regs[0] = vcpu_regs.r15; // r15
698-
regs[1] = vcpu_regs.r14; // r14
699-
regs[2] = vcpu_regs.r13; // r13
700-
regs[3] = vcpu_regs.r12; // r12
701-
regs[4] = vcpu_regs.rbp; // rbp
702-
regs[5] = vcpu_regs.rbx; // rbx
703-
regs[6] = vcpu_regs.r11; // r11
704-
regs[7] = vcpu_regs.r10; // r10
705-
regs[8] = vcpu_regs.r9; // r9
706-
regs[9] = vcpu_regs.r8; // r8
707-
regs[10] = vcpu_regs.rax; // rax
708-
regs[11] = vcpu_regs.rcx; // rcx
709-
regs[12] = vcpu_regs.rdx; // rdx
710-
regs[13] = vcpu_regs.rsi; // rsi
711-
regs[14] = vcpu_regs.rdi; // rdi
712-
regs[15] = 0; // orig rax
713-
regs[16] = vcpu_regs.rip; // rip
714-
regs[17] = sregs.cs.selector as u64; // cs
715-
regs[18] = vcpu_regs.rflags; // eflags
716-
regs[19] = vcpu_regs.rsp; // rsp
717-
regs[20] = sregs.ss.selector as u64; // ss
718-
regs[21] = sregs.fs.base; // fs_base
719-
regs[22] = sregs.gs.base; // gs_base
720-
regs[23] = sregs.ds.selector as u64; // ds
721-
regs[24] = sregs.es.selector as u64; // es
722-
regs[25] = sregs.fs.selector as u64; // fs
723-
regs[26] = sregs.gs.selector as u64; // gs
724-
725-
// Get the filename from the binary path
726-
let filename = self.metadata.binary_path.clone().and_then(|path| {
727-
Path::new(&path)
728-
.file_name()
729-
.and_then(|name| name.to_os_string().into_string().ok())
730-
});
731-
732-
Ok(crashdump::CrashDumpContext::new(
733-
&self.mem_regions,
734-
regs,
735-
xsave.buffer.to_vec(),
736-
self.entrypoint,
737-
self.metadata.binary_path.clone(),
738-
filename,
739-
))
689+
fn crashdump_context(&self) -> Result<Option<super::crashdump::CrashDumpContext>> {
690+
if self.rt_cfg.guest_core_dump {
691+
let mut regs = [0; 27];
692+
693+
let vcpu_regs = self.vcpu_fd.get_regs()?;
694+
let sregs = self.vcpu_fd.get_sregs()?;
695+
let xsave = self.vcpu_fd.get_xsave()?;
696+
697+
// Set up the registers for the crash dump
698+
regs[0] = vcpu_regs.r15; // r15
699+
regs[1] = vcpu_regs.r14; // r14
700+
regs[2] = vcpu_regs.r13; // r13
701+
regs[3] = vcpu_regs.r12; // r12
702+
regs[4] = vcpu_regs.rbp; // rbp
703+
regs[5] = vcpu_regs.rbx; // rbx
704+
regs[6] = vcpu_regs.r11; // r11
705+
regs[7] = vcpu_regs.r10; // r10
706+
regs[8] = vcpu_regs.r9; // r9
707+
regs[9] = vcpu_regs.r8; // r8
708+
regs[10] = vcpu_regs.rax; // rax
709+
regs[11] = vcpu_regs.rcx; // rcx
710+
regs[12] = vcpu_regs.rdx; // rdx
711+
regs[13] = vcpu_regs.rsi; // rsi
712+
regs[14] = vcpu_regs.rdi; // rdi
713+
regs[15] = 0; // orig rax
714+
regs[16] = vcpu_regs.rip; // rip
715+
regs[17] = sregs.cs.selector as u64; // cs
716+
regs[18] = vcpu_regs.rflags; // eflags
717+
regs[19] = vcpu_regs.rsp; // rsp
718+
regs[20] = sregs.ss.selector as u64; // ss
719+
regs[21] = sregs.fs.base; // fs_base
720+
regs[22] = sregs.gs.base; // gs_base
721+
regs[23] = sregs.ds.selector as u64; // ds
722+
regs[24] = sregs.es.selector as u64; // es
723+
regs[25] = sregs.fs.selector as u64; // fs
724+
regs[26] = sregs.gs.selector as u64; // gs
725+
726+
// Get the filename from the binary path
727+
let filename = self.rt_cfg.binary_path.clone().and_then(|path| {
728+
Path::new(&path)
729+
.file_name()
730+
.and_then(|name| name.to_os_string().into_string().ok())
731+
});
732+
733+
Ok(Some(crashdump::CrashDumpContext::new(
734+
&self.mem_regions,
735+
regs,
736+
xsave.buffer.to_vec(),
737+
self.entrypoint,
738+
self.rt_cfg.binary_path.clone(),
739+
filename,
740+
)))
741+
} else {
742+
Ok(None)
743+
}
740744
}
741745

742746
#[cfg(gdb)]
@@ -857,7 +861,14 @@ mod tests {
857861
#[cfg(gdb)]
858862
None,
859863
#[cfg(crashdump)]
860-
SandboxMetadata { binary_path: None },
864+
SandboxRuntimeConfig {
865+
#[cfg(crashdump)]
866+
binary_path: None,
867+
#[cfg(gdb)]
868+
debug_info: None,
869+
#[cfg(crashdump)]
870+
guest_core_dump: true,
871+
},
861872
)
862873
.unwrap();
863874
}

0 commit comments

Comments
 (0)