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
8 changes: 8 additions & 0 deletions nvx-rs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,14 @@ cancellation and exit fail every pending phase. Failure stops no process and
writes no record. A matching Ready ends at `Done`, without sending mappings or
Start. Terminal results are offered once and absorb later inputs.

NVX's own binaries drive the machine with a blocking driver, private to the
crate, beside the control session. It checks that the restore-ready client and
the control server are the VM's held process, sends the same activate message,
the record and the workload's identity, in at most three sessions, and allows
60 seconds to Ready, then 30 more for the mapping table and the workload's
Start. The caller's cancellation and the VM's exit end any pending accept, read
or write.

`ReadyListener` owns a restore-ready endpoint: a mode-0600 Unix socket in the
private VM directory on Linux, or a fresh first-instance named pipe with an
owner-only protected access control list on Windows. Its public `receive`
Expand Down
6 changes: 5 additions & 1 deletion nvx-rs/src/host/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@
//! restore from a [`Snapshot`](snapshot::Snapshot) hard-links the snapshot's OpenVMM files into
//! the VM directory and binds its restore-ready listener before any spawn.
//! - [`restore`] orders caller-driven activation to Ready without I/O or a clock, and listens for
//! OpenVMM's restore-ready event from the held VM process.
//! OpenVMM's restore-ready event from the held VM process. The private `restore_driver` (feature
//! `cli`) drives it over the [`session`] for NVX's blocking callers, through Ready, the mapping
//! table and the workload's start.
//! - `cli` (feature `cli`) is the `nvx-rs` command-line interface, which runs microVMs and
//! sandboxes, looks up and downloads artifacts, and compiles egress policies.
//!
Expand Down Expand Up @@ -90,6 +92,8 @@ pub mod platform;
pub mod process;
pub mod report;
pub mod restore;
#[cfg(feature = "cli")]
mod restore_driver;
pub mod runtime;
pub mod sandbox;
pub mod seal;
Expand Down
10 changes: 10 additions & 0 deletions nvx-rs/src/host/platform/linux/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,16 @@ pub(crate) fn transport_from_handle(handle: TransportHandle) -> io::Result<Box<d
}))
}

/// Ends the pending and later transfers of the connection that `handle` duplicates, by shutting
/// the socket down in both directions: a read then ends the stream, and a write fails.
#[cfg(feature = "cli")]
pub(crate) fn interrupt_transfers(handle: &TransportHandle) -> io::Result<()> {
match nix::sys::socket::shutdown(handle.as_raw_fd(), nix::sys::socket::Shutdown::Both) {
Ok(()) | Err(sys::Errno::ENOTCONN) => Ok(()),
Err(error) => Err(error.into()),
}
}

/// Returns the process that listens on a control endpoint, or `None` if nothing listens.
pub(crate) fn endpoint_server_pid(endpoint: &str) -> io::Result<Option<u32>> {
endpoint_server_pid_until(endpoint, Instant::now() + Duration::from_secs(5))
Expand Down
4 changes: 3 additions & 1 deletion nvx-rs/src/host/platform/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ pub(crate) use self::endpoint::{
ReadyListener, connect_endpoint, control_endpoint, endpoint_server_pid, listen_ready,
};
#[cfg(feature = "cli")]
pub(crate) use self::endpoint::{endpoint_server_pid_until, transport_from_handle};
pub(crate) use self::endpoint::{
endpoint_server_pid_until, interrupt_transfers, transport_from_handle,
};
pub use self::identity::file_identity;
pub(crate) use self::identity::{
Directory, file_id, is_deleted, link_count, opened_file_id, opened_file_identity,
Expand Down
15 changes: 15 additions & 0 deletions nvx-rs/src/host/platform/windows/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,21 @@ pub(crate) fn transport_from_handle(pipe: TransportHandle) -> io::Result<Box<dyn
Ok(Box::new(PipeTransport { pipe, event }))
}

/// Cancels the transfers pending on the pipe connection that `handle` duplicates, which then fail
/// with `ERROR_OPERATION_ABORTED`. A transfer that starts later is not cancelled, so a caller
/// repeats this until none starts.
#[cfg(feature = "cli")]
pub(crate) fn interrupt_transfers(handle: &TransportHandle) -> io::Result<()> {
// SAFETY: the handle is an open pipe handle of the caller's, and no OVERLAPPED is named.
if unsafe { CancelIoEx(raw(handle), ptr::null()) } == 0 {
let error = last_error();
if error != windows_sys::Win32::Foundation::ERROR_NOT_FOUND {
return Err(io::Error::from_raw_os_error(error as i32));
}
}
Ok(())
}

/// Returns the process that serves a named-pipe endpoint, or `None` if the pipe does not exist.
///
/// OpenVMM keeps one pipe instance for its whole lifetime, so a missing pipe means no OpenVMM
Expand Down
4 changes: 3 additions & 1 deletion nvx-rs/src/host/platform/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ pub(crate) use self::endpoint::{
ReadyListener, connect_endpoint, control_endpoint, endpoint_server_pid, listen_ready,
};
#[cfg(feature = "cli")]
pub(crate) use self::endpoint::{endpoint_server_pid_until, transport_from_handle};
pub(crate) use self::endpoint::{
endpoint_server_pid_until, interrupt_transfers, transport_from_handle,
};
pub use self::identity::file_identity;
pub(crate) use self::identity::{
Directory, file_id, is_deleted, link_count, opened_file_id, opened_file_identity,
Expand Down
Loading
Loading