Repository navigation
Conversation
This commit deletes the entire source code and configuration for: - xenith-cli - xenith-debugger - xenith-domain-management - xenith-gui - xenith-scripting - xenith-vmi
Introduce a new crate to generate randomized hardware identities and corresponding QEMU arguments. This masks hypervisor presence by spoofing CPUID, SMBIOS, ACPI tables, and device IDs to match plausible real-world hardware profiles.
Switch from OsString to String for QEMU argument generation across multiple modules (acpi, cpuid, devices, smbios, timing). This simplifies the API and removes unnecessary imports, as these arguments do not require OS-specific byte representations for current use cases.
Initial implementation of the VM management logic, including: - A generic `VmBackend` trait for hypervisor abstractions. - A QEMU backend with QMP integration for process control. - Configuration management for CPU, memory, disks, and networking. - Support for snapshots, pausing, and graceful power-down.
Replace the string representation of MAC addresses with the structured MacAddr type from the mac-addr crate. This improves type safety and standardizes the handling of hardware identifiers.
Removed several xenith-* members and added xenith-vm and xenith-stealth. Updated the shared workspace dependencies to include tracing, serde, tokio, memflow, gdbstub, and pyo3. The Cargo.lock changes reflect these dependency updates and the underlying crate graph shifts.
Implement a template-driven system for generating coherent hardware profiles using a new `templates.yaml` file. This replaces hardcoded values with a pool of real-world CPU, board, and NIC OUI data. - Add `serde_yml` dependency for template parsing - Implement `PlatformTemplate`, `CpuTemplate`, and `BoardTemplate` - Update `StealthConfig` and `HardwareProfile` to use templates - Refactor error handling and module exports - Temporary disable ACPI OEM overrides pending binary blob support
Include serde_yml v0.0.12 and its required sub-dependencies to the project configuration and lockfile.
- Make struct fields private across `VmConfig`, `DiskImage`, and `Snapshot`. - Add accessor methods and builders for configuration and state. - Transition `VmConfig` and `DiskImage` operations to use `tokio` for async I/O. - Rename `VmError` to `Error` and update variants to use named fields. - Add a `prelude` module and expand public exports in `lib.rs`. - Introduce unit tests for configuration and disk helpers.
Add multiple Intel Corporate OUIs and update vendor names for Realtek and Micro-Star to improve template authenticity.
The commit adds extensive test coverage across the `xenith-stealth` and `xenith-vm` crates. This includes unit tests for ACPI, CPUID, SMBIOS, and device configuration logic, as well as integration tests for VM lifecycle management, configuration serialization, and QEMU argument generation.
Apply consistent code formatting across multiple files, reorder imports for better organization, and relocate helper functions in qemu.rs to improve readability.
- Move `-no-kvmclock` from a top-level argument to a `-cpu` feature flag. - Add `smbios_safe` helper to strip commas from SMBIOS values, preventing QEMU parsing errors. - Update tests and integration logic to reflect new argument ordering and counts. - Add a new `boot` example to `xenith-vm` for launching VMs with stealth profiles. - Improve QEMU error reporting by capturing stderr on failure.
| let known: Vec<[u8; 3]> = ouis().iter().map(|o| o.bytes()).collect(); | ||
| let p = HardwareProfile::generate(); | ||
| let oui = p.mac_address().oui(); | ||
| assert!( |
There was a problem hiding this comment.
Pull request overview
This PR restructures the Rust workspace by removing several legacy crates (CLI / GUI / libvirt-based domain management / VMI stub / scripting / debugger) and introducing a new QEMU-centric VM lifecycle crate plus a new stealth-configuration crate.
Changes:
- Removed
xenith-cli,xenith-domain-management,xenith-debugger,xenith-scripting,xenith-gui, andxenith-vmifrom the workspace and deleted their sources. - Added
xenith-vm(VM config + QEMU backend + QMP control + snapshot operations) with examples and tests. - Added
xenith-stealth(hardware profile generation + CPUID/SMBIOS/device argument builders) with templates and tests, and updated root workspace deps /Cargo.lock.
Reviewed changes
Copilot reviewed 61 out of 62 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| Cargo.toml | Updates workspace members and expands shared workspace dependencies. |
| Cargo.lock | Lockfile update reflecting removed crates and new dependencies (tokio/tracing/qapi/rand/etc.). |
| xenith-vmi/Cargo.toml | Removes the xenith-vmi crate manifest from the repo/workspace. |
| xenith-vmi/src/lib.rs | Removes the xenith-vmi stub library code. |
| xenith-vm/Cargo.toml | Adds the new xenith-vm crate manifest and dependencies (tokio/qapi/etc.). |
| xenith-vm/src/lib.rs | Introduces the xenith-vm public module structure and re-exports. |
| xenith-vm/src/backend.rs | Defines the VmBackend trait abstraction for VM backends. |
| xenith-vm/src/backend/qemu.rs | Implements a QEMU backend: arg building, QMP control, snapshot job polling, pidfile handling. |
| xenith-vm/src/config.rs | Adds VmConfig and NetworkInterface plus TOML load/save and path helpers. |
| xenith-vm/src/disk.rs | Adds DiskImage/DiskFormat and qemu-img create/resize/delete helpers. |
| xenith-vm/src/display.rs | Adds DisplayMode with serde support for config serialization. |
| xenith-vm/src/error.rs | Defines xenith-vm error types and messages. |
| xenith-vm/src/snapshot.rs | Adds the Snapshot value type. |
| xenith-vm/src/vm.rs | Adds the high-level Vm manager wrapper around a backend + config + pid state. |
| xenith-vm/tests/integration.rs | Adds integration tests for config/disk/network/display/snapshot types and TOML round-trips. |
| xenith-vm/examples/boot.rs | Adds an example that launches QEMU using xenith-vm plus xenith-stealth extra args. |
| xenith-stealth/Cargo.toml | Adds the new xenith-stealth crate manifest and dependencies (rand/serde_yml/mac-addr). |
| xenith-stealth/src/lib.rs | Introduces the xenith-stealth module structure and re-exports. |
| xenith-stealth/src/builder.rs | Implements StealthConfig to build a composed QEMU arg list. |
| xenith-stealth/src/profile.rs | Implements random coherent hardware profile generation from YAML templates. |
| xenith-stealth/src/cpuid.rs | Builds -cpu arg with feature flags to hide hypervisor signals. |
| xenith-stealth/src/smbios.rs | Builds -smbios args and sanitizes comma-containing values. |
| xenith-stealth/src/devices.rs | Adds additional QEMU -device args (USB controller/tablet) to reduce detectability. |
| xenith-stealth/src/acpi.rs | Placeholder for future ACPI spoofing args (currently empty). |
| xenith-stealth/src/timing.rs | Placeholder for future timing args (currently empty). |
| xenith-stealth/src/error.rs | Adds stealth-layer error types. |
| xenith-stealth/templates.yaml | Adds the hardware identity template data (OUIs + platforms/boards/CPUs). |
| xenith-stealth/tests/integration.rs | Adds integration tests validating stealth arg properties and coherence. |
| xenith-scripting/Cargo.toml | Removes the xenith-scripting crate manifest. |
| xenith-scripting/src/lib.rs | Removes the xenith-scripting crate source. |
| xenith-debugger/Cargo.toml | Removes the xenith-debugger crate manifest. |
| xenith-debugger/src/lib.rs | Removes the xenith-debugger crate source. |
| xenith-cli/Cargo.toml | Removes the xenith-cli crate manifest. |
| xenith-cli/src/main.rs | Removes the old CLI entrypoint. |
| xenith-cli/src/commands.rs | Removes old CLI command routing. |
| xenith-cli/src/commands/vm.rs | Removes old VM subcommand handling. |
| xenith-gui/Cargo.toml | Removes the xenith-gui crate manifest. |
| xenith-gui/src/main.rs | Removes the xenith-gui binary stub. |
| xenith-domain-management/Cargo.toml | Removes the libvirt/Xen domain management crate manifest. |
| xenith-domain-management/build.rs | Removes the libvirt link directive build script. |
| xenith-domain-management/src/main.rs | Removes the libvirt exploration binary. |
| xenith-domain-management/src/lib.rs | Removes the old domain management library entrypoint. |
| xenith-domain-management/src/templating.rs | Removes the Tera-based XML domain templating implementation. |
| xenith-domain-management/src/error.rs | Removes old driver/config error definitions. |
| xenith-domain-management/src/driver.rs | Removes libvirt driver implementation. |
| xenith-domain-management/src/driver/identifier.rs | Removes domain identifier types. |
| xenith-domain-management/src/driver/status.rs | Removes domain status mapping. |
| xenith-domain-management/src/domain.rs | Removes domain model module. |
| xenith-domain-management/src/domain/devices.rs | Removes domain device modeling. |
| xenith-domain-management/src/domain/events.rs | Removes domain event/action modeling. |
| xenith-domain-management/src/domain/network.rs | Removes domain network modeling. |
| xenith-domain-management/src/domain/processor.rs | Removes SMBIOS/processor modeling. |
| xenith-domain-management/src/domain/time.rs | Removes TSC/time modeling. |
| xenith-domain-management/src/configuration.rs | Removes domain configuration filesystem model. |
| xenith-domain-management/src/configuration/domain.rs | Removes domain config parsing. |
| xenith-domain-management/src/configuration/disk.rs | Removes disk config parsing/model. |
| xenith-domain-management/src/configuration/image.rs | Removes image config model. |
| xenith-domain-management/src/configuration/template.rs | Removes packer template model. |
| xenith-domain-management/templates/default.xml | Removes the default XML template. |
| xenith-domain-management/tests/fixtures/default.xml | Removes XML fixture. |
| xenith-domain-management/tests/fixtures/default-config.cfg | Removes legacy cfg fixture. |
| xenith-redpill/xenith-redpill-macros/src/technique.rs | Minor formatting fix in macro error-return block. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| #[test] | ||
| fn display_sdl_adds_display_sdl() { | ||
| // VmConfig has no `with_display`, so inject via TOML round-trip. | ||
| let toml = format!( | ||
| "name = \"argtest\"\nvcpus = 4\nmemory_bytes = {}\ndisks = []\nnetworks = []\ndisplay = \"sdl\"\n", | ||
| VmConfig::gib_to_bytes(8) | ||
| ); | ||
| let cfg: VmConfig = toml::from_str(&toml).expect("parse"); | ||
| let args = args_str(&cfg); |
There was a problem hiding this comment.
The comment claims VmConfig has no with_display, but VmConfig::with_display exists now (xenith-vm/src/config.rs). This is misleading and should be updated; the test can construct the config via with_display(DisplayMode::Sdl) instead of relying on a TOML round-trip.
| #[test] | ||
| fn vm_config_runtime_paths_are_nested_under_base_dir() { | ||
| // SAFETY: single-threaded test process; no other thread reads XENITH_VM_DIR. | ||
| unsafe { std::env::set_var("XENITH_VM_DIR", "/tmp/xenith-test") }; | ||
| let cfg = make_config("path-test"); | ||
| assert!(cfg.runtime_dir().starts_with("/tmp/xenith-test")); | ||
| assert!(cfg.qmp_socket().starts_with("/tmp/xenith-test")); | ||
| assert!(cfg.config_file().starts_with("/tmp/xenith-test")); | ||
| unsafe { std::env::remove_var("XENITH_VM_DIR") }; | ||
| } |
There was a problem hiding this comment.
This test mutates the process-wide XENITH_VM_DIR environment variable. Rust tests run in parallel by default, so this can race with other tests and become flaky; the safety comment about being single-threaded is not guaranteed. Consider guarding env var mutation with a global mutex / serializing the test, and restore any previous value on exit (even on panic).
| pub async fn stop(&mut self) -> Result<(), VmError> { | ||
| self.ensure_running()?; | ||
| self.backend.stop(&self.config).await?; | ||
| self.pid = None; | ||
| info!("VM stopped"); | ||
| Ok(()) |
There was a problem hiding this comment.
Vm::stop clears self.pid and logs "VM stopped" immediately after calling backend.stop, but QemuBackend::stop only issues an ACPI powerdown over QMP and does not wait for the VM to actually exit. This can leave Vm thinking it is stopped while the process (and QMP socket/pidfile) is still alive, enabling inconsistent follow-up calls (including a new start). Consider either waiting for shutdown/exit before clearing pid, or renaming/adjusting the API so it reflects "powerdown requested" semantics.
| async fn save_snapshot(&self, config: &VmConfig, tag: &str) -> Result<(), VmError> { | ||
| let qmp = qmp_connect(config).await?; | ||
| let job_id = format!("snap-save-{tag}"); | ||
| qmp.execute(qapi::qmp::snapshot_save { | ||
| job_id: job_id.clone(), | ||
| tag: tag.to_owned(), | ||
| vmstate: String::from("drive0"), | ||
| devices: config.drive_ids(), | ||
| }) |
There was a problem hiding this comment.
Snapshot operations hard-code vmstate = "drive0" but pass devices = config.drive_ids(). If no disks are configured, drive_ids() is empty and drive0 won't exist, causing a QMP error at runtime. Consider validating that at least one disk is attached (or making vmstate/devices derive from the actual configured drives) and returning a clear VmError::Config/VmError::Disk early.
| async fn read_pid_file(path: &Path) -> Result<u32, VmError> { | ||
| let mut attempts = 0u8; | ||
| let pid_str = loop { | ||
| match fs::read_to_string(path) { | ||
| Ok(s) => break s, | ||
| Err(_) if attempts < 5 => { | ||
| attempts += 1; | ||
| tokio::time::sleep(Duration::from_millis(50)).await; | ||
| } | ||
| Err(e) => return Err(VmError::Backend(format!("could not read pidfile: {e}"))), | ||
| } |
There was a problem hiding this comment.
read_pid_file is async but uses blocking std::fs::read_to_string inside a retry loop. On a Tokio runtime this can block the executor thread and impact unrelated async tasks. Prefer tokio::fs::read_to_string (or spawn_blocking) for the pidfile read, keeping the retry/sleep logic the same.
| /// A disk image on the host that will be attached to a VM. | ||
| #[derive(Debug, Clone, Serialize, Deserialize)] | ||
| pub struct DiskImage { | ||
| path: PathBuf, | ||
| format: DiskFormat, | ||
| /// Capacity in bytes. | ||
| size_bytes: u64, | ||
| } |
There was a problem hiding this comment.
DiskImage has private fields and no public constructor for representing an existing disk, which forces tests/examples in this PR to construct instances via a TOML/serde round-trip. Consider adding a simple DiskImage::new(...) / DiskImage::from_existing(...) constructor to make the API ergonomic and avoid serialization hacks.
| let pid = vm.pid().expect("PID set after start"); | ||
| println!("VM started (PID {pid})"); | ||
| println!("QMP socket: {}", vm.config().qmp_socket().display()); | ||
| println!("Stop with: xenith-vm stop {}", vm.config().name()); | ||
| } |
There was a problem hiding this comment.
The example prints Stop with: xenith-vm stop ..., but this workspace no longer includes a xenith-vm CLI/binary (the crate is a library with examples). This message will confuse users running the example; consider changing it to describe the actual stop mechanism (e.g., call vm.stop() from code, or document the intended future CLI if that's planned).
| members = [ | ||
| "xenith-domain-management", | ||
| "xenith-vmi", | ||
| "xenith-cli", | ||
| "xenith-debugger", | ||
| "xenith-scripting", | ||
| "xenith-vm", | ||
| "xenith-stealth", | ||
| "xenith-redpill", | ||
| "xenith-gui", | ||
| ] |
There was a problem hiding this comment.
PR description emphasizes removing crates/dependencies, but this change also adds new workspace members (xenith-vm, xenith-stealth) and introduces a large set of new shared dependencies. Consider updating the PR description to reflect the scope (cleanup + new VM/stealth crates) so reviewers understand the intent.
| vec![ | ||
| // USB controller: Intel Panther Point xHCI (very common on 3rd-gen Intel boards) | ||
| String::from("-device"), | ||
| String::from("qemu-xhci,id=usb,p2=15,p3=15"), | ||
| // USB HID tablet (prevents relative-mouse issues; looks like a real USB device) |
There was a problem hiding this comment.
The comment claims the qemu-xhci device corresponds to an "Intel Panther Point xHCI" controller, but the argument being added is qemu-xhci (QEMU's generic xHCI controller). This is misleading documentation; either adjust the device/model to match the stated hardware, or update the comment to describe what is actually being emulated.
| # took from https://udger.com/resources/mac-address-vendor-detail?name=intel_corporation | ||
| - vendor: Intel Corporate | ||
| oui: "00:02:B3" | ||
| - vendor: Intel Corporate | ||
| oui: "00:03:47" | ||
| - vendor: Intel Corporate | ||
| oui: "00:04:23" | ||
| - vendor: Intel Corporate |
There was a problem hiding this comment.
Minor: # took from ... should be # taken from ..., and there is trailing whitespace after the 00:04:23 OUI entry. Cleaning this up avoids small documentation/style issues in the templates file.
This pull request removes several components and dependencies from the workspace, primarily cleaning up the codebase by deleting the
xenith-cli,xenith-domain-management, andxenith-debuggercrates and their source files. It also updates the workspace membership and shared dependencies in the rootCargo.toml. The main focus is on streamlining the project by eliminating unused or deprecated modules and their associated files.Workspace and Dependency Cleanup:
xenith-cli,xenith-domain-management, andxenith-debuggercrates from the workspace and deleted theirCargo.tomland all Rust source files, including command handlers and configuration modules. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]Dependency updates:
Cargo.tomlby adding several new libraries such asmac-addr,tracing,serde,serde_json,serde_yml,tokio,memflow,memflow-qemu,gdbstub,gdbstub_arch, andpyo3.These changes help simplify the project structure and prepare the workspace for future development by focusing only on the currently relevant components.