Files
erofs-freebsd-out-tree/docs/pre15-stage0/P15-083.md
T
2026-08-18 09:20:44 +02:00

5.0 KiB

P15-083 Stage0 Decision

Status: GO. G04 authorizes B27 for all three non-LZ4 codecs. The source batch must preserve the exact policies below and may not import the P15-062 LZ4 STOP rule.

The gate is bound to DUT BASE 68bbe94c44e35d53cec8ab55d007f40b01cf0502, FreeBSD source HEAD 106727738dcfb6c001b46f25363b91cece970085, erofs-utils 1.8.6, liblzma 5.8.1, zlib 1.3.1, and libzstd 1.5.7.

Authoritative Run

The gate ran from /work/erofs-freebsd-pre as:

timeout -k 10 240 repo-pre-15/tests/pre15/gates/P15-083.sh \
    --base 68bbe94c44e35d53cec8ab55d007f40b01cf0502 \
    --output planning/pre15/evidence/20260815T142600Z-G04-P15-083/gate-output

It returned 0 and recorded GO. Evidence is rooted at planning/pre15/evidence/20260815T142600Z-G04-P15-083/. The authoritative script SHA-256 is 6847541266b0668ad12442ffb54b67a772a29ed8ebe6fba0e1e25214db16b2c2, the input SHA-256 is b3c71b4ae03c6f9511246813952aab3178a1451433ece96f04562ec7cc6c1d1e, and the result SHA-256 is b9431b3819d64cdf940dff05ce7bc0e0bdf44c3ec647c90592052af5f7b3e544.

Decision Rule

P15-083 is GO only if LZMA, Deflate, and Zstd each have a reproducible real EROFS fixture, an independent consumed-byte oracle, and a codec-specific policy that distinguishes EROFS leading zero padding from unread nonzero bytes. Any missing codec oracle, legal image rejected by the proposed full-stream policy, or inability to distinguish trailing garbage makes the whole candidate STOP.

Reproducible Corpus

erofs-utils 1.8.6 twice generates each fixed-time, fixed-UUID, root-owned, xattr-free image from the same 151,552-byte source. Matching fsck extraction reconstructs the complete source. The image hashes are:

Codec Image SHA-256 Selected real extent Leading zero padding Stream
LZMA c26cf15844fe45a21a746bacbad2ef551c683bb9b2538de7a7eced37d8eadff9 4,096 + 4,096 3,556 540
Deflate 39455150c3e999bb7ae6c36402c15a408a5679726b6d099e7d121e009ef43af6 28,672 + 4,096 1,479 2,617
Zstd b905803f0e08500cc3c6cfe07a95fe027859165acae19ca8865856af256f32ca 4,096 + 4,096 1,092 3,004

The leading zero bytes are legal EROFS pcluster padding. They are removed by the common dispatch before the codec callback, matching Linux z_erofs_fixup_insize(). Every remaining legal stream reaches the format end, consumes every byte, reproduces the selected logical extent, and leaves its output guards intact.

Per-Codec Policy

  • Deflate: a full raw stream must reach Z_STREAM_END with no unread input. The independent zlib decoder consumes 2,617 of 2,625 bytes after an 8-byte nonzero tail and reproduces the output. fsck also accepts that mutation, as does the Linux streaming loop when output is already full, but the bytes are not EROFS leading padding and no mkfs fixture emits them. The audited FreeBSD full policy rejects them with positive EINTEGRITY (97).
  • LZMA: MicroLZMA stores no end marker and requires an exact compressed size. The legal 540-byte stream consumes all bytes. Adding the same tail produces liblzma status 9 after consuming 540 of 548 bytes; fsck rejects it and the FreeBSD policy returns 97.
  • Zstd: exactly one frame must finish with no unread input. The library finds frame end after 3,004 of 3,012 bytes with the tail present; fsck rejects the source-size mismatch and the FreeBSD policy returns 97. A concatenated or skippable second frame is not EROFS pcluster padding.

This is deliberately codec-specific. It aligns Linux's non-LZ4 leading-padding placement and stream completion semantics without copying the Linux wrappers' implicit unread-byte acceptance into the FreeBSD provider path.

Partial, Corruption, and Cleanup

The independent libraries decode real-stream prefixes that match the full slice: Deflate produces 3,587 bytes after consuming 715, LZMA produces 4,096 after consuming 352, and Zstd produces 4,096 after consuming 1,457. Replacing the final 64 stream bytes with zero begins strictly after each partial consumption boundary. The same partial request still succeeds and matches; full decode and fsck both fail for all three codecs, with the audited FreeBSD policy mapping the full failure to 97. Removing the final compressed byte also returns 97 for all three.

Every library path reports cleanup complete and unchanged guards. Frozen zdata.c releases metadata or physical input after the callback, frees failed decoded output, and publishes only successful output. The owned temporary tree was removed. QEMU, protected PID 26318, port 9222, and the shared base image were not touched. The full feature suite was not run.

Consequence

B27 may now make these three existing policies explicit in the exact planned write set and add TC176 host/QEMU coverage. It must preserve positive FreeBSD errno, optional Zstd ABI, provider/GEOM ownership, input release, failed-output free, and successful-output lifetime. The generated images, extracted files, oracle source, and oracle binary remain temporary and are not committed.