Commit graph

116 commits

Author SHA1 Message Date
72d50a50ee feat: add runtime sound control to device tray
The device tray now shows Sound Output and Microphone Input menus for
running VMs. Each direction can be toggled per-VM at runtime via the
vhost-device-sound control socket. Initial state comes from the existing
sound.playback/sound.capture NixOS options.

NixOS module passes --initial-streams and --control-socket to
vhost-device-sound. The vhost-device flake input is updated to include
the new control socket support.
2026-03-27 23:17:44 +00:00
6b0cb107c9 feat: add usb.logLevel option for USB passthrough service 2026-03-27 19:42:10 +00:00
c1ebb1813b docs: update CLAUDE.md and README.md for vsock-connect and related changes
Document the new vmsilo-vsock library crate, vsock-connect CLI tool,
vm-stop --all flag, and CID file pattern. Update SSH ProxyCommand
description for cloud-hypervisor VMs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 18:46:41 +00:00
6772a029a5 docs: update README.md fuzzing section for AFL++/SymCC and renamed apps
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 14:13:15 +00:00
92b249608a docs: add fuzz seed corpus generator usage to CLAUDE.md and README.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 00:07:37 +00:00
ef5e320cfc docs: add --fork and fuzz-clean-dbus-proxy usage to README and CLAUDE.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 22:24:43 +00:00
e0ab55208f feat(dbus-proxy): add cargo-fuzz fuzzing infrastructure
Add coverage-guided fuzzing for vmsilo-dbus-proxy with 5 targets:
- fuzz_deserialize: raw bytes → postcard deserialization
- fuzz_read_message: raw bytes → length-prefixed framing
- fuzz_sanitize_snapshot: structured input → sanitization invariants
- fuzz_sanitize_notification: structured input → sanitization invariants
- fuzz_tint_pixmap: structured input → pixel manipulation

Uses the arbitrary crate (behind a fuzz feature flag) for structured
input generation, with invariant assertion helpers that verify all
documented sanitization constraints.

Nix integration via rust-overlay nightly: `nix develop .#fuzz` for
interactive fuzzing, `nix run .#fuzz-dbus-proxy -- <target>` for
one-liners.

Also fixes a sanitization bug found by the fuzzer: sanitize_menu_tree
did not clamp negative IDs on the root menu node.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 21:05:28 +00:00
f3663e7e66 Sandbox virtiofsd services with namespace isolation and hardening
virtiofsd has built-in sandboxing (--sandbox=namespace): it creates
mount/PID/network namespaces, does pivot_root, drops capabilities, and
applies its own seccomp filter. The systemd unit adds non-overlapping
hardening: IPC/UTS namespace isolation, seccomp-based protections, a
capability bounding set as defense-in-depth, and LimitNOFILE=1048576.

Per-instance runtime directories (/run/vmsilo/<vmname>/virtiofs-<tag>/)
replace the shared directory for better isolation.

New VM options: virtiofs.seccompPolicy and virtiofs.disableSandbox.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 11:48:20 +00:00
b75563e100 Update docs: remove sommelier references, simplify wayland proxy section
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 00:17:55 +00:00
cd6a22b0c3 Sandbox cloud-hypervisor VMs with namespaces, landlock, and capability dropping
Harden CH VM services with a whitelist approach:

- TemporaryFileSystem=/ with explicit BindPaths/BindReadOnlyPaths
- PrivateUsers=identity (1:1 UID mapping, zero host capabilities)
- PrivatePIDs, PrivateIPC
- Empty CapabilityBoundingSet, NoNewPrivileges
- DevicePolicy=closed with specific DeviceAllow
- ProtectKernel{Tunables,Modules,Logs}, RestrictNamespaces, LockPersonality
- CH landlock enabled via --landlock flag

Launch flow restructured: ExecStart runs the CH binary directly inside
the sandbox. ExecStartPost=+ (privileged) handles VM creation, TAP FD
passing via vmsilo-tap-open + ch-remote add-net, boot, and socket chown.
ExecStartPre=+/ExecStopPost=+ handle ephemeral disk and socket cleanup.

Network config removed from CH JSON — TAP interfaces added via ch-remote
add-net with FD passing (SCM_RIGHTS). TAP and runtime directory ownership
changed to root. Wayland-seccontext socket moved to gpu/ subdirectory.
Ephemeral disk moved to per-VM /var/lib/vmsilo/{name}/ directory.

