Skip to content
Open
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
9 changes: 9 additions & 0 deletions .github/workflows/check-digdir.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,15 @@ jobs:
Set-MsvcEnvironment -Architecture ${{ matrix.vs_arch }} -HostArchitecture ${{ matrix.vs_host_arch }}
cargo test --locked --no-default-features --features local,net,runner,ssh -p microsandbox-utils -p microsandbox-runtime -p microsandbox -p microsandbox-cli --lib --target ${{ matrix.rust_target }} windows_drive

- name: Test nested virtualization host check
shell: pwsh
# Exercises the WHP probe on x86_64; hosted runners may or may not offer nesting.
run: |
$ErrorActionPreference = "Stop"
. "$env:GITHUB_WORKSPACE\vendor\libkrunfw\scripts\msvc-env.ps1"
Set-MsvcEnvironment -Architecture ${{ matrix.vs_arch }} -HostArchitecture ${{ matrix.vs_host_arch }}
cargo test --locked --no-default-features -p microsandbox-runtime --lib --target ${{ matrix.rust_target }} nested_virt

- name: Test bind rootfs backend
shell: pwsh
# Tests build without embed-binaries and take the guest agent from this override.
Expand Down
6 changes: 5 additions & 1 deletion COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ HTTP CONNECT outbound proxies accept optional Basic authentication through an op

That probe covers SDK launches only. v0.7.x `machine` runtimes and v0.7.x SDKs decode the proxy object leniently, so a saved configuration reopened by an older release drops `credentials` and would connect without authentication; a read-modify-write through an older SDK can then persist the stripped representation. No representability check in `crates/db/lib/compat/` covers this field today, and the downgrade preflight matches v0.6.x and v0.7.0-v0.7.6 rather than v0.7.7. Adding `credentials` to an existing variant also breaks Rust consumers that construct `OutboundProxy::HttpConnect` literally or match its fields exactly, and `OutboundProxyBuildError` is not `#[non_exhaustive]`.

Nested virtualization uses the optional `nested_virt` launch key and `resources.nested_virt` record field, both omitted while off, so sandboxes without it are byte-identical for every runtime and catalog reader. Enabling it, at create or through `modify`, needs the runtime `nested_virt` capability and host support; the SDK refuses before replacing, changing, or starting a sandbox, a v0.7 runtime without the capability rejects the unknown launch key, and the previous launch contract refuses it. A runtime or CLI that predates the field builds its own launch from the stored record and ignores the field, so it starts such a sandbox without nested virtualization instead of refusing. The field stays in the record, and applies again on the next start through a current SDK, unless an older peer rewrites the record: an older `modify` drops it silently.
Nested virtualization uses the optional `nested_virt` launch key and `resources.nested_virt` record field, both omitted while off, so sandboxes without it are byte-identical for every runtime and catalog reader. Enabling it, at create or through `modify`, needs the runtime `nested_virt` capability and host support; the SDK refuses before replacing, changing, or starting a sandbox, a v0.7 runtime without the capability rejects the unknown launch key, and the previous launch contract refuses it. A runtime or CLI that predates the field builds its own launch from the stored record and ignores the field, so it starts such a sandbox without nested virtualization instead of refusing. The field stays in the record, and applies again on the next start through a current SDK, unless an older peer rewrites the record: an older `modify` drops it silently. Windows x86_64 hosts support it from the release that bumps libkrun to 0.1.42, and both host checks must accept the host. An older SDK refuses before launch. Older Windows runtimes advertise `nested_virt` but refuse nesting on Windows when the VM starts, so a current SDK that launches one passes its own admission and the start fails after `replace` or a `modify` restart has already changed the sandbox. That needs an SDK that resolves an older runtime binary. Runtimes ship together with the SDK, so this is accepted rather than guarded by a separate capability.

Starting a sandbox crosses a private process boundary. On Unix, launch JSON is passed through inherited descriptor 96, the parent watchdog uses descriptor 97, startup JSON uses descriptor 98, and the lifecycle lock uses descriptor 99. Windows uses a short-lived launch-config file and platform-specific startup plumbing. Detach acknowledgement bytes and graceful-shutdown signals are also part of this contract.

