DF-5820 / verdict.json
{ "finding_id": "DF-5820", "status": "not_reproduced", "reproduced": false, "impact": "none", "confidence": "likely", "verdict": "hammer2_vop_nrename converts the rename-backends ENOENT (source dirent not found; the backend itself documents this happens under fsstress, hammer2_xops.c:621-628) into success at hammer2_vnops.c:2165-2166 and then performs every success side-effect on a media topology that was NOT renamed: rewrites ip->meta.name_len/name_key (:2174-2179) and ip->meta.iparent (:2180-2183), runs hammer2_inode_unlink_finisher on the overwrite target tip (:2194-2196, decrementing its persistent nlinks and marking it ISUNLINKED/DELETING while its dirent survives), and commits cache_rename (:2247-2248), diverging namecache from media. Code path certain; 120s of 4-thread rename churn on the guest did not hit the underlying race (zero xop_nrename: ... ENOENT console messages), so it stays runtime-unproven here.", "exploit_chain": "", "evidence": "README.md full path:line trace; rename_stress.c harness; stress attempt produced 0 backend-ENOENT console hits in 120s.", "kernel_refs": [ "sys/vfs/hammer2/hammer2_vnops.c:2165", "sys/vfs/hammer2/hammer2_vnops.c:2174", "sys/vfs/hammer2/hammer2_vnops.c:2194", "sys/vfs/hammer2/hammer2_xops.c:620" ], "poc_changes": "wrote a 4-thread rename-churn harness (rename_stress.c) to try to hit the documented race; window not hit on a single-master guest.", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 x86_64", "runtime_sec": 150, "guest_dirty": 0, "build_cmd": "cc -O -pthread -o /tmp/rename_stress /tmp/rename_stress.c", "run_cmd": "/tmp/rename_stress /dfpoc 30 ; /tmp/rename_stress /dfpoc 90 ; dmesg | grep -c xop_nrename", "code_hash": "50f00bb9fccc982650733a6ef12d3d3435b4be929dc331ddad8895e40d97e3c8", "notes": "Metadata-integrity bug (nlink corruption of tip, stale iparent, cache/media divergence) under a rare race; severity Low.", "recommended_fix": "Do not mask ENOENT from the rename xop: remove if (error == ENOENT) error = 0; at hammer2_vnops.c:2165-2166 so the VOP returns the error and skips all success side-effects.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "not_testable: trigger is a rare backend lookup race (upstream fsstress class); not hit in 120s of targeted churn.", "fix_evidence": "dmesg grep count 0 after both stress runs." } |