From e389be5218c2fcc44a5ca28a2842e8a31d9bd01d Mon Sep 17 00:00:00 2001 From: ErenAri Date: Sun, 14 Jun 2026 16:26:16 +0300 Subject: [PATCH 1/3] Soften hosted-runner README claim; make the gate debuggable The first real hosted-runner run confirmed /dev/kvm is present but every VM errored on 'wait for SSH ... context deadline exceeded' (guest boots but never becomes reachable). Soften the README to not overclaim, and instrument the workflow to diagnose: - README: hosted lane framed as wired + KVM-confirmed but boot still being stabilized; self-hosted KVM is the validated path today. - chmod 0666 /dev/kvm safeguard (runner user may not be in the kvm group). - timeout 12m -> 5m so a stuck guest fails fast instead of burning the budget. - on failure, dump serial.log/validator output into the job log; upload the whole .bpfcompat/runs tree as an artifact. Co-Authored-By: Claude Opus 4.8 --- .../workflows/bpfcompat-example-hosted.yml | 23 +++++++++++++++---- README.md | 17 +++++++++----- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/.github/workflows/bpfcompat-example-hosted.yml b/.github/workflows/bpfcompat-example-hosted.yml index 95c9e010..76cf822d 100644 --- a/.github/workflows/bpfcompat-example-hosted.yml +++ b/.github/workflows/bpfcompat-example-hosted.yml @@ -41,6 +41,10 @@ jobs: set -euo pipefail if [[ -e /dev/kvm ]]; then echo "::notice::/dev/kvm present - VM validation is hardware-accelerated." + # Some hosted images expose /dev/kvm but the runner user is not in + # the kvm group; loosen perms so QEMU can open it. + sudo chmod 0666 /dev/kvm || true + ls -l /dev/kvm || true else echo "::warning::/dev/kvm not found - falling back to TCG software emulation (slower, still correct)." fi @@ -73,10 +77,22 @@ jobs: suite: suites/dev-functional.yaml suite-out: reports/ci-dev-functional-suite.json suite-markdown: reports/ci-dev-functional-suite.md - timeout: 12m + # Short while we stabilize hosted-runner guest boot: a stuck VM fails + # in ~5m instead of burning the full budget on the SSH-ready wait. + timeout: 5m concurrency: "1" build: "true" + - name: Dump guest serial + validator output on failure + if: failure() + shell: bash + run: | + echo "===== /dev/kvm ====="; ls -l /dev/kvm || true + for f in $(find .bpfcompat -type f \( -name serial.log -o -name validator.stderr -o -name validator-result.json \) 2>/dev/null); do + echo "===== $f =====" + tail -n 120 "$f" || true + done + - name: Upload reports if: always() uses: actions/upload-artifact@v4 @@ -88,7 +104,4 @@ jobs: reports/ci-dev-functional-suite.md reports/suites/dev-functional/*.json reports/suites/dev-functional/*.md - .bpfcompat/runs/**/targets/**/serial.log - .bpfcompat/runs/**/targets/**/libbpf.log - .bpfcompat/runs/**/targets/**/validator-result.json - .bpfcompat/runs/**/targets/**/validator.stderr + .bpfcompat/runs/** diff --git a/README.md b/README.md index 6056d48a..38a1c503 100644 --- a/README.md +++ b/README.md @@ -28,14 +28,19 @@ CO-RE makes a `.bpf.o` *portable in principle*; it does not guarantee it will `bpfcompat` answers the empirical question CO-RE leaves open: *does it actually load and attach here?* — by running the artifact in a real kernel. -## Try it in CI — no self-hosted runner +## Try it in CI without your own KVM box -GitHub-hosted Linux runners now expose `/dev/kvm`, so the full QEMU VM -compatibility gate runs on a stock `ubuntu-latest` runner. No KVM box of your -own, no self-hosted runner. See +GitHub-hosted Linux runners now expose `/dev/kvm`, so the QEMU VM lane can run +on a stock `ubuntu-latest` runner instead of requiring a self-hosted KVM +machine. See [`.github/workflows/bpfcompat-example-hosted.yml`](.github/workflows/bpfcompat-example-hosted.yml) -for a copy-paste workflow; if a runner ever lacks KVM, validation degrades to -TCG software emulation (correct, just slower) instead of failing. +for a copy-paste workflow; if a runner lacks KVM, validation degrades to TCG +software emulation (correct, just slower) instead of failing. + +> **Status:** the hosted-runner lane is wired and KVM is confirmed available on +> `ubuntu-latest`, but end-to-end guest boot on hosted runners is still being +> stabilized (tracking a cloud-init/SSH-readiness timeout). Self-hosted KVM +> remains the validated path today; see issue tracker for hosted-runner status. ## Proof: a real Falco probe catches a real regression From c0c8fe7563f3bbdb616304e7aea1ab2757ff7a0e Mon Sep 17 00:00:00 2001 From: ErenAri Date: Sun, 14 Jun 2026 16:29:07 +0300 Subject: [PATCH 2/3] chmod /dev/kvm fixes the hosted gate; README now claims proven pass The kvm-perms safeguard was the fix: the runner user couldn't open /dev/kvm, so -enable-kvm failed and the guest never booted (the SSH-readiness timeout). With chmod 0666 the hosted gate passes end-to-end in ~1m46s (simple-pass + functional-execve both pass, KVM hardware-accelerated). README updated from 'being stabilized' to proven, with the kvm-group gotcha documented. Co-Authored-By: Claude Opus 4.8 --- README.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 38a1c503..4c93e8e7 100644 --- a/README.md +++ b/README.md @@ -30,17 +30,18 @@ load and attach here?* — by running the artifact in a real kernel. ## Try it in CI without your own KVM box -GitHub-hosted Linux runners now expose `/dev/kvm`, so the QEMU VM lane can run -on a stock `ubuntu-latest` runner instead of requiring a self-hosted KVM -machine. See +GitHub-hosted Linux runners now expose `/dev/kvm`, so the full QEMU VM +compatibility gate runs on a stock `ubuntu-latest` runner — no self-hosted KVM +machine required. This is proven end-to-end: [`.github/workflows/bpfcompat-example-hosted.yml`](.github/workflows/bpfcompat-example-hosted.yml) -for a copy-paste workflow; if a runner lacks KVM, validation degrades to TCG -software emulation (correct, just slower) instead of failing. - -> **Status:** the hosted-runner lane is wired and KVM is confirmed available on -> `ubuntu-latest`, but end-to-end guest boot on hosted runners is still being -> stabilized (tracking a cloud-init/SSH-readiness timeout). Self-hosted KVM -> remains the validated path today; see issue tracker for hosted-runner status. +boots a disposable VM and runs the `dev-functional` suite (load + behavioral +execve) in **under two minutes**. + +One gotcha: some hosted images expose `/dev/kvm` but the runner user isn't in +the `kvm` group, so QEMU can't open it. The example workflow runs +`sudo chmod 0666 /dev/kvm` to handle that. If a runner genuinely lacks KVM, +validation degrades to TCG software emulation (correct, just slower) instead of +failing. ## Proof: a real Falco probe catches a real regression From 7521f79e7073b8b2c3c62625bd9c949ee27141d4 Mon Sep 17 00:00:00 2001 From: ErenAri Date: Sun, 14 Jun 2026 19:41:26 +0300 Subject: [PATCH 3/3] Tighten artifact upload allowlist to exclude SSH key/seed/overlay Security review flagged the broad .bpfcompat/runs/** upload glob: the per-run dir holds the generated SSH private key (id_ed25519), cloud-init seed, and disk overlay. Restore an allowlist of just the log/result files (adding qemu.log for boot/KVM diagnosis) so secrets are never swept into a downloadable artifact. The on-failure dump already names specific log files only, not the key. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/bpfcompat-example-hosted.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/bpfcompat-example-hosted.yml b/.github/workflows/bpfcompat-example-hosted.yml index 76cf822d..51a373d1 100644 --- a/.github/workflows/bpfcompat-example-hosted.yml +++ b/.github/workflows/bpfcompat-example-hosted.yml @@ -88,7 +88,7 @@ jobs: shell: bash run: | echo "===== /dev/kvm ====="; ls -l /dev/kvm || true - for f in $(find .bpfcompat -type f \( -name serial.log -o -name validator.stderr -o -name validator-result.json \) 2>/dev/null); do + for f in $(find .bpfcompat -type f \( -name serial.log -o -name qemu.log -o -name validator.stderr -o -name validator-result.json \) 2>/dev/null); do echo "===== $f =====" tail -n 120 "$f" || true done @@ -99,9 +99,18 @@ jobs: with: name: bpfcompat-reports-${{ github.run_id }} if-no-files-found: warn + # Allowlist only — never `.bpfcompat/runs/**` wholesale: the per-run + # dir also holds the generated SSH private key (id_ed25519), the + # cloud-init seed, and the disk overlay, none of which belong in a + # downloadable artifact. path: | reports/ci-dev-functional-suite.json reports/ci-dev-functional-suite.md reports/suites/dev-functional/*.json reports/suites/dev-functional/*.md - .bpfcompat/runs/** + .bpfcompat/runs/**/targets/**/serial.log + .bpfcompat/runs/**/targets/**/qemu.log + .bpfcompat/runs/**/targets/**/libbpf.log + .bpfcompat/runs/**/targets/**/validator-result.json + .bpfcompat/runs/**/targets/**/validator.stderr + .bpfcompat/runs/**/targets/**/validator-exit-code