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