Expand All @@ -180,6 +180,8 @@ Sources: [`crates/runtime/lib/client/launch.rs`](crates/runtime/lib/client/launc

Windows disk attachment retains the existing exclusive sidecar filenames and sharing mode. The launcher duplicates non-inheritable sidecar handles into the exact spawned process and sends their values through a bounded startup-only stdin message, required by the hidden `msb machine --disk-locks-stdin` flag. The runtime adopts them before opening guest disks; successful handoff closes the launcher's copies without an unlocked interval. The SDK sends this flag only to modern runtimes; previous runtimes retain launcher-owned locks and never receive the unsupported flag. Failed or cancelled handoffs terminate the child before storage cleanup; confirmed exit also clears any remaining parent copies. Stop/start observes owned-disk sidecar release, independently of retained SDK objects. This changes the Windows private launch contract, not SDK APIs, agent framing, snapshot formats, or disk bytes.

On Windows, detached runtimes are started with `CREATE_BREAKAWAY_FROM_JOB` so that they outlive the launcher's job object. When that job does not allow breakaway, as under `cargo test` or in some sandboxed tool shells, `CreateProcess` refuses with `ERROR_ACCESS_DENIED`. The SDK then logs a warning and starts the runtime inside the job instead of failing. Such a runtime ends when the job is terminated or its last handle closes with kill-on-close, so a detached sandbox can stop when that test run or shell exits. Launchers in no job, or in a job that allows breakaway, are unchanged. If both attempts fail, the error names the process start. Launch arguments, JSON, handles and runtime state are unchanged.

Unix disk-lock descriptors stay close-on-exec in the SDK parent and become inheritable only in the intended child's pre-exec callback. Successful spawn closes the parent's copies without explicitly unlocking the child's shared open-file descriptions. The runtime receives the same locked descriptors; this Unix handoff preserves fixed launch descriptors, JSON and paths. Stop and terminal restart additionally observe this sandbox's owned-disk marker locks under transition/lifecycle ownership, since a zombie leader and free lifecycle lock do not prove deferred file teardown finished. Named/external disks retain ordinary conflict admission. An already-running older development SDK can still retain its own parent lock copy; the new observer waits or times out rather than forcibly unlocking that genuine holder. Drop that old handle or restart that SDK process before retesting with the corrected handoff.

Launch JSON requires an explicit `execution` intent (`boot` or `restore`) and rejects unknown fields. Restores also pass the internal `msb machine --restore` argument: a runtime predating this contract rejects the unknown argument rather than ignoring a JSON restore source and cold-booting. The argument, intent, and complete strictly validated `checkpoint_restore` source must agree before VM construction. Unsupported restore behavior is an error, never a fresh-boot fallback. These #8 development contracts replace superseded unreleased forms without shims; they do not change portable snapshot bytes.
Expand Down Expand Up @@ -388,6 +390,8 @@ Do not independently substitute or upgrade one component because its upstream AB

Normal x86 boot now declares `krun.poweroff=i8042` in libkrun's default kernel command line. Matching libkrunfw registers a low-priority final poweroff handler that sends the existing i8042 exit byte after orderly Linux shutdown. Generic KVM identity is not enough to enable it. Without both the host declaration and the new kernel, Linux may halt without releasing VMM ownership; StopWithTimeout reports expiry without killing. Existing running guests and full snapshots retain their captured kernel and require a fresh boot/recapture to acquire the handler. ARM platform poweroff, explicit custom command-line replacement and SEV/TDX built-in overrides are unchanged; they are not implicitly qualified by the normal Linux x86 test.

`msb_krun` 0.1.42 changes Windows x86_64 full snapshots. WHP execution state now records the emulated PIT, so new captures use backend state ABI 2, where earlier runtimes wrote ABI 1 without it. Each side refuses the other's state before the guest runs: this runtime rejects an earlier Windows full snapshot, fork or branch with libkrun's missing-PIT error, and an earlier runtime rejects the new ABI as incompatible. Restart such a sandbox from the snapshot's disks and capture a new full snapshot. Disk-only snapshots, Linux and macOS execution state, and non-Windows hosts are unchanged. Windows guests also boot with `tsc_early_khz` from the WHP processor clock, prepended to the default kernel command line so explicit caller values still win; this changes no launch field.

## 13. Networking, DNS, Published Ports, and Secret Substitution

Strict hostname policy is enabled by default. The v0.6.0–v0.6.17 launch gate rejects strict policies containing outbound hostname allow rules, including domain suffixes and rules applying in both directions. Policies without those rules retain their existing behavior on older runtimes because strict enforcement is unused. Explicit `strict: false` remains supported.
Expand Down
44 changes: 22 additions & 22 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ microsandbox-runtime = { version = "=0.7.11-digdir.1", path = "crates/runtime",
microsandbox-utils = { version = "=0.7.11-digdir.1", path = "crates/utils" }
microsandbox-vsock = { version = "=0.7.11-digdir.1", path = "crates/vsock" }
# Keep runtime APIs and shared metrics types on the same published release.
msb_krun = "=0.1.41"
msb_krun_utils = "=0.1.41"
msb_krun = "=0.1.42"
msb_krun_utils = "=0.1.42"
test-macros = { path = "crates/testing/macros" }
test-utils = { path = "crates/testing/utils" }

Expand Down
2 changes: 1 addition & 1 deletion crates/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ tracing.workspace = true
zeroize.workspace = true

[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.61.2", features = ["Win32_Foundation", "Win32_Security", "Win32_Security_Authorization", "Win32_Storage_FileSystem", "Win32_System_Kernel", "Win32_System_SystemInformation", "Win32_System_Threading"] }
windows-sys = { version = "0.61.2", features = ["Win32_Foundation", "Win32_Security", "Win32_Security_Authorization", "Win32_Storage_FileSystem", "Win32_System_Hypervisor", "Win32_System_Kernel", "Win32_System_LibraryLoader", "Win32_System_SystemInformation", "Win32_System_Threading"] }

[target.'cfg(unix)'.dependencies]
microsandbox-agent-client = { workspace = true, features = ["uds"], optional = true }
Expand Down
Loading
Loading