Create sandboxes directly from snapshots#1459
Conversation
There was a problem hiding this comment.
Pull request overview
Adds the ability to construct a MultiUseSandbox directly from an Arc<Snapshot>, bypassing UninitializedSandbox + evolve(). Snapshots now record the host functions registered at capture time, and the new constructor validates that the provided host-function set is a superset of those required. The gdb entry-point breakpoint mechanism is reworked into a one-shot tracked on the VM so it works for both Initialise and Call snapshots.
Changes:
- New
HostFunctionsnewtype (withdefault()pre-registeringHostPrintandnew()empty) andMultiUseSandbox::from_snapshot(snap, host_funcs, cfg). Snapshotnow carriesHostFunctionDetailsand exposesvalidate_host_functionsto reject missing/mismatched signatures; pre-init snapshots accept any registry.- Gdb support: replaces
VcpuStopReason::EntryPointBpwith aone_shot_entry_bpfield cleared by the run loop; entry breakpoint installed for bothInitialiseandCallentries; new gdb e2e test for snapshot path.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/hyperlight_host/src/sandbox/initialized_multi_use.rs | Implements from_snapshot, layout-override warning, snapshot host-function plumbing, and tests. |
| src/hyperlight_host/src/sandbox/snapshot/mod.rs | Adds host_functions field and validate_host_functions; updates constructors and tests. |
| src/hyperlight_host/src/sandbox/host_funcs.rs | Adds HostFunctions newtype and with_default_host_print; changes register_host_function to infallible; tweaks From impl. |
| src/hyperlight_host/src/sandbox/uninitialized.rs | Uses with_default_host_print and removes redundant register_print call in new. |
| src/hyperlight_host/src/func/host_functions.rs | Adapts Registerable impls to infallible registry call; adds HostFunctions impl. |
| src/hyperlight_host/src/mem/mgr.rs | Plumbs HostFunctionDetails into snapshot(); inherits snapshot_count in from_snapshot. |
| src/hyperlight_host/src/mem/layout.rs | Widens visibility of several layout fields and MAX_MEMORY_SIZE. |
| src/hyperlight_host/src/lib.rs | Re-exports HostFunctions. |
| src/hyperlight_host/src/hypervisor/hyperlight_vm/x86_64.rs | Sets up one-shot entry breakpoint covering Initialise and Call. |
| src/hyperlight_host/src/hypervisor/hyperlight_vm/mod.rs | Adds one_shot_entry_bp field and run-loop logic to clear it on first hit. |
| src/hyperlight_host/src/hypervisor/gdb/mod.rs | Removes VcpuStopReason::EntryPointBp variant. |
| src/hyperlight_host/src/hypervisor/gdb/event_loop.rs | Drops handling for the removed variant. |
| src/hyperlight_host/src/hypervisor/gdb/arch.rs | vcpu_stop_reason no longer takes/uses the entrypoint, becomes side-effect-free classifier. |
| src/hyperlight_host/examples/guest-debugging/main.rs | Extracts gdb test helpers and adds test_gdb_from_snapshot. |
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
jsturtevant
left a comment
There was a problem hiding this comment.
LGTM, I've left a few comments and one missing testing that needs a fix
|
|
||
| // Validate that the provided host functions are a superset of | ||
| // those required by the snapshot. | ||
| snapshot.validate_host_functions(&host_funcs)?; |
There was a problem hiding this comment.
I assume the snapshot manager does other validation? Should this validation live with that validation? if not are we missing validation? Can a maliciously crafted snapshot bypass any assumptions we have about the memory layout?
| .expect_err("signature mismatch on `Add` must be rejected"); | ||
| let msg = format!("{}", err); | ||
| assert!(msg.contains("Add"), "got: {}", msg); | ||
| } |
There was a problem hiding this comment.
we are missing a test that catches the case: snapshot, register a new host function, snapshot again
A test that demonstrates this is missing and fails:
let mut sbox = make_sandbox();
let _ = sbox.snapshot().unwrap();
sbox.register_host_function("Echo42", || Ok(42i64)).unwrap();
let snap = sbox.snapshot().unwrap();
let err = MultiUseSandbox::from_snapshot(snap, HostFunctions::default(), None)
.expect_err("late-registered `Echo42` must be required by the new snapshot");
let msg = format!("{}", err);
assert!(msg.contains("Echo42"), "got: {}", msg);
| /// disagrees with `snapshot`. Used by [`MultiUseSandbox::from_snapshot`] | ||
| /// to surface ignored caller-supplied layout values, since those | ||
| /// fields are always taken from the snapshot. | ||
| fn warn_on_layout_override( |
There was a problem hiding this comment.
what's the consequences of lay override?
Builds a ready-to-use MultiUseSandbox directly from an
Arc<Snapshot>without going throughUninitializedSandbox+evolve(). Building block for OCI-backed snapshot loading on a follow-up branch.Adds:
HostFunctionsnewtype around the internal FunctionRegistry. default() pre-registers HostPrint, empty() starts empty.MultiUseSandbox::from_snapshot(snap, host_funcs, cfg). Snapshot is the source of truth for layout. cfg is honored for non-layout fields (timeouts, debug info, interrupt retry delay).Recommend to review commit-by-commit