fix(host): enforce the full kdump crash reservation

This commit is contained in:
archipelago
2026-08-31 09:16:18 -04:00
parent 3409db569e
commit 54431fc856
3 changed files with 43 additions and 14 deletions
+22 -7
View File
@@ -237,24 +237,39 @@ exit 2
} }
} }
/// Append `crashkernel=` to the installed GRUB cmdline and run update-grub. /// Set the installed GRUB cmdline to one fixed `crashkernel=` reservation and
/// run update-grub. Debian's kdump-tools package installs a grub.d snippet that
/// otherwise appends its own range-based reservation after ours; on amd64 that
/// silently wins and reserves only 192M instead of the intended 256M.
/// The reservation itself only exists after the next reboot — memory cannot /// The reservation itself only exists after the next reboot — memory cannot
/// be set aside at runtime — so the caller must log the reboot caveat. /// be set aside at runtime — so the caller must log the reboot caveat.
/// Returns true if the cmdline changed. /// Returns true if the generated cmdline changed.
async fn ensure_crashkernel_cmdline() -> Result<bool> { async fn ensure_crashkernel_cmdline() -> Result<bool> {
let script = format!( let script = format!(
r#" r#"
set -u set -u
GRUB=/etc/default/grub GRUB=/etc/default/grub
KDUMP_GRUB=/etc/default/grub.d/kdump-tools.cfg
PARAM='{CRASHKERNEL_PARAM}' PARAM='{CRASHKERNEL_PARAM}'
[ -f "$GRUB" ] || exit 3 [ -f "$GRUB" ] || exit 3
CHANGED=0
# kdump-tools sources this after /etc/default/grub and unconditionally appends
# crashkernel=512M-:192M. Neutralize that package default: Archipelago owns the
# explicit fixed reservation in GRUB_CMDLINE_LINUX_DEFAULT below.
if [ -f "$KDUMP_GRUB" ] && grep -qE '^[^#]*crashkernel=' "$KDUMP_GRUB"; then
printf '%s\n' '# Archipelago owns crashkernel sizing in /etc/default/grub.' > "$KDUMP_GRUB"
CHANGED=1
fi
LINE=$(grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' "$GRUB" | head -1) LINE=$(grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' "$GRUB" | head -1)
[ -n "$LINE" ] || exit 3 [ -n "$LINE" ] || exit 3
case "$LINE" in # Remove any prior value before appending ours, so repeated fixups can never
*"$PARAM"*) exit 0 ;; # create conflicting parameters whose kernel precedence is easy to misread.
esac NEWLINE=$(printf '%s' "$LINE" | sed -E "s/[[:space:]]+crashkernel=[^ \"']+//g; s/\"$/ $PARAM\"/")
NEWLINE=$(printf '%s' "$LINE" | sed "s/\"$/ $PARAM\"/") if [ "$NEWLINE" != "$LINE" ]; then
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=.*|$NEWLINE|" "$GRUB" sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=.*|$NEWLINE|" "$GRUB"
CHANGED=1
fi
[ "$CHANGED" -eq 1 ] || exit 0
timeout 120 update-grub >/dev/null 2>&1 || true timeout 120 update-grub >/dev/null 2>&1 || true
exit 2 exit 2
"# "#
@@ -3746,6 +3746,13 @@ if [ -d "$BOOT_MEDIA/archipelago/plymouth-theme" ]; then
# Configure clean boot: splash, suppress kernel noise, hide cursor # Configure clean boot: splash, suppress kernel noise, hide cursor
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT=".*"/GRUB_CMDLINE_LINUX_DEFAULT="quiet splash loglevel=0 rd.systemd.show_status=false vt.global_cursor_default=0 acpi=force crashkernel=256M"/' \ sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT=".*"/GRUB_CMDLINE_LINUX_DEFAULT="quiet splash loglevel=0 rd.systemd.show_status=false vt.global_cursor_default=0 acpi=force crashkernel=256M"/' \
/mnt/target/etc/default/grub 2>/dev/null || true /mnt/target/etc/default/grub 2>/dev/null || true
# kdump-tools ships a grub.d snippet that appends crashkernel=512M-:192M
# after this line. The later value silently wins on amd64, so neutralize
# the package default and keep Archipelago's explicit fixed reservation.
if [ -f /mnt/target/etc/default/grub.d/kdump-tools.cfg ]; then
printf '%s\n' '# Archipelago owns crashkernel sizing in /etc/default/grub.' \
> /mnt/target/etc/default/grub.d/kdump-tools.cfg
fi
echo " Installed Archipelago Plymouth theme on target" echo " Installed Archipelago Plymouth theme on target"
fi fi
+14 -7
View File
@@ -242,14 +242,21 @@ section_d() {
else else
record FAIL "kdump-tools configured" "/etc/default/kdump-tools missing USE_KDUMP=1 — host fixup didn't land" record FAIL "kdump-tools configured" "/etc/default/kdump-tools missing USE_KDUMP=1 — host fixup didn't land"
fi fi
# D2. crashkernel reservation — memory is reserved at BOOT, so a node that # D2. crashkernel reservation — grade the memory the kernel actually
# took the OTA fixup but hasn't rebooted yet is WARN, not FAIL. # reserved, not merely the first matching cmdline token. Debian's
if grep -q 'crashkernel=' /proc/cmdline 2>/dev/null; then # kdump-tools.cfg used to append a second crashkernel= range after our 256M;
record PASS "crashkernel reserved" "$(grep -oE 'crashkernel=[^ ]+' /proc/cmdline | head -1)" # the audit falsely passed while /sys reported only 192M reserved.
elif grep -q 'crashkernel=' /etc/default/grub 2>/dev/null; then local crash_size expected_size=$((256 * 1024 * 1024))
record WARN "crashkernel reserved" "written to GRUB — applies on next reboot" crash_size=$(cat /sys/kernel/kexec_crash_size 2>/dev/null || echo 0)
[[ "$crash_size" =~ ^[0-9]+$ ]] || crash_size=0
if (( crash_size >= expected_size )); then
record PASS "crashkernel reserved" "$((crash_size / 1024 / 1024))MiB actually reserved"
elif (( crash_size > 0 )); then
record FAIL "crashkernel reserved" "$((crash_size / 1024 / 1024))MiB reserved; expected >=256MiB (conflicting cmdline?)"
elif grep -q 'crashkernel=256M' /etc/default/grub 2>/dev/null; then
record WARN "crashkernel reserved" "256M written to GRUB — applies on next reboot"
else else
record FAIL "crashkernel reserved" "absent from /proc/cmdline AND /etc/default/grub" record FAIL "crashkernel reserved" "no reservation and crashkernel=256M absent from GRUB"
fi fi
# D3. hang/panic capture policy — runtime-settable, expected immediately # D3. hang/panic capture policy — runtime-settable, expected immediately
if [[ "$(cat /proc/sys/kernel/hung_task_panic 2>/dev/null)" == "1" ]]; then if [[ "$(cat /proc/sys/kernel/hung_task_panic 2>/dev/null)" == "1" ]]; then