42 lines
2.5 KiB
Bash
42 lines
2.5 KiB
Bash
#!/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.'
|