From 3950b73e730026364688d59cb03d626709cd8dae Mon Sep 17 00:00:00 2001 From: Thierry Laurion Date: Sun, 5 Jul 2026 19:21:42 -0400 Subject: [PATCH] initrd/bin/kexec-sign-config.sh: stop re-hashing stale default entry paths on -u update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the -u block that re-hashed file paths extracted from the old kexec_default_hashes.txt. Those paths are from a previously saved default boot entry. If a distro replaced a versioned boot file in-place (i.e. atomically deletes old binaries while providing new ones), the old path no longer exists on disk and sha256sum fails, aborting the entire update with DIE. Qubes OS is the first distro that replaces boot binaries atomically without fan-out: a dom0 update replaces xen-4.19.4.gz with xen-4.19.5.gz in-place (QubesOS/qubes-vmm-xen#220, shipped to stable via QubesOS/updates-status#6746 on 2026-07-02). Other distros (Fedora, Arch, Debian, NixOS, Ubuntu) keep old kernels alongside new ones, leaving deletion to an OS cleanup policy, so the old paths still resolve and the re-hash failure was never observed there. The re-hash had been present since its introduction in 2018 but went unnoticed because no OS had ever removed boot binaries atomically without leaving the old files in place — Qubes OS automated testing on heads commit 426750ae (2026-04-22, pre_release_dasharo_101_rc3) passed because xen 4.19.4 was still current and the old paths resolved (openQA tests T430 openqa.qubes-os.org/tests/187218, V560TU openqa.qubes-os.org/tests/186420). It became blocking only after xen 4.19.5 replaced 4.19.4 on disk, at which point any user with a default boot entry pointing at xen-4.19.4.gz would hit the fatal failure. The failure is now fatal because the -u (update) and -r (rollback counter) flags are passed together in a single call. When the re-hash fails, DIE is called before the rollback counter is ever incremented, leaving the system with a partially updated kexec_hashes.txt but no counter bump. This coupling was introduced in commit 8bfae52ad6a (Oct 2020), which restructured update_checksums to always call kexec-sign-config with -u hardcoded and -r as extparam. Regression lineage: - Mar 14, 2018 - Kyle Rankin introduced the re-hash in update_checksums() inside gui-init (commit 769f6a7a24d). - Jul 5, 2019 - Matt DeVillier moved update_checksums() to /etc/functions (commit ed2f19d862d). - Oct 8, 2020 - alex-nitrokey moved the re-hash block into kexec-sign-config under the -u flag and coupled it with -r (rollback) in the same call (commit 8bfae52ad6a). - Through 2026 - No OS had removed boot binaries atomically without leaving old files in place, so the coupled failure went untriggered. Mitigation on unpatched firmware (recovery shell): mount -o rw,remount /boot rm /boot/kexec_default_hashes.txt mount -o ro,remount /boot reboot.sh Then re-run Update checksums. The -e guard skips the re-hash when the file is gone. Then set a new default from the boot menu. Fix: skip the re-hash entirely. The user re-saves the default boot entry from the boot menu to regenerate kexec_default_hashes.txt. Signed-off-by: Thierry Laurion --- initrd/bin/kexec-sign-config.sh | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/initrd/bin/kexec-sign-config.sh b/initrd/bin/kexec-sign-config.sh index cde9fae01..9ef261031 100755 --- a/initrd/bin/kexec-sign-config.sh +++ b/initrd/bin/kexec-sign-config.sh @@ -55,12 +55,18 @@ if [ "$update" = "y" ]; then DEBUG "update=y: Updating kexec hashes in staging dir $stagedir" cd /boot find ./ -type f ! -path './kexec*' -print0 | xargs -0 sha256sum >"$stagedir/kexec_hashes.txt" - if [ -e /boot/kexec_default_hashes.txt ]; then - DEBUG "/boot/kexec_default_hashes.txt exists, updating in staging" - DEFAULT_FILES=$(cut -f3 -d ' ' "$stagedir/kexec_default_hashes.txt" - fi - + # kexec_default_hashes.txt is intentionally NOT re-hashed here. + # The re-hash extracts file paths from the old default hash file + # and runs sha256sum on each. Qubes OS does NOT fan out old and + # new xen binaries: a dom0 update atomically deletes the old + # binary while providing the new one (xen-4.19.4.gz replaced by + # xen-4.19.5.gz in-place — QubesOS/qubes-vmm-xen#220 shipped to + # stable via QubesOS/updates-status#6746 on 2026-07-02). The old + # path no longer exists on disk, sha256sum fails, and DIE is + # called inside this -u subshell before the -r (rollback counter) + # block below can ever run (coupled since commit 8bfae52ad6a). + # The user re-saves a default from the boot menu to regenerate + # kexec_default_hashes.txt with current paths. #also save the file & directory structure to detect added files print_tree >"$stagedir/kexec_tree.txt" )