Uses fileset.toSource to widen src for vmsilo-tools and vmsilo-dbus-proxy
so both can resolve the shared vmsilo-vsock path dependency.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Pre-build the target before testing artifacts; abort without deleting
anything if the build fails
- Add 30s timeout per artifact test to prevent hangs on slow-unit inputs
- Add progress counter during artifact testing
- Add coreutils to PATH for timeout command
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
tint_pixmap crashed on index-out-of-bounds when argb_data length didn't
match width*height*4. Add checked-arithmetic validation before the loop.
Add `nix run .#fuzz-clean-dbus-proxy -- <target>` to replay all crash
artifacts and delete the ones that no longer reproduce.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Translates --fork=N to libfuzzer's -fork=N flag, allowing the fuzzer
to continue after finding crashes instead of stopping.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
System tray app (StatusNotifierItem + DBusMenu) for attaching/detaching
USB devices to VMs. Clicking the tray icon shows a menu of host USB
devices, each with a submenu of running VMs for attach/detach.
- vmsilo-device-tray/ Rust crate using ksni + zbus
- Polls sysfs + systemd D-Bus on each menu open (via patched ksni
AboutToShow)
- Breeze/Breeze-dark themed icons rendered at build time from SVGs
- Systemd user service tied to graphical-session.target
- modules/tray.nix for NixOS integration
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sommelier was an experimental alternative to wayland-proxy-virtwl that
never worked well. All VMs now use wayland-proxy-virtwl exclusively.
The waylandProxy.logLevel option remains as it controls
wayland-proxy-virtwl's log verbosity.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
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>
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>
Now that git.dsg.is/dsg/cloud-hypervisor.git has a flake.nix,
use it as a proper flake input with inputs.nixpkgs.follows.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add buildVmsiloWaylandSeccontext build function and expose vmsilo-wayland-seccontext
and cloud-hypervisor (from nixpkgs) as package outputs. Inject both into
_internal module options. Remove nvidiaWeakenSandbox-conditional crosvm selection.
Note: git.dsg.is/dsg/cloud-hypervisor.git has no flake.nix, so cloud-hypervisor
is sourced from nixpkgs instead of a dedicated flake input.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the local package derivation with the one now provided by the
vhost-device flake, removing packages/vhost-device-sound.nix.
Also bump wayland-proxy-virtwl.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move Qt platform theme setup (plasma-integration, breeze, breeze-gtk,
breeze-icons) into the base VM configuration so all guests get consistent
theming out of the box. Previously qt.platformTheme was set in
optionalGuestSettings but qt.enable was never set, so it had no effect.
optionalGuestSettings now only configures dark theme (BreezeDark color
scheme, Breeze-Dark GTK theme, breeze-dark icons) on top of the base.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
xdg-desktop-portal-kde reports color-scheme via org.freedesktop.appearance
by reading QApplication palette colors. Without a KDE dark color scheme in
kdeglobals, the portal reported "prefer-light", overriding the GTK dark
theme settings for Firefox and other apps.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
crosvm changes for realtime audio, plus some minor log message improvements.
Also stop pinning nixpkgs as the upstream build failure has been resolved.
The vm-switch experiment for VM-to-VM networking via vhost-user-net
didn't work out — it performs poorly under load, with busy connections
saturating the buffer and causing high latency for others.
Removes the vm-switch Rust crate, bufferbloat-test suite, all NixOS
module integration (options, services, networking, assertions, scripts),
and documentation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Proxy guest StatusNotifierItems to the host system tray over vsock:5001.
Guest-side watches SNI registrations on D-Bus, collects snapshots
(properties + DBusMenu tree), and streams them to the host. Host-side
creates synthetic SNI items with sanitized data and forwards user
interactions (clicks, scrolls, menu events) back to the guest. Includes
icon theme forwarding, VM color tinting on icon borders, CSS named color
resolution, and automatic service startup with the VM.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements a host-side daemon that equalizes free memory headroom between
host and guests via virtio-balloon, using ChromeOS's BalanceAvailablePolicy.
Includes VM discovery via inotify, crosvm control socket client, stall
detection, NixOS module integration, and CLI argument parsing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
guestConfig now accepts a single module or a list of modules via
coercedTo. Single modules are auto-wrapped in a list for backwards
compatibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allows each VM to choose its Wayland proxy. Defaults to wayland-proxy-virtwl
(existing behavior). Setting waylandProxy = "sommelier" uses the ChromeOS
sommelier compositor instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Nine minimal Wayland client programs to exercise decoration bypass
vectors identified in the security audit. Tests 1-6 cover CSD request,
no-protocol, mode-none, server-decoration-none, fullscreen, and layer
shell. Tests 7-9 add large popup, subsurface overflow, and SSD request
(control). Includes Nix package and dev shell in flake.nix.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two bugs were causing virtio_net TX timeouts in guest VMs:
1. inject_rx_frame used the source VM's memory mapping to access the
destination VM's vring descriptors. Fixed by making inject_rx_frame
a static method that uses the vring's own internal memory via a new
memory() accessor in VringState.
2. handle_event called read_kick() redundantly after the event loop
already consumed the eventfd, potentially blocking on a drained fd.
We temporarily use a local vnet library for debugging.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add VIRTIO_NET_F_STATUS feature flag to advertise link status support
- Set config status byte to VIRTIO_NET_S_LINK_UP (1) so guests see the
link as up instead of down
- Set max_virtqueue_pairs to 1 (was 0, which could confuse guests)
- Update vhost crate hash (upstream change)
This prevents potential issues where guest drivers might see the
interface as disconnected because the status field was returning 0.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements a vhost-user network switch daemon that enables L2 networking
between VMs in the same vmNetwork. The switch uses a router/client
topology where:
- Each network has exactly one router VM
- Client VMs can only communicate through the router
- MAC addresses are discovered via inotify-watched config directory
The daemon implements the vhost-user protocol to provide virtio-net
backends that crosvm connects to via --vhost-user sockets.
Key components:
- vm-switch Rust crate with MAC parsing, frame routing, and vhost-user backend
- NixOS module integration with per-network systemd services
- Automatic daemon startup when VMs are added to a network
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rename `disks` to `additionalDisks` with structured format
(path, readOnly, enableDiscard, blockSize, devIdentifier, useDirect)
- Add custom boot options: rootDisk, kernel, initramfs, rootDiskReadonly
- Add kernelParams for extra kernel command line options
- Add gpu option (default: "context-types=cross-domain:virgl2")
- Add sharedDirectories for crosvm --shared-dir
- Add global crosvmLogLevel option (default: "info")
- Add --name argument to crosvm set to VM name
- Migrate deprecated --disk/--rwdisk to --block format
- Switch flake to nixos-unstable channel
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add treefmt-nix with nixfmt for code formatting (nix fmt)
- Extract cidrToNetworkBase and mkVmCase helper functions
- Use lib.nameValuePair for cleaner listToAttrs patterns
- Consolidate assertions with single let block
- Remove duplicate util-linux package
- Document formatting requirement in CLAUDE.md
- Apply nixfmt to all Nix files
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use my wayland-proxy-virtwl fork. Unconditionally requests server-side
decorations even if the client doesn't want them.
Tested with firefox, works there.
Remove the old s6/execline-based rootfs in favor of the NixOS module approach:
- Delete rootfs/ directory (s6-based rootfs builder)
- Delete mktuntap/ directory (TAP utility, now using --tap-name)
- Delete default.nix (legacy package with vs*/tt*/ff* scripts)
- Update flake.nix to point packages.default to rootfs-nixos
- Update documentation to reflect NixOS-only architecture
The NixOS module (modules/) with socket-activated VMs is now the only
supported approach. VMs are configured declaratively via
programs.qubes-lite.nixosVms.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace the simple guestPrograms-only module with a full declarative
module that allows configuring VMs from configuration.nix:
- programs.qubes-lite.enable, user, vmNetwork, natEnable, natInterface
- programs.qubes-lite.nixosVms list with per-VM config (id, name,
memory, cpus, network, disks, guestPrograms, guestConfig)
- Automatic TAP interface creation via networking.interfaces
- NAT configuration for VM internet access
- Per-VM NixOS rootfs builds with combined packages
- Generated launcher scripts (qubes-lite-start-<name>)
- run-in-vm helper for executing commands via vsock
- Systemd user services for each VM
- Validation: odd IDs 3-255, unique IDs/names