New option: cloud-hypervisor.disableSandbox (default false) disables all
hardening except seccomp.

PrivateNetwork=true is not yet enabled — TAP FD passing works but CH
gets EIO writing to the TAP from inside a private network namespace.
To be investigated separately.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 22:52:20 +00:00
68e25742cf refactor: simplify options - new defaults, remove globals, restructure GPU
- Default hypervisor: crosvm → cloud-hypervisor
- Default GPU backend: crosvm → vhost-device-gpu
- GPU option: either bool submodule → pure submodule (disable via gpu.wayland = false)
- Remove global programs.vmsilo.{crosvm,cloud-hypervisor,vmsilo-dbus-proxy} options
- Per-VM crosvm/cloud-hypervisor options now non-nullable with direct defaults
- Add per-VM dbus.logLevel (passed to guest via kernel param, keeping rootfs uniform)
- Delete normalizeGpuConfig, gpuConfig, and all global fallback resolution code
- Simplify GPU assertion to use vm.gpu.* directly (no mkVmConfig needed)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 18:35:36 +00:00
98769aec88 Disable OpenGL by default, update docs
OpenGL and Vulkan worked in some simple test programs when using crosvm
with built-in GPU emulation. I never got them working in any real-world
application, I suspect because wayland dmabuf is not working. After
switching to vhost-user gpu, even the testcases don't work, but I
think it's worthwhile to be able to sandbox the GPU process better.
2026-03-23 15:39:52 +00:00
fccdfba687 Restructure waylandProxy option into waylandProxy.type and waylandProxy.logLevel
Maps logLevel to wayland-proxy-virtwl's --log-level flag (replaces
hardcoded -v). Ignored for sommelier.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 23:16:08 +00:00
77f00cb734 feat: add vhost-device-gpu as alternative GPU device backend
Add gpu.backend option to select between crosvm's built-in GPU device
emulation ("crosvm", default) and vhost-device-gpu ("vhost-device").
Both backends use the same vhost-user socket, sandboxing, and
wayland-seccontext service.

Also adds gpu.vulkan option (venus capset) and makes gpu.logLevel
independent of crosvm.logLevel (default "info").

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 22:58:00 +00:00
faad5006c9 cleanup: remove vmsilo-start-* scripts, rename vmsilo-usb to vm-usb, fix vm-run output
- Remove vmsilo-start-* user-facing symlinks from package.nix (internal
  VM launcher scripts are only used by systemd ExecStart, not by users)
- Rename vmsilo-usb to vm-usb to match the vm-* naming convention
- Increase socat -t timeout in vm-run from default 0.5s to 5s to fix
  missing output from console commands (cloud-hypervisor proxy startup
  latency exceeded the default timeout window)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 16:51:57 +00:00
08709827fb feat: replace crosvm USB passthrough with usbip-over-vsock
Replace crosvm xhci-based USB passthrough with usbip-rs over vsock,
enabling USB passthrough for both crosvm and cloud-hypervisor VMs.

Guest runs a persistent usbip-rs client listener on vsock port 5002.
Host runs one sandboxed usbip-rs host connect process per attached
device as a systemd template service (vmsilo-<vm>-usb@<devpath>).

Eliminates the JSON state file, file locking, and crosvm-specific
shell helper library in favor of systemd as the source of truth.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 16:15:27 +00:00
99cccf89ba VM option cloudHypervisor -> cloud-hypervisor for consistency 2026-03-22 09:55:43 +00:00
43438277d8 fix: use screen -dmS with Type=forking for console drain service
screen -dmS forks to background (daemon mode), which should work
without a controlling terminal. Type=forking tells systemd to expect
the fork.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 20:10:06 +00:00
dae577fe0f fix: switch from screen to tmux for console drain sessions
screen requires a controlling terminal which systemd services don't
provide. tmux works without a terminal via new-session without -d.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 20:04:27 +00:00
cb4c7d163e docs: update vm-shell detach instructions for screen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 19:49:11 +00:00
cd73430c3e feat: add RUST_BACKTRACE=full to all Rust services and sound.logLevel option
Set RUST_BACKTRACE=full on VM, GPU, sound, dbus-proxy, balloond, and
wayland-seccontext services for better crash diagnostics. Add per-VM
sound.logLevel option (default "info") that sets RUST_LOG on the
vhost-device-sound service.

