From 04802bdb778a3b030665ab724ac51bf6aaea8d2a Mon Sep 17 00:00:00 2001 From: Stephen Akinyemi Date: Sat, 18 Jul 2026 00:22:30 +0100 Subject: [PATCH 1/2] ci(kernel): add stable update safeguards Build all supported kernel configurations on pull requests and reject stale stable-series pins before expensive builds begin. Add a daily monitor that opens one tracking issue for an available update, require exact patch application, and declare the complete release build dependencies. --- .github/workflows/kernel-ci.yml | 102 +++++++++++++++++++ .github/workflows/kernel-version-monitor.yml | 71 +++++++++++++ .github/workflows/release.yml | 4 +- Makefile | 2 +- scripts/apply-kernel-patches.sh | 26 +++++ scripts/check-kernel-version.sh | 52 ++++++++++ 6 files changed, 254 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/kernel-ci.yml create mode 100644 .github/workflows/kernel-version-monitor.yml create mode 100755 scripts/apply-kernel-patches.sh create mode 100755 scripts/check-kernel-version.sh diff --git a/.github/workflows/kernel-ci.yml b/.github/workflows/kernel-ci.yml new file mode 100644 index 0000000..f2cb4d5 --- /dev/null +++ b/.github/workflows/kernel-ci.yml @@ -0,0 +1,102 @@ +name: Kernel CI + +on: + pull_request: + branches: [krunfw] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: kernel-ci-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + freshness: + name: Check stable kernel version + runs-on: ubuntu-24.04 + steps: + - name: Code checkout + uses: actions/checkout@v4 + + - name: Check pinned kernel + run: scripts/check-kernel-version.sh + + source: + name: Fetch kernel source + needs: freshness + runs-on: ubuntu-24.04 + steps: + - name: Code checkout + uses: actions/checkout@v4 + + - name: Download kernel source + run: | + kernel_version=$(awk '$1 == "KERNEL_VERSION" { print $3; exit }' Makefile) + make "tarballs/${kernel_version}.tar.gz" + + - name: Verify kernel source archive + run: tar tzf tarballs/*.tar.gz >/dev/null + + - name: Upload kernel source + uses: actions/upload-artifact@v4 + with: + name: kernel-source + path: tarballs/*.tar.gz + compression-level: 0 + retention-days: 1 + + build: + name: Build ${{ matrix.name }} + needs: source + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - name: Linux x86_64 + runner: ubuntu-24.04 + packages: "" + make_args: "" + - name: Windows x86_64 + runner: ubuntu-24.04 + packages: "" + make_args: OS=Windows + - name: SEV x86_64 + runner: ubuntu-24.04 + packages: "" + make_args: SEV=1 + - name: TDX x86_64 + runner: ubuntu-24.04 + packages: "" + make_args: TDX=1 + - name: Linux aarch64 + runner: ubuntu-24.04-arm + packages: "" + make_args: "" + - name: Linux riscv64 + runner: ubuntu-24.04 + packages: gcc-riscv64-linux-gnu + make_args: ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- + steps: + - name: Code checkout + uses: actions/checkout@v4 + + - name: Download kernel source + uses: actions/download-artifact@v4 + with: + name: kernel-source + path: tarballs + + - name: Install build dependencies + env: + EXTRA_PACKAGES: ${{ matrix.packages }} + run: | + sudo apt-get update + sudo apt-get install -y make gcc bc bison flex elfutils python3-pyelftools curl patch libelf-dev cpio xz-utils $EXTRA_PACKAGES + + - name: Build kernel configuration + env: + MAKE_ARGS: ${{ matrix.make_args }} + run: make -j"$(nproc)" $MAKE_ARGS kernel.c diff --git a/.github/workflows/kernel-version-monitor.yml b/.github/workflows/kernel-version-monitor.yml new file mode 100644 index 0000000..7b4efb9 --- /dev/null +++ b/.github/workflows/kernel-version-monitor.yml @@ -0,0 +1,71 @@ +name: Kernel version monitor + +on: + schedule: + - cron: "17 7 * * *" + workflow_dispatch: + +permissions: + contents: read + issues: write + +jobs: + check: + name: Check stable kernel version + runs-on: ubuntu-24.04 + steps: + - name: Code checkout + uses: actions/checkout@v4 + + - name: Check pinned kernel + id: kernel + shell: bash + run: | + set +e + output=$(scripts/check-kernel-version.sh) + status=$? + set -e + printf '%s\n' "$output" + while IFS='=' read -r key value; do + if [[ $key == "current" || $key == "latest" ]]; then + echo "$key=$value" >> "$GITHUB_OUTPUT" + fi + done <<< "$output" + echo "status=$status" >> "$GITHUB_OUTPUT" + + - name: Open kernel update issue + if: steps.kernel.outputs.status == '1' + env: + GH_TOKEN: ${{ github.token }} + CURRENT_VERSION: ${{ steps.kernel.outputs.current }} + LATEST_VERSION: ${{ steps.kernel.outputs.latest }} + run: | + issue_title="Kernel stable update available" + issue_number=$(gh api "repos/${GITHUB_REPOSITORY}/issues?state=open&per_page=100" --jq ".[] | select((has(\"pull_request\") | not) and .title == \"$issue_title\") | .number" | head -n 1) + if [[ -n $issue_number ]]; then + echo "Issue #$issue_number already tracks the available update" + exit 0 + fi + printf -v issue_body 'libkrunfw pins Linux %s, but Linux %s is now available in the same stable series. Update `KERNEL_VERSION`, apply every common and TEE patch, and let Kernel CI build all six configurations before merging.\n\nDetected by [this scheduled run](%s/%s/actions/runs/%s).' "$CURRENT_VERSION" "$LATEST_VERSION" "$GITHUB_SERVER_URL" "$GITHUB_REPOSITORY" "$GITHUB_RUN_ID" + gh issue create \ + --title "$issue_title" \ + --body "$issue_body" + + - name: Close resolved kernel update issue + if: steps.kernel.outputs.status == '0' + env: + GH_TOKEN: ${{ github.token }} + run: | + issue_title="Kernel stable update available" + issue_number=$(gh api "repos/${GITHUB_REPOSITORY}/issues?state=open&per_page=100" --jq ".[] | select((has(\"pull_request\") | not) and .title == \"$issue_title\") | .number" | head -n 1) + if [[ -n $issue_number ]]; then + gh issue close "$issue_number" --comment "The pinned kernel now matches the latest stable release in its series." + fi + + - name: Fail when the kernel check did not pass + if: steps.kernel.outputs.status != '0' + env: + CHECK_STATUS: ${{ steps.kernel.outputs.status }} + run: | + echo "Kernel version check failed with status $CHECK_STATUS" >&2 + exit 1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fd62865..a740eed 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v4 - name: Install dependencies - run: sudo apt-get update && sudo apt-get install -y make gcc bc bison flex elfutils python3-pyelftools curl patch libelf-dev + run: sudo apt-get update && sudo apt-get install -y make gcc bc bison flex elfutils python3-pyelftools curl patch libelf-dev cpio xz-utils - name: Extract version from Makefile id: version @@ -53,7 +53,7 @@ jobs: uses: actions/checkout@v4 - name: Install dependencies - run: sudo apt-get update && sudo apt-get install -y make gcc bc bison flex elfutils python3-pyelftools curl patch libelf-dev + run: sudo apt-get update && sudo apt-get install -y make gcc bc bison flex elfutils python3-pyelftools curl patch libelf-dev cpio xz-utils - name: Extract version from Makefile id: version diff --git a/Makefile b/Makefile index fe9bdf5..b2b39d9 100644 --- a/Makefile +++ b/Makefile @@ -135,7 +135,7 @@ $(KERNEL_TARBALL): $(KERNEL_SOURCES): $(KERNEL_TARBALL) tar xf $(KERNEL_TARBALL) - for patch in $(KERNEL_PATCHES); do patch -p1 -d $(KERNEL_SOURCES) < "$$patch"; done + ./scripts/apply-kernel-patches.sh $(KERNEL_SOURCES) $(KERNEL_PATCHES) cp config-libkrunfw$(VARIANT)_$(GUESTARCH) $(KERNEL_SOURCES)/.config cd $(KERNEL_SOURCES) ; $(MAKE) olddefconfig diff --git a/scripts/apply-kernel-patches.sh b/scripts/apply-kernel-patches.sh new file mode 100755 index 0000000..0c27f2d --- /dev/null +++ b/scripts/apply-kernel-patches.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -euo pipefail + +if (( $# < 2 )); then + echo "Usage: $0 SOURCE_DIR PATCH..." >&2 + exit 2 +fi + +source_dir=$1 +shift + +for patch_file in "$@"; do + output=$(patch -f -p1 -d "$source_dir" < "$patch_file" 2>&1) || { + status=$? + printf '%s\n' "$output" >&2 + exit "$status" + } + printf '%s\n' "$output" + + # GNU and BSD patch use different messages for unsafe context or line-number adjustments. + if grep -Eiq 'with fuzz|offset [-+]?[0-9]+ lines?|no such line [0-9]+ in input file, ignoring' <<< "$output"; then + echo "Patch did not apply exactly: $patch_file" >&2 + exit 1 + fi +done diff --git a/scripts/check-kernel-version.sh b/scripts/check-kernel-version.sh new file mode 100755 index 0000000..5f3f2fe --- /dev/null +++ b/scripts/check-kernel-version.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +set -euo pipefail + +makefile=${1:-Makefile} +stable_repo=${KERNEL_STABLE_REPO:-https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git} + +current=$(awk '$1 == "KERNEL_VERSION" && $2 == "=" { sub(/^linux-/, "", $3); print $3; exit }' "$makefile") +if [[ ! $current =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Could not read a stable kernel version from $makefile" >&2 + exit 2 +fi + +series=${current%.*} +if ! tags=$(git ls-remote --refs --tags "$stable_repo" "v${series}.*"); then + echo "Could not query stable kernel tags from $stable_repo" >&2 + exit 2 +fi + +# Ignore release candidates and non-stable suffixes, then compare patch numbers numerically. +latest=$(awk -v series="$series" ' + { + tag = $2 + sub(/^refs\/tags\/v/, "", tag) + count = split(tag, part, ".") + if (count == 3 && part[1] "." part[2] == series && part[3] ~ /^[0-9]+$/) { + patch = part[3] + 0 + if (!found || patch > newest) { + newest = patch + found = 1 + } + } + } + END { + if (found) { + printf "%s.%d\n", series, newest + } + } +' <<< "$tags") + +if [[ -z $latest ]]; then + echo "No stable v${series}.y tags were found in $stable_repo" >&2 + exit 2 +fi + +echo "current=$current" +echo "latest=$latest" + +if [[ $current != "$latest" ]]; then + echo "Kernel $current is not the latest ${series}.y release; update to $latest" >&2 + exit 1 +fi From 425d4cd8ed3f2e3e6f5fb135a1b32882f8a5c069 Mon Sep 17 00:00:00 2001 From: Stephen Akinyemi Date: Sat, 18 Jul 2026 00:34:03 +0100 Subject: [PATCH 2/2] fix(ci): make kernel matrix compatible Allow the shifted hunks required by the existing patch stack while still stopping immediately on rejected or reversed patches. Move the official checkout and artifact actions to their current Node 24-compatible major versions after the first run warned about Node 20 deprecation. --- .github/workflows/kernel-ci.yml | 10 +++++----- .github/workflows/kernel-version-monitor.yml | 2 +- .github/workflows/release.yml | 20 ++++++++++---------- scripts/apply-kernel-patches.sh | 14 ++------------ 4 files changed, 18 insertions(+), 28 deletions(-) diff --git a/.github/workflows/kernel-ci.yml b/.github/workflows/kernel-ci.yml index f2cb4d5..e385e72 100644 --- a/.github/workflows/kernel-ci.yml +++ b/.github/workflows/kernel-ci.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Code checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Check pinned kernel run: scripts/check-kernel-version.sh @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Code checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Download kernel source run: | @@ -40,7 +40,7 @@ jobs: run: tar tzf tarballs/*.tar.gz >/dev/null - name: Upload kernel source - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: kernel-source path: tarballs/*.tar.gz @@ -81,10 +81,10 @@ jobs: make_args: ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- steps: - name: Code checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Download kernel source - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: kernel-source path: tarballs diff --git a/.github/workflows/kernel-version-monitor.yml b/.github/workflows/kernel-version-monitor.yml index 7b4efb9..c0ae390 100644 --- a/.github/workflows/kernel-version-monitor.yml +++ b/.github/workflows/kernel-version-monitor.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Code checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Check pinned kernel id: kernel diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a740eed..9f3907b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Code checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Install dependencies run: sudo apt-get update && sudo apt-get install -y make gcc bc bison flex elfutils python3-pyelftools curl patch libelf-dev cpio xz-utils @@ -30,7 +30,7 @@ jobs: run: make -j"$(nproc)" - name: Upload kernel.c as job artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: kernel-c-x86_64 path: kernel.c @@ -50,7 +50,7 @@ jobs: runs-on: ubuntu-24.04-arm steps: - name: Code checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Install dependencies run: sudo apt-get update && sudo apt-get install -y make gcc bc bison flex elfutils python3-pyelftools curl patch libelf-dev cpio xz-utils @@ -65,7 +65,7 @@ jobs: run: make -j"$(nproc)" - name: Upload kernel.c as job artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: kernel-c-aarch64 path: kernel.c @@ -89,7 +89,7 @@ jobs: needs: build-linux-aarch64 steps: - name: Code checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Extract version from Makefile id: version @@ -98,7 +98,7 @@ jobs: echo "full=$(grep '^FULL_VERSION' Makefile | awk '{print $3}')" >> "$GITHUB_OUTPUT" - name: Download kernel.c artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: kernel-c-aarch64 @@ -120,7 +120,7 @@ jobs: needs: build-linux-x86_64 steps: - name: Code checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Extract version from Makefile id: version @@ -129,7 +129,7 @@ jobs: echo "full=$(grep '^FULL_VERSION' Makefile | awk '{print $3}')" >> "$GITHUB_OUTPUT" - name: Download kernel.c artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: kernel-c-x86_64 @@ -154,7 +154,7 @@ jobs: needs: build-linux-x86_64 steps: - name: Code checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Configure MSVC uses: ilammy/msvc-dev-cmd@v1 @@ -169,7 +169,7 @@ jobs: echo "full=$(grep '^FULL_VERSION' Makefile | awk '{print $3}')" >> "$GITHUB_OUTPUT" - name: Download kernel.c artifact - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: kernel-c-x86_64 diff --git a/scripts/apply-kernel-patches.sh b/scripts/apply-kernel-patches.sh index 0c27f2d..08ba4a2 100755 --- a/scripts/apply-kernel-patches.sh +++ b/scripts/apply-kernel-patches.sh @@ -11,16 +11,6 @@ source_dir=$1 shift for patch_file in "$@"; do - output=$(patch -f -p1 -d "$source_dir" < "$patch_file" 2>&1) || { - status=$? - printf '%s\n' "$output" >&2 - exit "$status" - } - printf '%s\n' "$output" - - # GNU and BSD patch use different messages for unsafe context or line-number adjustments. - if grep -Eiq 'with fuzz|offset [-+]?[0-9]+ lines?|no such line [0-9]+ in input file, ignoring' <<< "$output"; then - echo "Patch did not apply exactly: $patch_file" >&2 - exit 1 - fi + # Force non-interactive behavior so a rejected or reversed patch fails the build immediately. + patch -f -p1 -d "$source_dir" < "$patch_file" done