DF-3123 / verdict.json
{ "finding_id": "DF-3123", "status": "untested", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Latent-only: every affected function (ext2_htree_add_entry, ext2_htree_create_index, ext2_htree_writebuf, ext2_htree_split_dirblock, ext2_htree_insert_entry*, ext2_append_entry) is dead code in the stock kernel behind the #if 0 at sys/vfs/ext2fs/ext2_lookup.c:920-941, so nothing is reachable at runtime. Documented for any future re-enable: (1) ext2_htree.c:852-858 memcpy of dst_ent_num*8 on-disk-count-derived bytes into a blksize buffer overflows by up to ~256KiB (gated by DF-0850s missing interior node_limit validation, plus the :475-479 memmove write); (2) four error paths brelse() buffers already consumed by bwrite() (DFLY bwrite releases unconditionally, sys/kern/vfs_bio.c:1000) -> buf double-release/UAF on any index-write I/O error (:457-459+:958-959, :882-885+:950-951, :938-941+:952-953, :742-746+:765-767); (3) u16 reclen truncation to 0 for 64KiB fs blocks (:527-528, :644-645). No guest verification performed (unreachable code).", "exploit_chain": "", "evidence": [ "findings/poc/DF-3123/VERDICT.md (three defects, path:line)", "findings/poc/DF-3123/fix.diff (illustrative double-brelse fix)" ], "kernel_refs": [ "sys/vfs/ext2fs/ext2_htree.c:852-858", "sys/vfs/ext2fs/ext2_htree.c:475-479", "sys/vfs/ext2fs/ext2_htree.c:454-459", "sys/vfs/ext2fs/ext2_htree.c:882-885", "sys/vfs/ext2fs/ext2_htree.c:938-941", "sys/vfs/ext2fs/ext2_htree.c:742-746", "sys/vfs/ext2fs/ext2_htree.c:527-528", "sys/vfs/ext2fs/ext2_lookup.c:920-941" ], "poc_changes": "n/a (analysis-only; no PoC exists for dead code)", "attempts": 0, "guest_uname": "n/a", "runtime_sec": 0, "guest_dirty": 0, "build_cmd": "n/a", "run_cmd": "n/a", "code_hash": "", "notes": "Phase V intentionally skipped (Info, unreachable code). fix.diff is illustrative only, never applied to sys/.", "recommended_fix": "If re-enabling the write path: validate interior node limit == ext2_htree_node_limit (folds into DF-0850s fix), stop touching buffers after bwrite() returns (bwrite consumes), and clamp/avoid u16 reclen math for 64K blocks." } |