Repository navigation
A kernel copied onto the ESP takes its name only once it reads back as its source - #261
Merged
Merged
Conversation
…mmit: the trial stays, and the next boot commits again boot-success's commit_slot returned 0 once BOOTX64.EFI was the slot's kernel, whatever became of the committed-slot record. With the record unwritten, the caller cleared the trial, recorded "commit b", forgot the entries and raised the clock's floor while the ESP still named a: the next boot found b running uncommitted and rebooted once for nothing, and kryptik-update refused every apply from b until kryptik-recover --commit-slot b from the medium. Now the record is part of the commit. Failing it keeps the trial, and since BOOTX64.EFI already boots b and kryptik-efiboot's entries come after it in BootOrder, the next boot finds BOOTX64.EFI already b and writes only the record. kryptik-recover's put already dies the same way. kryptik-update says which ESP write failed when the staged kernel's flush or the version record fails, instead of leaving set -e to exit without a word.
…slot: a boot file that could not be replaced left the ESP naming a slot the firmware does not boot From a non-author read: when the copy, flush or rename of BOOTX64.EFI failed, commit_slot still rewrote committed-slot to the trial's slot. The next boot took BOOTX64.EFI, the old slot, whose applies kryptik-update then refused as not committed. The fixture fails that step and expects the record unchanged.
…s its source: boot-success's commit and kryptik-recover's commit and restore now compare, as the installer and kryptik-update already did boot-success copied the trial slot's kernel to BOOTX64.EFI.new, fsynced and renamed it without looking at what landed, and kryptik-recover did the same for the boot file and for the medium's kernel. A copy that read back wrong became a boot file Secure Boot refuses. Now the copy is compared with its source before the rename: a failed compare fails the commit and the trial stays, as a failed write already does, and recover stops before anything is committed. The installer compares BOOTX64.EFI and kryptik-update hashes its staged kernel. The boot-success fixture makes the copy read back wrong and expects the old boot file and record and the trial kept.
…ped from the page cache after its fsync, so the compare reads the ESP and not the copy still in memory From a non-author read: cmp right after sync -f read the cached pages, which says little more than cp's own status. dd iflag=nocache count=0 drops a file's clean pages, best effort; boot-success's and kryptik-recover's compares and kryptik-update's hash of its staged kernel now read what the ESP holds.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Built on #258 (commit-record-fails, in the integrator's batch). Until it lands, the diff against main includes its two commits. This PR's own changes are its top two commits, 5688e3d and d0e6f32.
What was wrong (from an adversarial re-read of the update chain on main). Of the four places Kryptik copies a kernel onto an ESP, two looked at what landed:
BOOTX64.EFIwith the slot A kernel (kryptik-install.sh:313),kryptik-update applyhashes its staged kernel against the signed manifest (kryptik-update:369).The other two did not:
BOOTX64.EFI.new, fsynced it and renamed it,kryptik-recoverdid the same for the boot file in--commit-slot, and for the medium's kernel in--restore-slot.A copy that read back wrong (a failing card, a full or damaged FAT) became a boot file that Secure Boot refuses. After a commit, only the slot's own firmware entry then stood between the machine and an unbootable disk.
What changed.
build/service-scripts/boot-success.sh: the copy is compared with its source (cmp -s) between the fsync and the rename. A copy that differs fails the commit as a failed write already does: the trial stays,commit-failedis recorded and the boot file is unchanged.dd iflag=nocache count=0, best effort), which a non-author read pointed out: without that, the compare read the copy still in memory.kryptik-update's hash of its staged kernel does the same.tools/update/kryptik-recover: both copies are compared before their rename. A mismatch stops the tool, withBOOTX64.EFIunchanged, or with nothing committed in the restore.docs/design/boot-and-updates.md: step 5 says ".new, fsync, compare, rename" (that paragraph is rewrapped).tools/tests/boot-success.sh: acmpstand-in passes through to the real one, except that it can make the copy toBOOTX64.EFI.newread back wrong. The new case expectscommit-failed b, the old boot file, the record still naming a, and the trial kept.How the run proves it. CI's fixture step runs the new case. Distro run 37883969899 commits through boot-success in the update and install suites, and the integrity suite runs
kryptik-recover --commit-slotand--restore-slotfrom the medium.