From 4b07cb6b3447dfa59d13b20454f3ec739212e95b Mon Sep 17 00:00:00 2001 From: KoLDXr00T Date: Tue, 20 Oct 2026 20:33:41 +0100 Subject: [PATCH] ci: run the escape suite for firecracker on hosted runners, on every change GitHub's hosted Ubuntu runners expose /dev/kvm, and the firecracker backend needs nothing more than KVM, vsock, podman and crun. escape.yml runs the escape suite there under strict and standard isolation, on every pull request and push to main as well as nightly; each job takes about a minute. Until now the suite ran only on the self-hosted kvm runner, nightly, and that runner has not picked up a job in days. The podman and krun backends need crun built with libkrun, which those runners lack, so security.yml keeps running them on the self-hosted runner. Until #56 lands, box up needs krun on PATH whatever the backend, so the job symlinks krun to crun; the step says to remove that once it does. --- .github/workflows/escape.yml | 64 ++++++++++++++++++++++++++++++++++ .github/workflows/security.yml | 5 +-- SECURITY.md | 9 +++-- 3 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/escape.yml diff --git a/.github/workflows/escape.yml b/.github/workflows/escape.yml new file mode 100644 index 0000000..664d041 --- /dev/null +++ b/.github/workflows/escape.yml @@ -0,0 +1,64 @@ +name: Escape suite (firecracker) + +# The escape suite for the firecracker backend, on GitHub-hosted runners: they +# expose /dev/kvm, and firecracker needs nothing beyond KVM, vsock, podman and +# crun. It takes about a minute, so it runs on every change, not only nightly. +# +# The podman and krun backends need crun built with libkrun, which stock Ubuntu +# does not ship; security.yml still runs them on the self-hosted kvm runner. + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + schedule: + - cron: "41 3 * * *" + +permissions: + contents: read + +jobs: + escape: + runs-on: ubuntu-latest + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + isolation: [strict, standard] + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-go@v7 + with: + go-version-file: go.mod + cache: true + + - name: KVM, vsock and subordinate UIDs for the runner user + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \ + | sudo tee /etc/udev/rules.d/99-kvm.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + sudo modprobe vhost_vsock + sudo chmod 666 /dev/vhost-vsock + # Room for strict mode's UID per sandbox (box doctor's suggestion). + sudo usermod --add-subuids 262144-4456447 --add-subgids 262144-4456447 "$USER" + podman system migrate + command -v crun || sudo apt-get install -y crun + # Until #56 lands, box up wants krun on PATH whatever the backend. + # Remove this then, so the job is a firecracker-only host. + sudo ln -sf "$(command -v crun)" /usr/local/bin/krun + + - name: host + run: | + uname -r + ls -l /dev/kvm /dev/vhost-vsock + podman --version + crun --version | head -1 + + - name: build (static, so it can serve as the guest agent) + run: CGO_ENABLED=0 go build -o box ./cmd/box + + - name: escape tests (firecracker, ${{ matrix.isolation }}) + run: security/escape-test.sh ./box ${{ matrix.isolation }} firecracker diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 19db500..ee21bd2 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -1,7 +1,8 @@ name: Security -# The escape tests boot real microVMs, which needs KVM and libkrun: neither -# exists on the hosted runners. This runs on a self-hosted Linux runner +# The escape tests boot real microVMs. For the podman and krun backends that +# needs libkrun, which the hosted runners lack (escape.yml runs firecracker +# there, on every change). This runs on a self-hosted Linux runner # labelled `kvm` (Fedora with podman, crun +LIBKRUN and the krun symlink), on # demand and nightly, and fails if any escape succeeds under either # isolation mode. diff --git a/SECURITY.md b/SECURITY.md index fdebee8..f340d2a 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -151,9 +151,12 @@ a sandbox, and checks the VMM's confinement from outside: security/escape-test.sh "$(command -v box)" strict ``` -It needs KVM, so it does not run in the hosted CI. `.github/workflows/ -security.yml` runs it on a self-hosted runner labelled `kvm`, and before every -release it is run by hand on a Linux host. +It needs KVM. `.github/workflows/escape.yml` runs it for the firecracker +backend, under both isolation modes, on every change, on GitHub's hosted +runners, which expose KVM. The podman and krun backends need crun built with +libkrun, which those runners lack: `.github/workflows/security.yml` runs them +nightly on a self-hosted runner labelled `kvm`, and before every release the +suite is run by hand on a Linux host. ## Reporting