From fe7591e3b56a5ee07e617b46e6691de6434e19ac Mon Sep 17 00:00:00 2001 From: Tomaz Zaman Date: Wed, 12 Aug 2026 02:42:08 +0200 Subject: [PATCH 45/62] mono-update-check: allow retrying the release the floor already points at The anti-rollback floor is advanced immediately before flashing, so a sysupgrade that is cleanly refused (or crashes) leaves the device running the OLD release with floor == offered tag - and the old gate (install only when strictly newer than the floor) then refused that same release forever: one failed attempt pinned the device until someone logged in and cleared /etc/mono-update.state. The gzip migration turns this from theoretical into likely: firmware predating the gzip-capable flash path refuses a gzipped image pre-write, reboots unharmed, and would never have tried again. Split the gate: refuse only tags STRICTLY OLDER than the floor (the actual anti-rollback property - a validly-signed older release is still rejected and the floor never moves backward), and treat a tag equal to the floor as installable whenever the running release is older. Crash recovery gets the same retry for free. The retry only helps devices whose flash path can eventually succeed. A unit that skips the release carrying the gzip-capable platform.sh cannot install any later gzipped release over the air no matter how often it retries - it must take that intermediate release first (or be reflashed). This commit must therefore ship in the same release as the platform.sh change, before any gzipped image is published. Co-Authored-By: Claude Opus 4.8 --- package/mono/mono-update-check/Makefile | 2 +- .../mono-update-check/files/mono-update-check | 22 ++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/package/mono/mono-update-check/Makefile b/package/mono/mono-update-check/Makefile index 921d0a2c85..4799a4e010 100644 --- a/package/mono/mono-update-check/Makefile +++ b/package/mono/mono-update-check/Makefile @@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mono-update-check PKG_VERSION:=1.0 -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_LICENSE:=GPL-2.0 include $(INCLUDE_DIR)/package.mk diff --git a/package/mono/mono-update-check/files/mono-update-check b/package/mono/mono-update-check/files/mono-update-check index 956a8d4204..bacb56c1e7 100644 --- a/package/mono/mono-update-check/files/mono-update-check +++ b/package/mono/mono-update-check/files/mono-update-check @@ -112,14 +112,19 @@ WANT=$(echo "$JSON" | jsonfilter -e "@.devices['$BOARD'].sha256") [ -n "$TAG" ] || { say "malformed manifest (no tag)"; exit 1; } [ -n "$SYSUPGRADE_URL" ] || { say "no image for board $BOARD in latest.json"; exit 0; } -# Anti-rollback: compare against the floor, not just the running tag. -if ! is_newer "$TAG" "$FLOOR_TAG"; then +# Anti-rollback: refuse anything STRICTLY older than the floor. Equal to the +# floor is not a rollback - the floor is advanced right before flashing, so +# after a crashed or refused flash the device still runs an older release +# with floor == offered tag, and that retry must stay allowed: refusing it +# would pin the device on the old release forever after one failed attempt. +if is_newer "$FLOOR_TAG" "$TAG"; then rm -f "$STATE" - if [ "$TAG" = "$CURRENT" ]; then - say "up to date ($CURRENT)" - else - say "server offers $TAG, not newer than floor $FLOOR_TAG - keeping $CURRENT" - fi + say "server offers $TAG, older than floor $FLOOR_TAG - keeping $CURRENT" + exit 0 +fi +if ! is_newer "$TAG" "$CURRENT"; then + rm -f "$STATE" + say "up to date ($CURRENT)" exit 0 fi @@ -148,7 +153,8 @@ GOT=$(sha256sum "$TMP/image.bin" | cut -d' ' -f1) [ "$GOT" = "$WANT" ] || fail "image hash mismatch against signed manifest - refusing" # Advance the floor BEFORE flashing so a crash mid-upgrade can never later -# accept an image older than this one. Preserved across sysupgrade via keep.d. +# accept an image older than this one; retrying THIS tag stays allowed (see +# the anti-rollback gate). Preserved across sysupgrade via keep.d. printf 'floor=%s\n' "$TAG" > "$FLOORFILE" sync -- 2.47.3