Skip to content

update-m1n1 aborts on ostree epoch-zero u-boot mtime #71

Description

@okwalerie

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions