From 5fd5df54b487e5c81cd5851a736d69efab994fd6 Mon Sep 17 00:00:00 2001 From: Mike Reeves Date: Thu, 9 Jul 2026 13:47:50 -0400 Subject: [PATCH] Install UEK8 in so-kernel-upgrade when no UEK kernel is present The script assumed the UEK8 kernel was already installed and only switched the boot default to it. On a node running the EL9 stock kernel (RHCK 5.14) there is no kernel-uek* package at all, so `dnf update` has nothing to upgrade and UEK8 never lands -- the script just logged "nothing to do" and exited 0. When no 6.x UEK boot entry exists, install the kernel-uek metapackage (it pulls kernel-uek-core plus the module subpackages, including kernel-uek-modules-extra-netfilter) and then proceed with the grubby switch. Fail loudly if securityonionkernel is not an enabled repo, since that assignment is gated on the NIC-pin marker and the salt version match and a silent no-op there is hard to diagnose. Also point DEFAULTKERNEL at kernel-uek-core so later kernel updates stay on the UEK line rather than falling back to RHCK. Still idempotent and still never reboots. --- salt/common/tools/sbin/so-kernel-upgrade | 77 ++++++++++++++++++------ 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/salt/common/tools/sbin/so-kernel-upgrade b/salt/common/tools/sbin/so-kernel-upgrade index 46d471051..f901dad8d 100755 --- a/salt/common/tools/sbin/so-kernel-upgrade +++ b/salt/common/tools/sbin/so-kernel-upgrade @@ -5,40 +5,81 @@ # https://securityonion.net/license; you may not use this file except in compliance with the # Elastic License 2.0. # -# so-kernel-upgrade — switch the boot default to the installed UEK8 (6.x) kernel. +# so-kernel-upgrade — install the UEK8 (6.x) kernel if needed and make it the boot default. # -# Security Onion is moving off the EL9 stock kernel / UEK7 (5.x) onto UEK8 (6.x). -# Installing the kernel-uek-core package adds a UEK8 boot entry but does NOT make it the -# default: kernel-install/grubby only auto-promote a new kernel within the running -# kernel's flavor lineage, and we're crossing from a 5.x kernel to the new 6.x UEK flavor. -# So even with UPDATEDEFAULT=yes and DEFAULTKERNEL=kernel-uek-core the box keeps booting -# the old kernel. This tool finds the newest installed 6.x UEK kernel and makes it the -# GRUB default via grubby so the next boot comes up on UEK8. +# Security Onion is moving off the EL9 stock kernel (RHCK, 5.14) / UEK7 (5.15) onto UEK8 (6.x). +# Two separate things have to happen, and neither is automatic: # -# Idempotent: if the UEK8 kernel is already the default it does nothing. It only sets the -# boot default; it does NOT reboot — the admin reboots the node on their own schedule. +# 1. Install it. A node running RHCK has no kernel-uek* package at all, so 'dnf update' +# never pulls UEK8 in — there is nothing to upgrade. The kernel-uek metapackage has to +# be installed explicitly from the securityonionkernel repo. +# 2. Boot it. Installing kernel-uek-core adds a UEK8 boot entry but does NOT make it the +# default: kernel-install/grubby only auto-promote a new kernel within the running +# kernel's flavor lineage, and we're crossing from a 5.x kernel to the new 6.x UEK +# flavor. So even with UPDATEDEFAULT=yes and DEFAULTKERNEL=kernel-uek-core the box +# keeps booting the old kernel until grubby is told otherwise. +# +# This tool does both, then points DEFAULTKERNEL at kernel-uek-core so later kernel updates +# stay on the UEK line. +# +# Idempotent: an already-installed, already-default UEK8 kernel is left alone. It only sets +# the boot default; it does NOT reboot — the admin reboots the node on their own schedule. + +KERNEL_REPO="securityonionkernel" +KERNEL_PKG="kernel-uek" log() { echo "[so-kernel-upgrade] $*"; } [ "$(id -u)" -eq 0 ] || { log "must run as root"; exit 1; } command -v grubby >/dev/null 2>&1 || { log "grubby not found"; exit 1; } +command -v dnf >/dev/null 2>&1 || { log "dnf not found"; exit 1; } # Newest installed UEK8 (6.x) kernel known to the bootloader. UEK8 vmlinuz paths look like -# /boot/vmlinuz-6.12.0-203.76.7.5.el9uek.x86_64; the 5.x UEK7 and 5.14 RHCK won't match. -target="$(grubby --info=ALL 2>/dev/null \ - | sed -n 's/^kernel="\(.*\)"$/\1/p' \ - | grep -E '/vmlinuz-6\.[0-9]+.*uek' \ - | sort -V | tail -1)" +# /boot/vmlinuz-6.12.0-203.76.7.5.el9uek.x86_64; the 5.15 UEK7 and 5.14 RHCK won't match. +find_uek8() { + grubby --info=ALL 2>/dev/null \ + | sed -n 's/^kernel="\(.*\)"$/\1/p' \ + | grep -E '/vmlinuz-6\.[0-9]+.*uek' \ + | sort -V | tail -1 +} + +target="$(find_uek8)" if [ -z "$target" ]; then - log "no installed 6.x UEK (UEK8) kernel found — confirm the kernel repo is assigned and" - log "'dnf update' has installed kernel-uek-core. Nothing to do." - exit 0 + log "no UEK8 kernel installed — installing $KERNEL_PKG from $KERNEL_REPO" + + # The repo is assigned by the repo.client highstate, and only once NICs are pinned by MAC + # (/opt/so/state/nic_names_pinned) so the kernel swap can't renumber interfaces SO binds + # by name. Without the repo we'd silently pull nothing, so fail loudly instead. + if ! dnf -q repolist --enabled 2>/dev/null | awk '{print $1}' | grep -qx "$KERNEL_REPO"; then + log "ERROR: repo '$KERNEL_REPO' is not enabled on this node." + log "Run a highstate first; it is skipped until /opt/so/state/nic_names_pinned exists" + log "(run so-nic-pin) and this node's salt matches the version this release ships." + exit 1 + fi + + dnf -y install "$KERNEL_PKG" || { log "ERROR: failed to install $KERNEL_PKG"; exit 1; } + + target="$(find_uek8)" + if [ -z "$target" ]; then + log "ERROR: $KERNEL_PKG installed but no 6.x UEK boot entry appeared — check 'grubby --info=ALL'" + exit 1 + fi + log "installed UEK8 kernel: $target" +fi + +# Keep future kernel updates on the UEK line rather than falling back to RHCK. Oracle ships +# this file; only rewrite it when it's actually pointing somewhere else. +if [ -f /etc/sysconfig/kernel ] && ! grep -q '^DEFAULTKERNEL=kernel-uek-core$' /etc/sysconfig/kernel; then + log "setting DEFAULTKERNEL=kernel-uek-core in /etc/sysconfig/kernel" + sed -i 's/^DEFAULTKERNEL=.*/DEFAULTKERNEL=kernel-uek-core/' /etc/sysconfig/kernel fi current="$(grubby --default-kernel 2>/dev/null)" if [ "$current" = "$target" ]; then log "UEK8 kernel is already the boot default: $target" + [ "$(uname -r)" = "$(basename "$target" | sed 's/^vmlinuz-//')" ] \ + || log "REBOOT REQUIRED to start using it (currently running $(uname -r))." exit 0 fi