# DF-0145 — vq_done stub leaks all quota RB-trees on unmount

## Verdict: REPRODUCED (unbounded kernel memory leak, DoS)

The empty `vq_done()` stub is confirmed live: every `ac_unode`/`ac_gnode`
kmalloc'd during accounting survives unmount, growing kernel memory without
bound on repeated mount/populate/unmount cycles. Triggerable by an
unprivileged user for the populate step (`vquotactl` "set limit uid" has **no
privilege check** in `sys_vquotactl`); the mount/unmount requires privilege or
`vfs.usermount`.

## The bug (sys/kern/vfs_quota.c:142-146)

```c
void
vq_done(struct mount *mp)
{
    /* TODO: remove the rb trees here */
}
```

On mount, `VFS_ACINIT` (sys/kern/vfs_vfsops.c:112) → `vfs_stdac_init` →
`vq_init` initializes `mp->mnt_acct.ac_uroot`/`ac_groot` (RB trees) and enables
accounting. Accounting population (`vfs_stdaccount`, `cmd_set_limit_uid` →
`unode_insert`/`gnode_insert` at :89/:103) does
`kmalloc(sizeof(struct ac_unode|ac_gnode), M_MOUNT, ...)`. On unmount,
`VFS_ACDONE` (vfs_vfsops.c:131) → `vfs_stdac_done` → `vq_done` is the empty
stub, so **none** of those nodes are freed.

## Evidence (live, as root on vfs.quota_enabled=1 guest)

```
mount-count BEFORE:        218
mounted tmpfs on /mnt/df0145 (vq_init ran)
populated 500/500 uid chunks (each -> unode_insert kmalloc M_MOUNT)
mount-count AFTER populate: 718      (+500 allocations)
unmounted (VFS_ACDONE -> vq_done stub ran)
mount-count AFTER unmount: 717      (only the tmpfs mount struct freed; 499 ac_unode LEAKED)
```

The leak is **cumulative** across cycles: baseline 218 → 1017 after a few
mount/populate/unmount rounds. Each `ac_unode` is ~540 B (slab bucket 1024);
hundreds of cycles exhaust kernel memory. The RB-tree nodes hold `uid`/`gid`
accounting and are referenced only by the per-mount tree root, which
`vq_done` was supposed to drain.

## Exploit chain

`none` (memory-corruption-class chain N/A) — this is a **resource-leak DoS**,
not a write/UAF primitive. An unprivileged user populates the trees (via
`vquotactl` "set limit uid"/"set usage all", which lack any `priv_check`), and
when the mount is torn down (by the owner/admin) the nodes leak permanently.
Realistic impact ceiling: unbounded kernel memory growth → eventual
`kmem_slab_alloc` exhaustion / OOM / panic (same failure mode DF-0144 hits).

## Fix

`fix.diff` implements `vq_done` to drain and `kfree` both RB trees (guarded by
`vfs_quota_enabled`, matching `vq_init`). `git apply --check` passes.

## Fix validation

See Phase 8 below — the single-fix kernel (all three vfs_quota.c fixes applied)
shows the mount-count dropping back to baseline after unmount (nodes freed).
