Skip to content

Expose sandbox nested-virt capability and pre-check create on the host - #375

Open
AprilNEA wants to merge 1 commit into
masterfrom
core-13-nested-virt-capability-gating-fail-fast-and-expose-1ec7
Open

Expose sandbox nested-virt capability and pre-check create on the host#375
AprilNEA wants to merge 1 commit into
masterfrom
core-13-nested-virt-capability-gating-fail-fast-and-expose-1ec7

Conversation

@AprilNEA

@AprilNEA AprilNEA commented Jul 8, 2026

Copy link
Copy Markdown
Member

Sandboxes need nested virtualization (/dev/kvm inside the System VM), available only on the VZ backend with M3+/macOS 15+. The guest already probes /dev/kvm at init and rejects sandbox RPCs with FAILED_PRECONDITION — but that's a round-trip into the guest, and clients have no way to know the surface is dead before a Create.

This surfaces the capability on the host so arcbox sandbox create fails immediately with an actionable message, and clients (CLI/Desktop) can grey out sandbox features without booting a microVM.

  • New SystemService.GetSandboxCapability RPC returning { supported, reason, backend }, computed from the System VM backend plus a static host nested-virt probe.
  • arcbox_hypervisor::host_supports_nested_virt() — a cheap cross-platform probe (VZ on macOS, KVM module params on Linux x86_64) that doesn't construct a hypervisor. The Linux detection is refactored out of KvmHypervisor to back it.
  • arcbox sandbox create pre-checks and bails with the reason on unsupported hosts/backends; a missing/unavailable RPC falls through to the create (guest agent remains the backstop).

On supported setups behavior is unchanged.

Closes CORE-13.

@linear-code

linear-code Bot commented Jul 8, 2026

Copy link
Copy Markdown

CORE-13

Add SystemService.GetSandboxCapability so clients learn whether sandboxes
can run (nested-virt microVMs) without booting one into an opaque KVM
failure. The host computes it from the System VM backend plus a static
host nested-virt probe (arcbox_hypervisor::host_supports_nested_virt),
so arcbox sandbox create fails fast with an actionable message on
unsupported hardware/backends — no round-trip into the guest.

Refactor the Linux nested-virt detection out of KvmHypervisor into a
reusable module function backing the new cross-platform helper.

Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com>
@AprilNEA
AprilNEA force-pushed the core-13-nested-virt-capability-gating-fail-fast-and-expose-1ec7 branch from f5b1835 to e64d7e3 Compare July 21, 2026 05:25
@AprilNEA
AprilNEA marked this pull request as ready for review July 21, 2026 05:25

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e64d7e3575

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

