vmsilo/flake.nix
Davíð Steinn Geirsson 869abed1b0 fix(dbus-proxy): harden fuzz-clean-dbus-proxy against build failures and hangs
- 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>
2026-03-25 22:05:46 +00:00

402 lines
13 KiB
Nix

{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
wayland-proxy-virtwl = {
url = "git+https://git.dsg.is/dsg/wayland-proxy-virtwl.git?submodules=1";
inputs.nixpkgs.follows = "nixpkgs";
};
crosvm = {
url = "git+https://git.dsg.is/dsg/crosvm.git?ref=vmsilo&submodules=1";
inputs.nixpkgs.follows = "nixpkgs";
};
vhost-device = {
url = "git+https://git.dsg.is/dsg/vhost-device.git";
inputs.nixpkgs.follows = "nixpkgs";
};
cloud-hypervisor = {
url = "git+https://git.dsg.is/dsg/cloud-hypervisor.git";
inputs.nixpkgs.follows = "nixpkgs";
};
usbip-rs = {
url = "git+https://git.dsg.is/dsg/usbip-rs.git";
inputs.nixpkgs.follows = "nixpkgs";
};
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
self,
nixpkgs,
wayland-proxy-virtwl,
crosvm,
vhost-device,
cloud-hypervisor,
usbip-rs,
treefmt-nix,
rust-overlay,
}:
let
usbip-rs-input = usbip-rs;
eachSystem = nixpkgs.lib.genAttrs [
"x86_64-linux"
"aarch64-linux"
];
# Build NixOS-based rootfs as qcow2 image
makeRootfsNixos =
system:
{
guestPrograms ? [ ],
guestConfig ? [ ],
usbip-rs ? usbip-rs-input.packages.${system}.default,
}:
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.callPackage (import ./rootfs-nixos) {
inherit guestPrograms guestConfig usbip-rs;
wayland-proxy-virtwl = wayland-proxy-virtwl.packages.${system}.default;
};
# Build vmsilo-balloond Rust binary
buildVmsiloBalloond =
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.rustPlatform.buildRustPackage {
pname = "vmsilo-balloond";
version = "0.1.0";
src = ./vmsilo-balloond;
cargoLock = {
lockFile = ./vmsilo-balloond/Cargo.lock;
};
};
# Build vmsilo-dbus-proxy Rust binaries
buildVmsiloDbusProxy =
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.rustPlatform.buildRustPackage {
pname = "vmsilo-dbus-proxy";
version = "0.1.0";
src = ./vmsilo-dbus-proxy;
cargoLock = {
lockFile = ./vmsilo-dbus-proxy/Cargo.lock;
};
};
# Build vmsilo-wayland-seccontext Rust binary
buildVmsiloWaylandSeccontext =
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.rustPlatform.buildRustPackage {
pname = "vmsilo-wayland-seccontext";
version = "0.1.0";
src = ./vmsilo-wayland-seccontext;
cargoLock = {
lockFile = ./vmsilo-wayland-seccontext/Cargo.lock;
};
nativeBuildInputs = with pkgs; [ pkg-config ];
buildInputs = with pkgs; [ wayland ];
};
# Build vmsilo-tools workspace
buildVmsiloTools =
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.rustPlatform.buildRustPackage {
pname = "vmsilo-tools";
version = "0.1.0";
src = ./vmsilo-tools;
cargoLock = {
lockFile = ./vmsilo-tools/Cargo.lock;
};
};
# Build vmsilo-device-tray
buildVmsiloDeviceTray =
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.callPackage ./vmsilo-device-tray/package.nix {
ksniPatch = ./patches/ksni-about-to-show-refresh.patch;
};
# treefmt configuration
treefmtConfig = {
projectRootFile = "flake.nix";
programs.nixfmt.enable = true;
};
in
{
formatter = eachSystem (
system:
(treefmt-nix.lib.evalModule nixpkgs.legacyPackages.${system} treefmtConfig).config.build.wrapper
);
packages = eachSystem (system: {
default = makeRootfsNixos system { };
rootfs-nixos = makeRootfsNixos system { };
vmsilo-balloond = buildVmsiloBalloond system;
vmsilo-dbus-proxy = buildVmsiloDbusProxy system;
vmsilo-wayland-seccontext = buildVmsiloWaylandSeccontext system;
vmsilo-tools = buildVmsiloTools system;
vmsilo-device-tray = buildVmsiloDeviceTray system;
"cloud-hypervisor" = cloud-hypervisor.packages.${system}.cloud-hypervisor;
decoration-tests =
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.stdenv.mkDerivation {
pname = "decoration-tests";
version = "0.1.0";
src = ./wayland_decoration_tests;
nativeBuildInputs = with pkgs; [
wayland-scanner
pkg-config
];
buildInputs = [ pkgs.wayland ];
makeFlags = [
"WAYLAND_PROTOCOLS=${pkgs.wayland-protocols}/share/wayland-protocols"
"PLASMA_WAYLAND_PROTOCOLS=${pkgs.kdePackages.plasma-wayland-protocols}/share/plasma-wayland-protocols"
"WLR_PROTOCOLS=${pkgs.wlr-protocols}/share/wlr-protocols"
];
installPhase = ''
mkdir -p $out/bin
cp test-csd-request test-no-decoration-protocol test-mode-none test-server-decoration-none test-fullscreen test-layer-shell test-large-popup test-subsurface-overflow test-ssd-request $out/bin/
'';
};
});
devShells = eachSystem (system: {
default =
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.mkShell {
buildInputs = with pkgs; [
# Rust toolchain
cargo
rustc
rust-analyzer
rustfmt
clippy
# Build dependencies
pkg-config
];
RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
};
decoration-tests =
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.mkShell {
buildInputs = with pkgs; [
wayland
wayland-protocols
kdePackages.plasma-wayland-protocols
wlr-protocols
wayland-scanner
pkg-config
gcc
];
WAYLAND_PROTOCOLS = "${pkgs.wayland-protocols}/share/wayland-protocols";
PLASMA_WAYLAND_PROTOCOLS = "${pkgs.kdePackages.plasma-wayland-protocols}/share/plasma-wayland-protocols";
WLR_PROTOCOLS = "${pkgs.wlr-protocols}/share/wlr-protocols";
};
fuzz =
let
pkgs = nixpkgs.legacyPackages.${system};
rust-nightly = rust-overlay.packages.${system}.rust-nightly;
in
pkgs.mkShell {
buildInputs = [
rust-nightly
pkgs.cargo-fuzz
];
nativeBuildInputs = [ pkgs.stdenv.cc ];
};
});
apps = eachSystem (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
rust-nightly = rust-overlay.packages.${system}.rust-nightly;
fuzz-dbus-proxy = pkgs.writeShellScriptBin "fuzz-dbus-proxy" ''
set -euo pipefail
export PATH="${rust-nightly}/bin:${pkgs.cargo-fuzz}/bin:${pkgs.stdenv.cc}/bin:$PATH"
cd "$(${pkgs.git}/bin/git rev-parse --show-toplevel)/vmsilo-dbus-proxy"
if [ $# -eq 0 ]; then
cargo fuzz list
else
target="$1"
shift
fork=0
args=()
for arg in "$@"; do
case "$arg" in
--fork=*) fork=''${arg#--fork=} ;;
*) args+=("$arg") ;;
esac
done
if [ "$fork" -gt 0 ]; then
while true; do
cargo fuzz run "$target" -- -max_len=1048576 "-fork=$fork" "''${args[@]}" || true
echo "--- fuzzer exited, restarting (artifacts saved) ---"
done
else
cargo fuzz run "$target" -- -max_len=1048576 "''${args[@]}"
fi
fi
'';
fuzz-clean-dbus-proxy = pkgs.writeShellScriptBin "fuzz-clean-dbus-proxy" ''
set -euo pipefail
export PATH="${rust-nightly}/bin:${pkgs.cargo-fuzz}/bin:${pkgs.stdenv.cc}/bin:${pkgs.coreutils}/bin:$PATH"
cd "$(${pkgs.git}/bin/git rev-parse --show-toplevel)/vmsilo-dbus-proxy"
if [ $# -eq 0 ]; then
echo "Usage: fuzz-clean-dbus-proxy <target>"
echo "Available targets:"
cargo fuzz list
exit 1
fi
target="$1"
dir="fuzz/artifacts/$target"
if [ ! -d "$dir" ]; then
echo "No artifacts directory: $dir"
exit 0
fi
shopt -s nullglob
files=("$dir"/crash-* "$dir"/oom-* "$dir"/timeout-*)
if [ ''${#files[@]} -eq 0 ]; then
echo "No artifacts to test."
exit 0
fi
echo "Building $target..."
if ! cargo fuzz build "$target" 2>&1; then
echo "Build failed not touching artifacts."
exit 1
fi
echo "Testing ''${#files[@]} artifacts for $target..."
removed=0
kept=0
for f in "''${files[@]}"; do
if timeout 30 cargo fuzz run "$target" "$f" -- -max_len=1048576 >/dev/null 2>&1; then
rm "$f"
removed=$((removed + 1))
else
kept=$((kept + 1))
fi
echo -ne "\r tested $((removed + kept))/''${#files[@]}, removed $removed, kept $kept"
done
echo ""
echo "Done: removed $removed fixed, kept $kept still-crashing."
'';
in
{
fuzz-dbus-proxy = {
type = "app";
program = "${fuzz-dbus-proxy}/bin/fuzz-dbus-proxy";
};
fuzz-clean-dbus-proxy = {
type = "app";
program = "${fuzz-clean-dbus-proxy}/bin/fuzz-clean-dbus-proxy";
};
}
);
# Helper function for building custom NixOS rootfs
lib.makeRootfsNixos = makeRootfsNixos;
nixosModules.default =
{
config,
pkgs,
lib,
...
}:
{
imports = [ ./modules ];
# Inject dependencies when module is enabled
config = lib.mkIf config.programs.vmsilo.enable {
programs.vmsilo._internal = {
crosvm = crosvm.packages.${pkgs.stdenv.hostPlatform.system}.default;
"cloud-hypervisor" = cloud-hypervisor.packages.${pkgs.stdenv.hostPlatform.system}.cloud-hypervisor;
vmsilo-wayland-seccontext = buildVmsiloWaylandSeccontext pkgs.stdenv.hostPlatform.system;
wayland-proxy-virtwl = wayland-proxy-virtwl.packages.${pkgs.stdenv.hostPlatform.system}.default;
vhost-device-sound = vhost-device.packages.${pkgs.stdenv.hostPlatform.system}.vhost-device-sound;
vhost-device-gpu = vhost-device.packages.${pkgs.stdenv.hostPlatform.system}.vhost-device-gpu;
vmsilo-balloond = buildVmsiloBalloond pkgs.stdenv.hostPlatform.system;
vmsilo-dbus-proxy = buildVmsiloDbusProxy pkgs.stdenv.hostPlatform.system;
vmsilo-tools = buildVmsiloTools pkgs.stdenv.hostPlatform.system;
"usbip-rs" = usbip-rs-input.packages.${pkgs.stdenv.hostPlatform.system}.default;
"vmsilo-device-tray" = buildVmsiloDeviceTray pkgs.stdenv.hostPlatform.system;
};
};
};
nixosModules.optionalGuestSettings =
# Dark Breeze theme for Qt and GTK apps. Not used by default.
{
config,
pkgs,
lib,
...
}:
{
config = {
environment.etc."xdg/gtk-3.0/settings.ini".text = ''
[Settings]
gtk-theme-name=Breeze-Dark
gtk-application-prefer-dark-theme=true
'';
environment.etc."xdg/gtk-4.0/settings.ini".text = ''
[Settings]
gtk-theme-name=Breeze-Dark
gtk-application-prefer-dark-theme=true
'';
# plasma-integration reads kdeglobals for color scheme and style.
# xdg-desktop-portal-kde reads Colors:Window BackgroundNormal to
# report org.freedesktop.appearance color-scheme preference.
environment.etc."xdg/kdeglobals".text = ''
[General]
ColorScheme=BreezeDark
widgetStyle=breeze
[Icons]
Theme=breeze-dark
[KDE]
widgetStyle=breeze
[Colors:Window]
BackgroundNormal=32,35,38
'';
};
};
};
}