Also document previously undocumented options in README: cloud-hypervisor
hugepages, netvmRange, sound.logLevel, sound.seccompPolicy,
cloudHypervisor.hugepages, cloudHypervisor.seccompPolicy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:53:49 +00:00
ce22c095cb feat: add gpu.disableSandbox option for debugging GPU service
Allows disabling non-seccomp sandboxing (filesystem isolation, device
allow, capabilities, private network, etc.) per VM. Seccomp remains
independently controlled via gpu.seccompPolicy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:00:04 +00:00
57a71e16ae feat: add per-VM tray.enable option (default false)
Tray proxy was unconditionally enabled for all crosvm VMs. Add
tray.enable so it must be opted into per VM. When disabled, neither
the host-side tray service nor the guest-side tray daemon are created.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 09:37:32 +00:00
5d587eb421 docs: update README for GPU sub-options, remove stale vulkan references
Remove vulkan/venus references (option was removed in cloud-hypervisor
refactor) and document gpu.allowWX, gpu.logLevel, gpu.seccompPolicy
per-VM options that were missing from the options table and GPU section.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 09:36:45 +00:00
cf16f2b07c docs: update README for cloud-hypervisor options, remove vm-start-debug
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 09:36:22 +00:00
62ceb91b90 Update docs for vmsilo-dbus-proxy rename and notification support
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 17:21:39 +00:00
7e2f3cf708 Document automatic DNS configuration for netvm setups
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 14:31:37 +00:00
6fd44b9d2f Change default shared home path from /shared/<vm> to /shared/<vm>/home
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 11:20:14 +00:00
dfa2dd8054 Add sharedDirectories mountPath option for automatic guest mounts
Adds a `mountPath` option to `sharedDirectories.<name>` that, when set,
automatically mounts the virtiofs share at the specified path inside the
guest via systemd.mount-extra kernel parameter. The implicit sharedHome
entry now uses this same code path (mountPath = "/home/user") instead of
a hardcoded special case.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 11:16:49 +00:00
463f73d274 Add PAM limits for guest PipeWire realtime scheduling
xdg-desktop-portal 1.20.3's Realtime portal intercepts PipeWire's RT
scheduling requests but fails silently: it calls fstatat(pidfd, "ns/pid")
to check the caller's PID namespace, which returns ENOTDIR because pidfds
don't support being used as directory FDs on current kernels (6.18/6.19).
PipeWire uses fire-and-forget D-Bus and never sees the error.

Fix by granting the @audio group PAM limits (rtprio=95, nice=-19,
memlock=unlimited) so PipeWire's module-rt can call sched_setscheduler
directly, bypassing both the broken portal and rtkit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 11:35:15 +00:00
b876265793 Reduce default core isolation from "full" to "vm"
Full isolation has too much impact to be a default. Even on an almost
unloaded machine with a couple of VMs running it results in audio buffer
underruns due to the significant scheduling latency.

This change is fine because with vmsilo, the trust domain is the VM. There
isn't much reason to protect apps from other apps running in the same VM.
Better to run those apps in separate VMs in that case.
2026-03-18 11:35:10 +00:00
eda15f16f8 Update options and docs for vhost-device-sound
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:45:22 +00:00
43c99ec162 Document USB device passthrough in README and CLAUDE.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 13:10:54 +00:00
0a07f7f14e Switch ephemeral overlay from qcow2 to raw sparse image
qcow2 causes O_DIRECT failures on ext4 due to crosvm doing unaligned
access when parsing the qcow2 header. Since we don't use any qcow2
features (the disk is created fresh and deleted on stop), a raw sparse
file via truncate works just as well and also removes the qemu package
dependency from the VM service.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 00:49:44 +00:00
3b0bbd088d Update docs and examples 2026-03-07 17:49:04 +00:00
3b640b1662 netvm: support network.netvm = "host" for host-routed networking
Route VM traffic through the host directly instead of requiring a
separate netvm VM. Uses the same nftables NAT and forward firewall
rules as VM-based netvms, applied on the host using TAP interface
names. Removes the hostNetworking.nat options in favor of the
unified netvm approach.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 15:28:47 +00:00
f33abeace0 Update README.md and examples to use netvm config 2026-03-07 15:07:04 +00:00
bb1ab85237 netvm: add network.netvm/isNetvm convenience layer for auto VM-to-VM links
Adds network.netvm / network.isNetvm options that auto-configure
point-to-point VM networking (host bridge, TAP interfaces, guest IPs,
default routes, masquerade NAT, and forward firewall rules) without
manual interface configuration.

