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.
This commit is contained in:
Mike Reeves
2026-07-09 13:47:50 -04:00
parent 339a5af4a3
commit 5fd5df54b4
+59 -18
View File
@@ -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