Re: [PATCH] reboot: fail run_cmd() before init so hw protection can force the action
From: Matti Vaittinen
Date: Mon Nov 09 2026 - 02:22:29 EST
On 07/11/2026 16:31, Zak Brighton Knight wrote:
__hw_protection_trigger() asks userspace to power off through
orderly_poweroff(). It only forces the power-off when running
poweroff_cmd fails. run_cmd() waits for the exec only (UMH_WAIT_EXEC)
so a successful exec counts as a started shutdown.
Before init has started that exec can succeed and do nothing. Usermode
helpers are enabled at rootfs_initcall and wait for the initramfs to
be unpacked. So a built-in driver that triggers during device
initcalls runs the initramfs copy of /sbin/poweroff. On a
dracut/systemd initramfs that is systemctl. It finds /proc not mounted
and decides it is in a chroot. It logs "Running in chroot, ignoring
request." and exits 0. Nobody sees the message because a usermode
helper starts with no stdout or stderr. The default
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 arms no backup timer. The
one-shot latch in __hw_protection_trigger() then makes the kernel
ignore every later request. The machine runs without its critical
temperature protection until the next boot.
I hit this on a ThinkPad T520 running Fedora's 7.2.15 kernel, booted
while still hot from a long memtest run. The ACPI zone read 101 C
against a 100 C _CRT 0.29 s into boot. The kernel logged "HARDWARE
PROTECTION shutdown (Temperature too high)" and the machine kept
running for 90 minutes.
It reproduces in QEMU with Fedora's 7.2.13 kernel and with current
tip. The test uses an SSDT thermal zone whose _TMP is above its _CRT
and an initramfs with Fedora's systemctl as /sbin/poweroff.
hw_protection=reboot fails the same way. Setting
sysctl.kernel.poweroff_cmd on the command line does not help either
because do_sysctl_args() runs after the initcalls.
Make run_cmd() fail with -EBUSY until system_state reaches
SYSTEM_RUNNING. Both callers then take the fallback they already have.
__orderly_poweroff(true) syncs and powers off. __orderly_reboot()
syncs and restarts.
Firmware that reports a bogus critical temperature only during early
boot used to get away with it. Such a machine will now power off at
boot, as it already does when the same reading comes after init has
started.
A short window remains between SYSTEM_RUNNING and init being ready to
handle the request. A non-zero CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS
still covers that.
An AI coding assistant (Claude by Anthropic) helped find the cause,
build the reproducer and draft this patch.
Fixes: 10a0a8d4e3f6 ("Add common orderly_poweroff()")
Signed-off-by: Zak Brighton Knight <zakbrightonknight@xxxxxxxxx>
Reviewed-by: Matti Vaittinen <mazziesaccount@xxxxxxxxx>
Yours,
-- Matti
--
Matti Vaittinen
Linux kernel developer at ROHM Semiconductors
Oulu Finland
~~ When things go utterly wrong vim users can always type :help! ~~