New options:
  programs.vmsilo.netvmRange         — IP pool for /31 auto-allocation (default 10.200.0.0/16)
  vm.network.isNetvm                  — mark VM as a network gateway
  vm.network.netvm                    — route this VM through a named netvm
  vm.network.netvmSubnet              — override auto-allocated /31 (pin specific address)

Architecture:
  modules/netvm.nix computes all (netvm, client) pairs and writes to
  _internal.netvmInjections to avoid infinite recursion in the module
  system. networking.nix, scripts.nix, and services.nix each have a
  getEffectiveInterfaces helper that merges user-configured and
  injected interfaces transparently.

  Guest nftables config (masquerade NAT, forward isolation between
  clients, ip_forward sysctl) is injected via _generatedGuestConfig
  and merged into the rootfs build in scripts.nix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 14:21:38 +00:00
85c88cfb33 Change nixosVms from list to attrset keyed by VM name
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 20:26:55 +00:00
b247b46066 Start autoStart GPU VMs with session instead of at boot
GPU VMs need a Wayland socket, so starting them at multi-user.target
(boot) fails. The session-bind user service now also starts autoStart
GPU VMs when the graphical session begins. Non-GPU VMs still start at
boot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 22:14:53 +00:00
f34b494dd1 Fix last blocker for guest-side vulkan
Add libvulkan.so to crosvm LD_LIBRARY_PATH. Along with the earlier fix
commits, this now enables full guest-side vulkan (tested with vkcube
and vulkaninfo - they're using the host GPU). Huzzah!

Was hoping enabling vulkan and not opengl would make mesa fall back to
zink, so we could skip virgl2 and just translate opengl to vulkan. But
it still ends up using llvmpipe. Forcing zink gives errors, getting that
working will be the next goal.
2026-02-22 16:16:25 +00:00
f1041db662 Refactor GPU option from raw crosvm attrset to high-level feature config
Replace the low-level gpu attrset (mapped directly to --gpu args) with a
submodule of supported features: wayland (cross-domain), opengl (virgl2),
and vulkan (venus). Vulkan automatically adds --gpu-render-server.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 13:06:41 +00:00
16b08cc3c8 Add nvidiaWeakenSandbox option to select crosvm-nvidia package
Nvidia GPU drivers require RWX memory pages, which crosvm's seccomp
sandbox blocks. This option switches to a crosvm-nvidia build with
a relaxed W+X memory policy, keeping the default secure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 00:46:58 +00:00
a20c5d06af Use darkred as default VM color
Plain red is distractingly intense.
2026-02-20 18:29:08 +00:00
8de5e55801 Replace sound tri-state with playback/capture booleans
Instead of passing raw crosvm attrsets, sound is now configured
with two booleans: sound.playback (default true) and sound.capture
(default false, implies playback).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:30:39 +00:00
c2e054171b Replace crosvm built-in virtiofs with virtiofsd
Switch shared directories from crosvm's built-in --shared-dir to
external virtiofsd processes connected via --vhost-user. Each shared
directory gets a dedicated virtiofsd systemd service that starts
before the VM and stops when the VM stops.

The sharedDirectories option is now an attrsOf submodule (keyed by
fs tag) with typed options for all virtiofsd flags instead of the
previous freeform list passed directly to crosvm.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 23:57:10 +00:00
67b8284c9c Add schedulerIsolation option to configure hyperthreading mitigations
Also add crosvm options to hint to the scheduler to put it on the performance
cores, enable vCPU stop on guest suspend and disable some legacy peripheral
emulation.
2026-02-19 22:00:01 +00:00
4238d34638 Update kwin clipboard patches for separate global clipboard
Instead of using host buffer, use a global vmsilo buffer. Host buffer is
treated just like VM buffers - copying to/from it needs explicit action. This
is more like the Qubes behavior, only difference is that copy/paste to/from
the host clipboard is allowed.
2026-02-19 21:58:50 +00:00
cd1fc27a4a Add sound capture support, bump crosvm and wayland proxy 2026-02-19 00:53:27 +00:00
be6a175c87 README.md: Update quickstart config, minor updates 2026-02-18 23:19:34 +00:00