# 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: ```sh 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 `MAXPATHLEN` target; - 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.