fix: stop the raw install-if-different check at the end of the object - #449
Merged
Conversation
otavio
force-pushed
the
fix/install-if-different-object-region
branch
from
September 10, 2026 14:34
f224d35 to
a9fd875
Compare
The check handed `should_skip_install` a reader over the whole target device whenever `count` was `-1`, so it kept scanning well past the bytes the object owns. Objects sharing a device at different offsets then answer for each other. An i.MX6ULL package hit this on a downgrade. It writes SPL at `seek` 1 and U-Boot proper at `seek` 64 of the same `/dev/mtdblock1`, both guarded by the same U-Boot version, and objects install largest first: U-Boot proper landed on the device first, and the SPL check then read straight through its own region into the U-Boot image just written, found the version it was looking for, and skipped the SPL. The device kept the previous SPL while every other object downgraded. Bound the reader to the bytes the install writes. For a compressed object that is the uncompressed size, since `skip` and `count` measure the source rather than the region they land in; otherwise it is `size` minus `skip`, narrowed by `count` when it is limited. Turning `count` into a byte length up front also lets the write path share it, and drops both the clone it needed and the `AsyncReadSeek` boxing.
otavio
force-pushed
the
fix/install-if-different-object-region
branch
from
September 10, 2026 14:36
a9fd875 to
6d16a2b
Compare
0.5.0 cannot read a version banner that lands across the boundary of one of its 0x200 reads, and reports no version at all when that happens. The check guarding an object then reads as "the target differs" every time, so an object that never changed is written on every update, and the comparison the object asked for never actually runs. The i.MX6ULL builds this showed up on sat on both sides of that: one pair of binaries kept their banners clear of a boundary and compared fine, the other pair straddled one and never compared at all. 0.5.1 carries that fix, and 0.5.2 stops the custom-pattern search from reading the whole source into memory before matching, which for a rule pointed at a partition meant holding the image alongside the device it came from. Naming the version rather than any 0.5 keeps a fresh resolve from picking up either of the older behaviours.
otavio
force-pushed
the
fix/install-if-different-object-region
branch
from
September 10, 2026 14:42
6d16a2b to
dbb2990
Compare
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.
What
An object installed with the
rawhandler could be skipped as "unchanged" on the strength of a different object's version string, leaving the old binary on the device while everything around it updated.The failure
An i.MX6ULL package writes
SPLatseek1 andu-boot.imgatseek64 of the same/dev/mtdblock1, both guarded by the same U-Boot version.Install::handlesorts objects largest first, so U-Boot proper is written first. The SPL check then ran withcount: -1, which handedshould_skip_installa reader over the whole device — it read straight past the SPL's own 56320 bytes into the U-Boot image written moments earlier, found the version it was looking for, and skipped the SPL.Downgrading a device left it with the new SPL and everything else rolled back.
The fix
Bound the check to the bytes the install writes:
The two cases differ because
skipandcountmeasure the source, not the region it lands in: for a compressed object the source is compressed, so narrowing an uncompressed length by a compressed byte count would under-bound the check. Convertingcountto a byte length once, up front, also lets the write path share it, which drops theself.count.clone()that only existed to allow matching the enum twice. With both arms of the check now yielding the same type, the localAsyncReadSeektrait and itsBox<dyn>go away.flash.rsandimxkobs.rswere left alone deliberately.Flasherases and rewrites the whole MTD partition, so its check already covers exactly its own region, and asizebound would cut off the banner on NAND wherenandwrite -pskips bad blocks.Imxkobsreads/dev/mtdXrobecausekobs-ngwrites FCB/DBBT plus firmware copies at layout-defined offsets, so there is no region expressible asseek + size.Tests
install_if_different_stops_at_the_end_of_the_object— object atSHARED_OBJECT_AT, neighbour atSHARED_NEIGHBOUR_ATcarrying the version the object asks for; the object must still be written. Fails against the previous code with "the neighbour's version answered for this object and skipped it".install_if_different_matches_inside_the_object— the counterpart, so a matching version inside the object's own region still skips.The dependency bump
The second commit pins
find-binary-versionto 0.5.2 rather than accepting any 0.5. 0.5.0 read binaries in fixed 0x200 windows with no overlap, so a version banner crossing a boundary was never found and the binary reported no version at all — whichcheck_if_differentreads as "different", quietly turninginstall-if-differentinto "always install" for whole builds at a time. 0.5.1 fixes that; 0.5.2 additionally stops the custom-pattern search from reading the whole source into memory before matching.Both halves are needed here: the bound alone made the downgrade work only because nothing was detectable, and the detection fix alone would still have let U-Boot proper answer for the SPL.
Verified against the real packages, driving
objects::Raw::installover a simulated/dev/mtdblock1: