# DF-3306 VERDICT — false-positive-for-now / latent (no runtime test possible)

`expire_upcalls()` (`ip_mroute.c:1423-1428`) frees an mfc's bandwidth
meters with a bare `kfree` loop and never calls `unschedule_bw_meter()`,
unlike FreeBSD. If a scheduled ("<=") meter were ever attached to an
entry that `expire_upcalls` frees, it would remain linked in
`bw_meter_timers[]` after being freed → guaranteed UAF at the next 1 Hz
`bw_meter_process()` pass.

Reachability analysis proves this is **not reachable in the current
code**: bw meters attach only via `add_bw_upcall()` → `mfc_find()`
(`:2286`, and `mfc_find` at `:327-332` only returns entries with
`mfc_stall == NULL`), while `expire_upcalls()` only frees entries with
`mfc_stall != NULL` (`:1400`), and NOCACHE-created stalled entries get
`mfc_bw_meter = NULL` at creation (`:1337`) and never receive meters.
The invariant "stalled ⇒ no meters" holds on every path; the kfree loop
is dead code today. One refactor away from a real UAF, and a pointless
divergence from FreeBSD — hence filed as Info (hardening), confidence
certain about the divergence, speculative about any future trigger.

No PoC is possible (the precondition does not exist); the fix is one
line, included in fix.diff, and the patched kernel built and boots:

```diff
 		while (mfc->mfc_bw_meter != NULL) {
 		    struct bw_meter *x = mfc->mfc_bw_meter;
 		    mfc->mfc_bw_meter = x->bm_mfc_next;
+		    unschedule_bw_meter(x);
 		    kfree(x, M_BWMETER);
 		}
```

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
