DF-3120 / manifest.json
{ "finding_id": "DF-3120", "title": "Unsynchronized UFS quotaon/quotaoff mount-state machine: concurrent Q_QUOTAOFF double-executes teardown (double vn_close -> vnode opencount/refcount corruption, crfree(NOCRED) NULL-deref, dqsync panic on closed quota file)", "verdict": "reproduced", "impact": "panic", "confidence": "certain", "reproduce": { "build": "cc -O -pthread -o /root/qt_race /root/qt_race.c (kernel must be built with 'options QUOTA'; stock X86_64_GENERIC lacks it and quotactl returns EOPNOTSUPP)", "run": "vnconfig -c /dev/vn0 /qt.img && newfs -m 0 /dev/vn0 && mount -t ufs /dev/vn0 /qtmnt && /root/qt_race 100", "expected": "kernel panic <=45s: 'panic: VOP_STDCLOSE: BAD OPENCOUNT' with stack vop_stdclose<-vop_close<-vn_close<-ufs_quotaoff<-ufs_quotactl (double vn_close at ufs_quota.c:519), or 'Fatal trap 12' at crfree+0xc fault va=0x0 (crfree(NOCRED) at ufs_quota.c:521); with fix applied: SURVIVED ... exit 0, guest stays up" }, "kernel_refs": [ "sys/vfs/ufs/ufs_quota.c:495", "sys/vfs/ufs/ufs_quota.c:503", "sys/vfs/ufs/ufs_quota.c:505", "sys/vfs/ufs/ufs_quota.c:517", "sys/vfs/ufs/ufs_quota.c:519", "sys/vfs/ufs/ufs_quota.c:520", "sys/vfs/ufs/ufs_quota.c:521", "sys/vfs/ufs/ufs_quota.c:522", "sys/vfs/ufs/ufs_quota.c:412", "sys/vfs/ufs/ufs_quota.c:437", "sys/vfs/ufs/ufs_quota.c:448", "sys/vfs/ufs/ufs_quota.c:909", "sys/vfs/ufs/ufs_vfsops.c:141", "sys/sys/ucred.h:82", "sys/kern/kern_prot.c:crfree", "sys/kern/vfs_lock.c:354" ], "fix": "fix.diff (per-mount um_quota_lock serializing ufs_quotaon/ufs_quotaoff; quotaon unlocks the quota-file vp before taking the lock)", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Sun Sep 6 20:12:38 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_QUOTA x86_64", "fix_verdict": "Baseline (pristine ufs_quota.c + options QUOTA, INVARIANTS): identical PoC panicked in <=45s with 'panic: VOP_STDCLOSE: BAD OPENCOUNT' via ufs_quotaoff->vn_close (double close). Patched (fix.diff): 300s run (1.5M Q_QUOTAON + 17.8M Q_QUOTAOFF) and a 120s confirmation run both SURVIVED with exit 0, 0 panics in dmesg, mount healthy. An intermediate fix iteration that held the quota-file vp lock across um_quota_lock acquisition deadlocked (found by this validation and corrected: vn_unlock(vp) before lockmgr).", "artifacts": ["README.md", "VERDICT.md", "qt_race.c", "build.sh", "run.sh", "build.log", "run.log", "panic.txt", "panic.diag.txt", "env.txt", "fix.diff", "manifest.json", "verdict.json"] } |