# DF-5640 — VERDICT

**Status: reproduced** (impact: panic / boot-time DoS, severity Low — privileged
preconditions) — **fix validated (fixed)**.

## The finding

`sys/cpu/x86_64/misc/cputimer_tsc.c:145-156` — `tsc_cputimer_register()` copies
the hardware/calibration-derived global `tsc_frequency` into `tsc_cputimer.freq`
with no validation, then `cputimer_select(&tsc_cputimer, 0)` →
`cputimer_set_frequency(timer, 0)` → `sys/kern/kern_cputimer.c:190`
`(1000000LL << 32) / freq` — integer division by zero (#DE) → fatal trap →
kernel panic during boot (SI_BOOT2_POST_SMP). The `regcnt:` path likewise
installs `tsc_cpucounter.freq = tsc_frequency` unvalidated (cputimer_tsc.c:162).

Preconditions for `tsc_mpsync == 1` with `tsc_frequency == 0`:
- `hw.tsc_cputimer_force=1` loader tunable (clock.c:871 sets `tsc_invariant`,
  clock.c:1522 sets `tsc_mpsync`) — the tunable the kernel itself recommends
  for qemu (clock.c:863-871) — combined with `startrtclock()` calibration
  returning 0 (clock.c:980-1043; a non-ticking TSC measures 0), or
- `ncpus == 1` with CPUID-invariant TSC (clock.c:1513-1516 sets `tsc_mpsync=1`
  unconditionally) with failed calibration.

No unprivileged trigger exists: the file has zero runtime attack surface (boot
SYSINIT + loader tunables only). Hence Low, not High.

## How it was verified (guest dfbsd-qemu, kernel of 2026-07-02, #0)

1. **Live introspection** (`env.txt`): stock guest runs HPET
   (`kern.cputimer.name: HPET`), `hw.tsc_mpsync=0`, `hw.tsc_invariant=0`,
   `hw.tsc_frequency=3600011246` — on the stock config the file's registration
   early-returns at cputimer_tsc.c:134.

2. **Production-path proof** (`forced_boot_dmesg.txt`): booting with
   `hw.tsc_cputimer_force=1` (the real documented tunable, no harness) runs the
   genuine path end-to-end: the mpsync qualification state machine
   (`TSC testing MP synchronization ... TSC is MP synchronized`,
   clock.c:1567-1705) then the real `tsc_cputimer_register()` prints
   `TSC: cputimer freq 3600008821` (cputimer_tsc.c:148) and
   `kern.cputimer.name` becomes `TSC`.

3. **Baseline panic** (`run.log`, `panic_serial.log`, `panic.txt`): a KLD
   harness replays cputimer_tsc.c:145-156 verbatim (replica struct,
   `tsc_frequency = 0`, real `cputimer_register()`/`cputimer_select()`
   production entry points; replica `pri = CPUTIMER_PRI_DUMMY-1` so the sink
   call at kern_cputimer.c:99 — which precedes the pri check — is the only
   thing that can fire). Result, live serial console:

   ```
   DF5640: live state: tsc_mpsync=1 tsc_invariant=1 tsc_frequency=3600008821 sys_cputimer=TSC (3600008821 Hz)
   DF5640: replaying cputimer_tsc.c:145-156 with freq=0 (divide error at kern_cputimer.c:190 expected)
   TSC: cputimer freq 0
   Fatal trap 18: integer divide fault while in kernel mode
   kernel: type 18 trap, code=0
   Stopped at      cputimer_select+0x29:   divq    %rcx,%eax
   db>
   ```

   Guest dropped to DDB, ssh dead, `vm.sh status` → down. The faulting
   instruction is `divq` inside **cputimer_select** (production code); the
   harness never executes the faulting instruction itself.

   *Methodology note*: a boot-loaded KLD cannot put the globals into the
   precondition state before `tsc_cputimer_register` runs — preloaded modules
   link at SI_BOOT2_KLD (0x1e00000), after SI_BOOT2_POST_SMP (0x1cc0000).
   Proven empirically: a forcing SYSINIT at SI_BOOT2_FINISH_SMP from a
   loader-loaded module executed after the whole registration pass (dmesg
   ordering showed `DF5640: FORCING ...` with no `TSC: cputimer freq` line,
   and the boot completed). Hence the kldload-time verbatim replay.

4. **Fix validation** (`fix.diff`, `fix_build.log`, `fix_run.log`,
   `fix_forced_boot.txt`): fix applied inside the guest's `/usr/src` copy
   (producer guards in cputimer_tsc.c at both the mpsync path and the `regcnt:`
   path + sink guard in kern_cputimer.c), `make nativekernel
   KERNCONF=X86_64_GENERIC` + `installkernel` (RC=0), reboot into the patched
   kernel (#1 Fri Oct 9 03:49:03 UTC 2026). Identical harness:

   ```
   DF5640: replaying cputimer_tsc.c:145-156 with freq=0 ...
   TSC: cputimer freq 0
   cputimer: refusing zero frequency for DF5640 (cputimer unchanged)
   DF5640: NOT REACHED on an unpatched kernel
   SURVIVED-rc=0
   kern.cputimer.name: HPET      (unchanged, system healthy)
   ```

   No trap, module load returns, guest stays up. Legit-path regression check on
   the patched kernel: `hw.tsc_cputimer_force=1` boot still prints
   `TSC: cputimer freq 3600009374` and selects `kern.cputimer.name: TSC` —
   the guards do not affect the normal registration path.

## Why not higher severity

Memory corruption this is not: it is a deterministic #DE. The operand
(`tsc_frequency`) is set only at boot from CPUID/calibration; all three
involved globals are read-only sysctls afterwards; the forcing tunable lives in
`/boot/loader.conf` (root). The realistic scenario is a forced-TSC
misconfiguration on a machine/VM whose TSC calibration fails → unbootable
system (local DoS at boot, admin-fixable). The `cpucounter` half is currently
dead surface: `cpucounter_find()`/`cpucounter_find_pcpu()` have no callers
outside kern_cputimer.c in this tree.

## Attempts

1. Boot-forcing SYSINIT in loader-loaded KLD — failed by design (module
   linking happens after POST_SMP); documented, valuable negative ordering
   evidence.
2. Same module via /boot/modules — directory absent on guest image; installed
   to /boot/kernel; ran but (per 1) too late to affect the production path.
3. kldload-time verbatim replay — panicked deterministically at
   `cputimer_select+0x29 (divq)`.

Guest reset to the clean `with-src` snapshot after validation.

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