# DF-2774 — stale `vp->v_pfsmp` used via `mountlist_exists()` after nullfs unmount

## What this proves

`_cache_setvp()` (sys/kern/vfs_cache.c:1386-1389) stores a **raw, unheld,
never-cleared** pointer `vp->v_pfsmp = mp` into the *lower* filesystem's
vnode whenever that vnode is resolved through a nullfs mount.

`vq_vptomp()` (sys/kern/vfs_quota.c:421-433) dereferences that stale pointer
after "validating" it with `mountlist_exists()` (sys/kern/vfs_mount.c:692-708),
which only does a **pointer comparison walk of the mountlist under the shared
mountlist token — it takes no reference and provides no lifetime guarantee**
(the source FIXME at vfs_mount.c:689-691 admits this).

Consequences:
1. After the nullfs mount is unmounted and its `struct mount` is kfree'd,
   a *fresh* mount that reuses the same kfree'd chunk makes
   `mountlist_exists(stale)` return **1** (the new, unrelated mount is on the
   list at the same address).
2. `vq_vptomp()` then returns the stale pointer, and VFS accounting
   (`VFS_ACCOUNT` at sys/kern/vfs_vnops.c:325, `vq_write_ok` at
   sys/kern/vfs_vopops.c:487-492) charges / enforces **against the wrong,
   unrelated mount**.
3. In the race window (exists() passes -> unmount completes -> kfree ->
   use), `VFS_ACCOUNT`/`vfs_stdaccount` (sys/kern/vfs_quota.c:149-172)
   operates on freed `struct mount` memory (stale `mnt_op` read,
   `spin_lock(&mp->mnt_acct.ac_spin)` write, `ac_bytes += delta` with an
   attacker-influenced delta). On this kernel's slab allocator the freed
   chunk retains its contents, so the practical outcome is silent corruption
   of freed-memory state / wrong-mount accounting rather than a wild write.

Deterministic user-visible manifestation (needs `vfs.quota_enabled=1`, a
boot tunable — default 0):

* extend a file **through the lower mount** whose vnode has a stale
  `v_pfsmp` -> the write is quota-checked against the *new, unrelated*
  nullfs mount -> **EDQUOT from a tmpfs that has no limits**, or
* `: > lowerfile` (O_TRUNC) -> `vfs_stdaccount(freed/wrong mp, uid, gid,
  -osize)` -> the unrelated mount's reported usage goes **negative**.

## Build

No compilation needed — pure shell against stock userland
(`/sbin/mount_null`, `/sbin/vquota`, `dd`, `su`).

## Run

As root on the guest (the actor is unprivileged user `qa`):

    ./run.sh

## Expected output (success criteria)

1. CONTROL append through the lower mount with NO nullfs alive: succeeds.
2. `vquota set limit /mnt/alias2 10`, then the *same* append through the
   lower mount: fails with **Disk quota exceeded (EDQUOT)** — enforcement
   against the wrong mount (the stale `v_pfsmp` address now equals
   alias2's `struct mount`).
3. `vquota get usage /mnt/alias2` reports **negative** bytes after an
   O_TRUNC through the lower mount (the `-osize` account delta landed on
   alias2).

## Environment

* DragonFly 6.5-DEVELOPMENT #0 (stock INVARIANTS kernel)
* `vfs.quota_enabled=1` added to /boot/loader.conf (tunable; sysctl is RD)
* tmpfs lower mount, two sequential nullfs mounts (address reuse via
  M_MOUNT zone LIFO)
