5.1 KiB
P15-019 Stage0 Decision
Status: GO. G03 authorizes B16 for P15-019 only. P15-046 remains the B01
test-only legacy xattr prefix fallback contract; it neither changes this
decision nor authorizes any exact-header or xattr behavior change.
The decision is bound to DUT BASE
d645feb720c7022d2138d2a62eb72c022eb75351, FreeBSD source HEAD
106727738dcfb6c001b46f25363b91cece970085, erofs-utils source HEAD
7db78788b000999e2de88decd2ba90654f26171c, and
mkfs.erofs (erofs-utils) 1.8.6.
Authoritative Run
The gate ran from /work/erofs-freebsd-pre/repo-pre-15 as:
umask 077
timeout -k 10 240 tests/pre15/gates/P15-019.sh \
--base d645feb720c7022d2138d2a62eb72c022eb75351 \
--output /work/erofs-freebsd-pre-evidence/pre15/\
20260815T093800Z-G03-P15-019-umask-fix/gate-output
It returned zero with GO. The authoritative hashes are:
- gate script:
afa20cbd28ca9dfc8064596a312248756ed7cde54398efb5ef713818cc04ea54 - gate input:
291bf12838981ef650e16bbf7381eaa9b2921de957e97dec46e6a573750a19b8 - result:
bb52e1a88cb09554a51432ec545ed98d5509a529832141ed0ce83b0c336be5bb - cases:
0c12cdce8b3ed37e85f349af0715a728d4acabbb758451fb65546dd9836066b5 - fixture manifest/set:
5e99e5ad9112508991e78ae6e65928973d6b0da78285a059894bed06010cf373 - semantics:
090e6b0cd5eaa197f17da12daf29f30bd8f337d3d4ae2f0f4f5819ad41e906f9 - cleanup:
8e3b52610ee1492262494d00c48bf66ea04d313ab9ac1ef27565fa0e607b9a97
An additional independent replay from umask 077 produced the same result,
cases, fixture manifest, semantics, and cleanup hashes byte for byte. The gate
sets umask 022 internally because erofs-utils records the packed fragment
inode's source mode; this makes the fixture set independent of its caller.
Real EROFS Fixture Oracle
The gate creates 35 deterministic EROFS images and seven external chunk blobs in owned output. Nothing is committed as an image, blob, binary, or KLD. Each of the five required storage paths has these seven cases:
- normal short target;
- normal 1,024-byte
MAXPATHLENtarget; - zero-byte target;
- embedded NUL at the first, middle, and last byte;
- 1,025-byte over-limit target.
Inline positives are native mkfs symlinks. Plain, chunk, compact compressed
ztailpacking, and whole-file fragment cases start as real mkfs regular-file
carriers because the host cannot create a symlink containing NUL and mkfs does
not select those layouts for symlinks. The transform changes only inode mode,
the root dirent type, and, for empty cases, inode size, then recomputes the real
EROFS checksum. Chunk data remains on a real --blobdev; fragment data remains
in the real packed inode. Changed-byte offsets are recorded for every case.
The independent Python parser reads the superblock, checksum span, inode,
dirent, layout, and target bytes directly. It resolves chunk indexes and the
external blob, decodes compact inline-pcluster raw LZ4 without a DUT helper,
and resolves the whole-fragment offset through the packed inode. It does not
compile, call, or inject values into any DUT internal function. dump.erofs
is only a layout/type cross-check. All legal targets also pass
fsck.erofs --extract and reproduce the exact source bytes.
The independent decision model returns positive FreeBSD EINTEGRITY (97) for
empty or embedded-NUL targets, positive ENAMETOOLONG (63) before target I/O
for size greater than MAXPATHLEN, and success for exact non-NUL bytes. No
trailing NUL is required. All 35 expected results match, so every layout has a
bounded positive and negative oracle as required by G03.
Linux and FreeBSD Semantics
Linux erofs_fill_symlink() validates only flat-inline fast symlinks while
building i_link; it uses kmemdup_nul()/strlen() and returns negative
-EFSCORRUPTED. Non-inline Linux symlinks use page_get_link. That page/cache
shape is not a FreeBSD implementation contract.
FreeBSD enters through VOP_READLINK on a vnode and currently streams through
erofs_readlink_target, the common map/read path, GEOM or the compressed
backing path, and uiomove. It has no Linux i_link or page-get-link path and
uses positive errno. B16 must therefore validate the complete immutable target
before any uiomove, use the existing layout-specific map/read machinery, and
keep the scan bounded by MAXPATHLEN=1024.
The 1,024-byte case is a successful readlink(2) byte target. Pathname follow
may still return ENAMETOOLONG when that target plus the remaining pathname
exceeds FreeBSD's namei buffer; that VFS result is distinct from the on-disk
target validator. The 1,025-byte inode is rejected by B16 before target I/O.
Scope and Cleanup
The gate did not modify src/**, build a KLD, start QEMU, or run a feature
suite. It observed but did not signal or otherwise alter protected PID 26318,
port 9222, or /work/debug-qemu/local/vm-freebsd-build.qcow2.bp; their recorded
identity was unchanged before and after the run. Owned temporary source and
extract directories were removed, with zero leftovers.
B16 may now modify only its planned source/test write set and must pass the specified host TC166, D, zstdio0 build, and targeted TC166 QEMU acceptance.