#!/usr/bin/env bash # Explicit administrator/prerequisite operation; never called as a generic RPC. # Installs a verified Debian kernel. It does not reboot or claim the running # kernel is fixed. Keep the existing kernel/boot entries for recovery. set -euo pipefail [[ $(id -u) == 0 ]] || { echo 'Root administrator required' >&2; exit 1; } ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) source /etc/os-release [[ ${ID:-} == debian ]] || { echo 'Vendor-specific kernel qualification required' >&2; exit 1; } case "${VERSION_CODENAME:-}" in trixie) series=6.12; minimum=6.12.113-1 ;; bookworm) series=6.1; minimum=6.1.190-1 ;; *) echo 'Unsupported suite: qualify its fixed kernel before installation' >&2; exit 1 ;; esac arch=$(dpkg --print-architecture) case "$arch" in amd64|arm64) ;; *) echo 'Unsupported kernel architecture' >&2; exit 1 ;; esac [[ $(uname -r) == "$series".* ]] || { echo 'Kernel series differs from the suite default; qualify its backport/vendor upgrade instead of downgrading it' >&2; exit 1; } # A vendor/Raspberry Pi kernel cannot be replaced with a generic Debian kernel # without its own firmware/boot qualification. running_package="linux-image-$(uname -r)" case "$running_package" in *rpi*|*rpt*|*raspi*) echo 'Pi vendor boot path requires separate qualification' >&2; exit 1 ;; esac source_package=$(dpkg-query -W -f='${source:Package}' "$running_package" 2>/dev/null || true) case "$source_package" in linux|linux-6.12|linux-signed-amd64|linux-signed-arm64) ;; *) echo 'Running vendor/unowned kernel: refusing a generic replacement' >&2; exit 1 ;; esac export DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=l apt-get update package="linux-image-$arch" candidate=$(LC_ALL=C apt-cache policy "$package" | python3 -c 'import re,sys;m=re.search(r"^\s*Candidate:\s*(\S+)",sys.stdin.read(),re.M);print(m.group(1) if m else "")') [[ "$candidate" == "$series".* ]] && dpkg --compare-versions "$candidate" ge "$minimum" || { echo "No qualified fixed $package candidate is available (minimum $minimum)" >&2; exit 1; } # Normal authenticated APT verification remains enabled. No blanket upgrade, # autoremove, native-service restart, key change or automatic reboot. apt-get -o APT::Get::AllowUnauthenticated=false install -y --no-install-recommends "$package=$candidate" python3-apt python3 "$ROOT/kernel-security.py" --installed --record-provenance echo 'Fixed kernel installed. Reboot and pass kernel-security.py --running before calling this node patched.'