.to_string(),
);
}
if backend == arcbox_vmm::VmBackend::Hv {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore the macOS backend selector when evaluating Linux hosts

On a Linux x86_64 host with KVM nesting enabled and vm.backend = "hv" (also accepted through ARCBOX_VM_BACKEND=hv), this rejects sandbox creation even though the Linux VMM always executes initialize_linux() and ignores the macOS-only VmBackend selector. The new Linux host probe therefore returns true for a usable nested-KVM setup, but this branch reports it unsupported and makes arcbox sandbox create bail before reaching the guest; apply the HV/VZ restriction only on macOS.

Useful? React with 👍 / 👎.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — two minor points, both inline.

Reviewed changes — a host-side sandbox nested-virt capability query plus a fast-fail pre-check on arcbox sandbox create, with the Linux nested-virt probe refactored into a reusable helper.

  • New GetSandboxCapability RPCSystemService gains an RPC returning SandboxCapability { supported, reason, backend }; proto message committed in the prost-generated arcbox.v1.rs, tonic service code regenerates via arcbox-grpc OUT_DIR.
  • Runtime::sandbox_capability() + pure evaluate_sandbox_capability — host nested-virt is the hard gate (checked first), then the HV backend becomes the actionable "switch to vz" blocker; split out for the unit test.
  • arcbox_hypervisor::host_supports_nested_virt() — cheap cross-platform probe (macOS VZ class-property, Linux x86_64 KVM nested module params) that constructs no hypervisor; Linux detection lifted out of KvmHypervisor::check_nested_virt (removed) into linux::host_supports_nested_virt.
  • CLI ensure_sandbox_supported pre-check — runs before SandboxServiceClient create; transport/RPC errors fall through so older/not-ready daemons still proceed, with the guest agent as backstop.
  • Unit testsandbox_capability_gates_on_nested_virt_and_backend covers the three gate outcomes.

ℹ️ Nitpicks

  • SandboxCapability is not added to the flat pub use v1::{...} block or the api submodule in rpc/arcbox-protocol/src/lib.rs, unlike sibling System types (ResolveImageFsResponse, etc.). It compiles because callers use the v1::SandboxCapability path, but rpc/AGENTS.md's extending checklist calls for the hand-written re-export so the flat arcbox_protocol::SandboxCapability path resolves for future consumers.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Claude Opus𝕏

if !host_nested_virt {
return (
false,
"sandbox requires nested virtualization: the VZ backend on Apple \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason strings here are macOS-specific ("the VZ backend on Apple Silicon M3 or newer with macOS 15+" and, below, "arcbox system backend vz"), but evaluate_sandbox_capability and the host_supports_nested_virt() probe both have real Linux paths (KVM nested module params). A Linux host with KVM nesting disabled would surface the Apple-Silicon message. Minor, and sandboxes are macOS-oriented, but the text is misleading off macOS.

Technical details
# macOS-centric reason strings on a cross-platform helper

## Affected sites
- `app/arcbox-core/src/runtime.rs:172-186` — both `reason` strings name Apple Silicon / macOS 15+ / `arcbox system backend vz`, yet the function is reached on Linux via `Runtime::sandbox_capability``arcbox_hypervisor::host_supports_nested_virt` (Linux KVM probe in `virt/arcbox-hypervisor/src/linux/mod.rs`).

## Required outcome
- On Linux, an unsupported result should read as a KVM-nesting message rather than an Apple-Silicon one — or the reason should be platform-conditional.

## Open questions for the human
- Is `arcbox sandbox create` a supported surface on Linux at all? If the System VM / sandbox architecture is macOS-only in practice, this is cosmetic and can be left as-is; if Linux is a real target, the strings should branch per platform.

@greptile-apps

greptile-apps Bot commented Jul 21, 2026

Copy link
Copy Markdown

Greptile Summary

This PR exposes sandbox nested-virtualization capability on the host. The main changes are:

  • Adds a sandbox capability RPC and protocol response.
  • Adds host probes for macOS VZ and Linux KVM.
  • Pre-checks sandbox create before contacting the guest.
  • Reuses the Linux probe for hypervisor capabilities.

Confidence Score: 4/5

The Linux ARM64 capability result and runtime readiness gate need fixes before merging.

Nested-KVM-capable ARM64 hosts can be rejected before creation. The host-only RPC remains unavailable until the System VM is ready. Unexpected RPC failures are hidden and creation continues.

virt/arcbox-hypervisor/src/linux/mod.rs, app/arcbox-api/src/system.rs, and app/arcbox-cli/src/commands/sandbox.rs

T-Rex T-Rex Logs

What T-Rex did

  • Validated ARM64 nested-KVM rejection by reproducing the behavior: cross-compiled the repository's probe as a Linux aarch64 ELF and executed it under QEMU, where the real function branch returned false and the assertion failed with exit code 101.
  • Collected reproducibility artifacts, including a rerunnable script, a Rust harness containing the reviewed function, and the command transcript that shows the aarch64 executable returning false and exiting with 101.
  • Attempted to run the focused startup-state harness to exercise the GetSandboxCapability path, but the build halted due to an unresolved super::KvmVcpu import in src/linux/vm/virtual_machine.rs, so no runtime response was captured.
  • Compared sandbox precheck flows and observed that the before path called CreateSandbox only, while the after path exercised GetSandboxCapability and Create RPCs; both harness runs exited 0, but the capability path hit a known nested-virtualization error with an import blocker leading to exit code 101.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
app/arcbox-api/src/system.rs Adds the capability RPC, but gates the host-only result on full runtime readiness.
app/arcbox-cli/src/commands/sandbox.rs Adds the create pre-check, but treats every RPC failure as a compatibility fallback.
app/arcbox-core/src/runtime.rs Adds the capability model and backend decision logic with focused tests.
rpc/arcbox-protocol/proto/api.proto Adds the capability RPC and its supported, reason, and backend fields.
virt/arcbox-hypervisor/src/lib.rs Adds a cross-platform entry point for static nested-virtualization detection.
virt/arcbox-hypervisor/src/linux/mod.rs Centralizes x86 KVM probing but categorically rejects Linux ARM64.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant CLI
participant SystemService
participant Runtime
participant HostProbe
participant SandboxService

CLI->>SystemService: GetSandboxCapability
SystemService->>Runtime: sandbox_capability()
Runtime->>HostProbe: host_supports_nested_virt()
HostProbe-->>Runtime: supported
Runtime-->>SystemService: supported, reason, backend
SystemService-->>CLI: SandboxCapability
alt Supported or RPC unavailable
    CLI->>SandboxService: Create
else Unsupported
    CLI-->>CLI: Fail with reason
end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant CLI
participant SystemService
participant Runtime
participant HostProbe
participant SandboxService

CLI->>SystemService: GetSandboxCapability
SystemService->>Runtime: sandbox_capability()
Runtime->>HostProbe: host_supports_nested_virt()
HostProbe-->>Runtime: supported
Runtime-->>SystemService: supported, reason, backend
SystemService-->>CLI: SandboxCapability
alt Supported or RPC unavailable
    CLI->>SandboxService: Create
else Unsupported
    CLI-->>CLI: Fail with reason
end
Loading

Reviews (1): Last reviewed commit: "feat(sandbox): expose nested-virt capabi..." | Re-trigger Greptile

Comment on lines +51 to +54
#[cfg(not(target_arch = "x86_64"))]
{
false
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 ARM64 Nested KVM Always Rejected

On Linux ARM64, this branch always reports false. A host with nested KVM enabled is therefore exposed as unsupported, so the new CLI pre-check blocks a sandbox that could run and shows an unrelated M3/macOS message.

Artifacts

Repro: rerunnable script that extracts the reviewed function, cross-compiles it, and executes it under ARM64 emulation

  • Contains supporting evidence from the run (text/x-shellscript; charset=utf-8).

Repro: generated repository-derived Rust harness containing the reviewed function and failing capability assertion

  • Contains supporting evidence from the run (text/x-rust; charset=utf-8).

Repro: command transcript showing an aarch64 executable returning false and failing with exit code 101

  • Keeps the command output available without making the summary code-heavy.

View artifacts

T-Rex Ran code and verified through T-Rex

&self,
_request: Request<Empty>,
) -> Result<Response<SandboxCapability>, Status> {
let runtime = self.runtime.ready()?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Host Capability Waits For Guest

This host-only query uses shared_runtime, which is unavailable until full runtime initialization and System VM readiness. During daemon startup, clients receive UNAVAILABLE even after early_runtime contains the configured backend, so they cannot discover the capability without first booting the VM.

Context Used: AGENTS.md (source)

}
// The capability RPC is unavailable (older daemon, not ready); let the
// create proceed rather than blocking on a missing pre-check.
Err(_) => Ok(()),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Capability Errors Silently Bypass Check

This arm treats every gRPC status as an unavailable capability RPC. A permission, data-loss, or internal server error therefore starts sandbox creation instead of reporting the failed pre-check; only compatibility and temporary-availability statuses should fall through.

Suggested change
Err(_) => Ok(()),
Err(status)
if matches!(
status.code(),
tonic::Code::Unimplemented | tonic::Code::Unavailable
) =>
{
Ok(())
}
Err(status) => Err(status.into()),

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant