โฌข DragonFlyBSD Kernel Audit
DF-2705 / verdict.json
โ† back to finding โ†“ download raw
{
  "finding_id": "DF-2705",
  "status": "untested",
  "reproduced": 0,
  "impact": "none",
  "confidence": "likely",
  "verdict": "vop_write's quota glue (sys/kern/vfs_vopops.c:476-478, 489, 495-497) never charges VFS_ACCOUNT usage for files with va_nlink==0, while vop_nremove (:1665-1668) refunds the entire size on last-link removal and vq_write_ok checks against only the charged usage โ€” so unlinking an open fd then writing unbounded completely bypasses per-uid/gid/mount quota limits (and N concurrent writers can TOCTOU-overshoot by (N-1)x limit). Certain as logic, but the whole mechanism is gated on vfs_quota_enabled (sys/kern/vfs_quota.c:111-113), default 0, boot-tunable only (CTLFLAG_RD) โ€” non-default admin config. Phase V skipped: reproducing requires booting the shared guest with vfs.quota_enabled=1 and vquota limit setup for a Low accounting-bypass; every line of the chain was verified statically.",
  "exploit_chain": "open+write to limit -> unlink while open (usage refunded, nlink=0) -> keep writing through fd: checks pass trivially, charges never happen -> unbounded growth on quota-limited mount",
  "evidence": [
    "sys/kern/vfs_vopops.c:476-478 do_accounting gated on va_nlink>0",
    "sys/kern/vfs_vopops.c:489 vq_write_ok check vs charged usage",
    "sys/kern/vfs_vopops.c:495-497 charge skipped when do_accounting==0",
    "sys/kern/vfs_vopops.c:1665-1668 last-link removal refunds full size",
    "sys/kern/vfs_quota.c:111-113 vfs_quota_enabled default 0, boot tunable only",
    "findings/poc/DF-2705/VERDICT.md full chain + cross-refs"
  ],
  "kernel_refs": [
    "sys/kern/vfs_vopops.c:472",
    "sys/kern/vfs_vopops.c:477",
    "sys/kern/vfs_vopops.c:489",
    "sys/kern/vfs_vopops.c:495",
    "sys/kern/vfs_vopops.c:1666",
    "sys/kern/vfs_quota.c:111"
  ],
  "poc_changes": "no PoC built: needs non-default boot tunable + vquota setup on the shared guest; Low severity",
  "attempts": 0,
  "guest_uname": "",
  "runtime_sec": 0,
  "guest_dirty": 0,
  "build_cmd": "",
  "run_cmd": "",
  "code_hash": "",
  "notes": "Cross-file item for orchestrator (belongs to sys/kern/vfs_quota.c row): vfs_stdaccount/unode_insert kmalloc(M_WAITOK) under mp->mnt_acct.ac_spin (vfs_quota.c:153-165) โ€” blocking alloc under spinlock, same pattern at :236-306. Recommend separate finding there.",
  "recommended_fix": "Charge unlinked-open files (drop the va_nlink>0 gate on do_accounting in vop_write) or account on block allocation inside the FS; refunds in vop_nremove already balance."
}