summary
on an rpm-ostree fedora asahi atomic deployment, package files in /usr have canonical epoch-zero mtimes. update-m1n1 passes the u-boot input filename to gzip -c; gzip warns that the timestamp is out of range and exits with status 2. because update-m1n1 uses set -e, it aborts before atomically replacing boot.bin.
the existing boot.bin remains untouched, so this fails safely, but m1n1, u-boot, and device-tree updates are not applied.
environment
- architecture: aarch64, apple m1 pro
- base image:
quay.io/fedora-asahi-remix-atomic-desktops/silverblue:44
- deployment: a signed bluebuild derivative of that image; it had not modified
update-m1n1 or the u-boot package when this was reproduced
- kernel:
7.0.13-400.asahi.fc44.aarch64+16k
update-m1n1-20250713-7.fc44.noarch
uboot-images-armv8-2026.04-102.fc44.noarch
rpm-ostree-2026.2-1.fc44.aarch64
ostree-2026.2-1.fc44.aarch64
gzip-1.14-2.fc44.aarch64
the relevant source remains the package-owned line from update-m1n1. rpm verification showed timestamp differences from ostree canonicalization, not a content modification to this line.
reproduction
the gzip failure can be reproduced without mounting or writing the system esp:
input=/usr/share/uboot/apple_m1/u-boot-nodtb.bin
stat -c 'epoch=%Y' "$input"
gzip -c "$input" >/dev/null
echo "$?"
observed output:
epoch=0
gzip: /usr/share/uboot/apple_m1/u-boot-nodtb.bin: warning: file timestamp out of range for gzip format
2
the full command similarly stopped after the warning and never printed its final m1n1 updated at ... success line. the script had already created boot.bin.new, but did not reach the comparison, backup, or mv steps.
proposed fix
tell gzip not to encode the source filename or timestamp:
-gzip -c "$U_BOOT" >>"${TARGET}.new"
+gzip -nc "$U_BOOT" >>"${TARGET}.new"
-n changes only gzip header metadata. the decompressed bytes are identical, and omitting volatile metadata makes the payload reproducible. this was checked with:
original=$(sha256sum "$input" | cut -d' ' -f1)
roundtrip=$(gzip -nc "$input" | gzip -dc | sha256sum | cut -d' ' -f1)
test "$original" = "$roundtrip"
first=$(gzip -nc "$input" | sha256sum | cut -d' ' -f1)
second=$(gzip -nc "$input" | sha256sum | cut -d' ' -f1)
test "$first" = "$second"
observed hashes:
original and round trip: 0de50ffa28010b67405d84312b5699e76497fe573de260cfd734383437358956
compressed runs 1 and 2: 6a079b34e5dce85d086cdda1e426de07f0081cde2d673ef1f6e28b2886fd548f
downstream validation
i carried a fail-closed downstream patch that requires exactly one copy of the known source line:
the build-time guard deliberately fails if upstream changes the source line, so the downstream patch cannot silently drift.
summary
on an rpm-ostree fedora asahi atomic deployment, package files in
/usrhave canonical epoch-zero mtimes.update-m1n1passes the u-boot input filename togzip -c; gzip warns that the timestamp is out of range and exits with status 2. becauseupdate-m1n1usesset -e, it aborts before atomically replacingboot.bin.the existing
boot.binremains untouched, so this fails safely, but m1n1, u-boot, and device-tree updates are not applied.environment
quay.io/fedora-asahi-remix-atomic-desktops/silverblue:44update-m1n1or the u-boot package when this was reproduced7.0.13-400.asahi.fc44.aarch64+16kupdate-m1n1-20250713-7.fc44.noarchuboot-images-armv8-2026.04-102.fc44.noarchrpm-ostree-2026.2-1.fc44.aarch64ostree-2026.2-1.fc44.aarch64gzip-1.14-2.fc44.aarch64the relevant source remains the package-owned line from
update-m1n1. rpm verification showed timestamp differences from ostree canonicalization, not a content modification to this line.reproduction
the gzip failure can be reproduced without mounting or writing the system esp:
observed output:
the full command similarly stopped after the warning and never printed its final
m1n1 updated at ...success line. the script had already createdboot.bin.new, but did not reach the comparison, backup, ormvsteps.proposed fix
tell gzip not to encode the source filename or timestamp:
-nchanges only gzip header metadata. the decompressed bytes are identical, and omitting volatile metadata makes the payload reproducible. this was checked with:observed hashes:
downstream validation
i carried a fail-closed downstream patch that requires exactly one copy of the known source line:
ghcr.io/okwalerie/asahi-bluefin:latest@sha256:a98818d86fd1055e8723a29ea1c67f6a82e09cd9e7bd1fa98a9952da416d3a5athe build-time guard deliberately fails if upstream changes the source line, so the downstream patch cannot silently drift.