bootloader/lkenv,lk: recover devices wedged by duplicated boot partions - #17419
Open
kubiko wants to merge 1 commit into
Open
bootloader/lkenv,lk: recover devices wedged by duplicated boot partions#17419kubiko wants to merge 1 commit into
kubiko wants to merge 1 commit into
Conversation
…ions A device updated by a snapd carrying the duplicate boot image partition bug can be left with the same kernel revision recorded in more than one boot image partition. Fixing the assignment logic stops new duplicates from appearing but does not help such a device: the duplicate is persisted in the snapbootsel partition, no free boot image partition can be found any more and kernel refreshes keep failing. Nothing in the existing code repairs it - RemoveKernelFromBootPartition() looks a partition up by the kernel revision it holds and clears the first match only, so even removing the kernel leaves the second reference behind. Add DuplicateKernelBootPartitions(), reporting each kernel revision that is referenced by more than one boot image partition together with all the partitions referencing it, and ClearKernelBootPartition(), clearing the value of a boot image partition addressed by label rather than by the value it holds, which is what is needed to clear one specific partition out of several holding the same value. Use both from lk.ExtractKernelAssets() to repair the boot image matrix before looking for a free boot image partition, so an affected device recovers on its next kernel refresh with no manual intervention. How much has to be established before a redundant reference can be cleared depends on whether the kernel revision is referenced for booting at all. Add IsKernelReferenced() to report whether a kernel revision is named by snap_kernel or snap_try_kernel. These are the only two variables that direct the bootloader at the kernel matrix; the recovery system variables name recovery systems in a separate matrix that this repair never touches, so they are deliberately not considered. A kernel revision named by neither is not used to boot the device. The bootloader never searches the matrix for it, so no boot image partition it points at can be selected, and the redundant references can be dropped without comparing the boot image partitions at all - there is no boot image to lose. This matters in practice, because the revision left duplicated is frequently one that has already been superseded. For a kernel revision that is referenced, a redundant reference is only cleared once the two boot image partitions have been confirmed to hold identical content. If they differ, then the reference is the only record of where a distinct boot image lives: clearing it would leave a boot image the bootloader can no longer find and would let the extraction that follows overwrite an image that is still needed. In that case the matrix is left untouched and the extraction fails as before rather than silently discarding a boot image. The reference in the partition appearing first in the matrix is the one kept, matching the partition that GetKernelBootPartition() resolves the kernel revision to, so the bootloader's view of the device does not change. Repair is wired into the kernel path only. The recovery system matrix can duplicate as well, but it reserves every assigned recovery system, so it leaks a boot image partition instead of wedging the device, and the boot images of two distinct recovery systems may legitimately be identical, which makes the content check unsafe as a criterion there. While at it, factor the boot image partition path resolution that ExtractKernelAssets() already did out into bootPartitionPath(), as the repair needs the same lookup. Signed-off-by: Ondrej Kubik <ondrej.kubik@canonical.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #17419 +/- ##
==========================================
+ Coverage 78.81% 78.84% +0.02%
==========================================
Files 1406 1403 -3
Lines 197084 197108 +24
Branches 2498 2498
==========================================
+ Hits 155330 155404 +74
+ Misses 32387 32348 -39
+ Partials 9367 9356 -11
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Thu Jul 30 17:58:02 UTC 2026 Failures:Preparing:
Executing:
Restoring:
Skipped tests from snapd-testing-skipIf you wish to have any of the below tests run in your PR, in your PR description, add 'unskip:' followed by a copy-and-pasted list of the below tests you wish to run (unskip plus test list must be valid yaml)
|
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.
A device updated by a snapd carrying the duplicate boot image partition bug can be left with the same kernel revision recorded in more than one boot image partition. Fixing the assignment logic stops new duplicates from appearing but does not help such a device: the duplicate is persisted in the snapbootsel partition, no free boot image partition can be found any more and kernel refreshes keep failing. Nothing in the existing code repairs it -
RemoveKernelFromBootPartition()looks a partition up by the kernel revision it holds and clears the first match only, so even removing the kernel leaves the second reference behind.Add
DuplicateKernelBootPartitions(), reporting each kernel revision that is referenced by more than one boot image partition together with all the partitions referencing it, andClearKernelBootPartition(), clearing the value of a boot image partition addressed by label rather than by the value it holds, which is what is needed to clear one specific partition out of several holding the same value.Use both from
lk.ExtractKernelAssets()to repair the boot image matrix before looking for a free boot image partition, so an affected device recovers on its next kernel refresh with no manual intervention.A redundant reference is cleared only after the two boot image partitions have been confirmed to contain identical content, ensuring we accidentally don't drop into a failed refresh trap. If they differ, then the reference is the only record of where a distinct boot image lives: clearing it could bring the device to the bricked state. The exception here is when a duplicate kernel snap record is not referenced by either the current or try kernel (system for recovery env), in which case it's safe to clear it as it's unreferenced. In other cases, the matrix is left untouched, and the extraction fails as before rather than silently discarding a boot image. The reference in the partition appearing first in the matrix is the one kept, matching the partition that
GetKernelBootPartition()resolves the kernel revision to, so the bootloader's view of the device does not change.Repair is wired into the kernel path only. The recovery system matrix can duplicate as well, but it reserves every assigned recovery system, so it leaks a boot image partition instead of wedging the device, and the boot images of two distinct recovery systems may legitimately be identical, which makes the content check unsafe as a criterion there.