# VERDICT — DF-5124

**status: untested** (guest is KVM; code path dormant — cannot be exercised)
**reproduced: false · impact: none (observed) · confidence: speculative**

## Narrative

Claim: `hyperv_md_uninit()` (`hyperv_machdep.c:208-225`) frees the
reference-TSC DMA page (`:222`) without quiescing CPUs that may currently
be inside the TSC-reading seqlock loop (`:96-125`) using a pointer loaded
before the teardown began.

Lifetime trace (all path:line verified in-tree):

1. `hyperv_md_init()` allocates `hyperv_ref_tsc.tsc_ref`
   (`hyperv_machdep.c:186-188`), enables the MSR, registers
   `hyperv_tsc_cputimer` and publishes `hyperv_tc64 = hyperv_tsc_lfence/
   mfence` (`:201-205`).
2. Runtime readers: vmbus per-CPU timer code calls `hyperv_tc64()`
   (`vmbus.c:366` in the timer reload path, `vmbus.c:916` in
   `vmbus_timer_oneshot`) — executed in interrupt context, on any CPU.
   The HYPERV_TSC macro caches the page pointer at entry (`:96`) and then
   reads `tsc_seq`/`tsc_scale`/`tsc_ofs` repeatedly (`:99-118`).
3. Teardown (SYSUNINIT `hyperv_uninit`, `hyperv.c:331-344`; the file is
   builtin — `sys/platform/pc64/conf/files:203-205` — so this is
   shutdown-only): `cputimer_deregister()` (`:215`) switches
   `sys_cputimer` away, `hyperv_tc64` is restored to the MSR reader
   (`:217`), then the page is freed (`:222`).
   **Nothing between :217 and :222 guarantees an in-flight reader on
   another CPU has left the loop.** A reader that loaded `tsc_ref` at
   `:96` before `:217` and is spinning/reading between `:217` and `:222`
   dereferences freed DMA memory: UAF read.
4. Consequence bounded to: garbage `uint64_t` time values (vmbus timer
   mis-fire) or a fault if the mapping is torn down → panic during
   shutdown. No unpriv-user trigger, no info leak (page holds only the
   TSC record), shutdown-gated.

Why "speculative": the window is real by construction (no synchronization
exists between the free and in-flight readers), but I cannot demonstrate
it — the audit guest is KVM (`env.txt`), where `hyperv_identify()` fails
(`hyperv.c:207-208`) and this code never runs; even on a Hyper-V guest it
is a probabilistic SMP race at reboot.

Sibling asymmetry *not* re-reported: `hyperv_tsc_cpucounter` is registered
in `md_init` (`:203`) but never deregistered — already noted in the
pass-2 hyperv.c review (no `cpucounter_deregister` API exists in
kern_cputimer.c).

## Fix validation

Not applicable (Low-class, shutdown-only, dormant on the guest).

## 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.
