#!/usr/bin/env bash # Boot the Cirros qcow2 under KVM with QMP and a monitor socket exposed. # # This is the v0 VM launcher for phase 2: validate that the orchestrator # and host /proc collector work against a real qemu-system process. No # host-only bridge yet, no exploit driver, no payload — just boot and # idle. We add the bridge and exploit machinery in later phases. # # Run dir is exported so the orchestrator can read the qemu pid: # $RUN_DIR/qemu.pid # $RUN_DIR/qmp.sock # $RUN_DIR/monitor.sock set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" IMAGE="${IMAGE:-$REPO_ROOT/vm/images/alpine-baseline.qcow2}" CIDATA="${CIDATA:-$REPO_ROOT/vm/images/cidata.iso}" RUN_DIR="${RUN_DIR:-/tmp/cis490-vm}" mkdir -p "$RUN_DIR" QMP_SOCK="$RUN_DIR/qmp.sock" MON_SOCK="$RUN_DIR/monitor.sock" PID_FILE="$RUN_DIR/qemu.pid" if [[ ! -f "$IMAGE" ]]; then echo "no image at $IMAGE" >&2 exit 1 fi if [[ ! -f "$CIDATA" ]]; then echo "no cidata at $CIDATA — build it with: uv run python tools/build_cidata.py $CIDATA" >&2 exit 1 fi # snapshot=on routes guest writes through a temporary overlay so the qcow2 # on disk is never mutated — every boot starts from the same bytes. exec qemu-system-x86_64 \ -name cis490-vm \ -machine q35,accel=kvm \ -cpu host \ -smp 1,sockets=1,cores=1,threads=1 \ -m 256 \ -drive file="$IMAGE",format=qcow2,if=virtio,snapshot=on \ -drive file="$CIDATA",format=raw,if=virtio,readonly=on \ -netdev user,id=n0,hostfwd=tcp:127.0.0.1:2222-:22 \ -device virtio-net-pci,netdev=n0 \ -nographic \ -serial unix:"$RUN_DIR/serial.sock",server=on,wait=off \ -monitor unix:"$MON_SOCK",server=on,wait=off \ -qmp unix:"$QMP_SOCK",server=on,wait=off \ -pidfile "$PID_FILE" \ -display none