# VERDICT — DF-4735

## What reproduced, exactly
On the QEMU/KVM guest (Intel Xeon E3-1275 v5 host, `-cpu host`), a kernel module
(`msrtest.c`, this pack) executing the exact `coretemp.c:599` instruction in kernel
context produced:

```
msrtest: rdmsr_safe(MSR_THERM_STATUS=0x19c)...
msrtest: rdmsr_safe -> error 14 (MSR faults on this VMM)
msrtest: raw rdmsr now (coretemp.c:599 path) -- expect #GP panic

Fatal trap 9: general protection fault while in kernel mode
cpuid = 1; lapic id = 1
instruction pointer = 0x8:0xffffffff8260005d
...
kernel: type 9 trap, code=0
CPU1 stopping CPUs: 0x0000003d
Stopped at      msrtest_modevent+0x5d:  rdmsr
db>
```

Guest dead in DDB (`vm.sh status` → down). Full console capture in `panic.txt` /
`run.log`.

## Why coretemp itself did not panic (the honest gap)
`coretemp` is compiled into X86_64_GENERIC (`device coretemp`, config:188) and its
identify() gates on `cpu_thermal_feature & CPUID_THERMAL_SENSOR` (coretemp.c:200):

1. Stock guest CPU (qemu64 under KVM): CPUID leaf 6 returns 0 → identify exits →
   coretemp inert (verified: no hw.sensors.coretemp children; `kldload coretemp`
   → "already loaded or in kernel").
2. Guest rebooted with `-cpu host` (Skylake): leaf 6 EAX = **0x4 (ARAT)** — KVM
   **strips the DTS bit even on host passthrough** (`sysctl -a | grep Thermal`).
   identify still exits.

KVM strips the DTS bit *because* it does not virtualize MSR 0x19c — and the msrtest
run proves both halves: the safe read faults (error 14), the raw read takes a fatal
trap 9. So the platform class "CPUID advertises DTS without the MSR" is real, known to
VMM vendors, and is exactly the "PIII reports thermal sensors but GPFs" scenario the
driver's own identify() comment (coretemp.c:192-196) documents on real silicon. On any
such platform, the stock kernel's coretemp sensor task (registered coretemp.c:455-464,
2 s period) executes the raw read in softclock/kthread context ~2 s after boot →
unrecoverable kernel panic, no user interaction. The trigger module substitutes only
the CPUID advertisement (root kldload on a platform where the VMM already supplies the
faulting MSR).

Upstream FreeBSD re-engineered this exact surface (live do_cpuid(0x06) re-check in
identify + fault-safe x86_msr_op reads on the sysctl path), confirming the class is
recognized.

## Exploit chain
None — this is a denial-of-service/panic class finding (kernel #GP in the sensor
task). No memory corruption, no privilege boundary.

## Fix validation
`fix.diff`: `coretemp_msr_fetch` → `rdmsr_safe` for both MSRs, error return; both
sensor tasks map fetch failure to `CORETEMP_TEMP_INVALID` (sensor_set_invalid path,
coretemp.c:613-619 already handles it). Build-validated in the same nativekernel run
as DF-4733/4734 (BUILD_RC=0, -Werror, coretemp.c compiled — build.log).
The baseline run itself demonstrates the patched semantics on the faulting platform:
`rdmsr_safe(MSR_THERM_STATUS)` returns error 14 instead of trapping (first half of the
msrtest output). In-driver runtime delta not observable on this guest because KVM
masks the DTS bit and coretemp never attaches.

## Non-findings recorded for coretemp.c (pass 2, with reasoning)
- KKASSERT(sens_idx < sc_nsens) at :376 — invariant holds: at CORE_LEVEL,
  popcount(node->members) == node->child_no in every tree shape built by
  subr_cpu_topology.c build_topology_tree (:115-154: members = OR of exactly
  child_no single-member leaves) and the AMD compute-unit fixup (:284-341 merges
  1-member leaves only). Guest (6 CPU, cores_per_chip=6, no HT) takes the CORE-leaf
  child_no==0 path → node=NULL → nsens=1 (:361-364).
- detach UAF — none: sensor_task_thread holds thr->lock across st->func
  (kern_sensors.c:307-340), so sensor_task_unregister2 (:252-267) cannot return while
  a task is in flight; sc/sc_sens freed in coretemp_detach (:478-495) are never
  touched again; st itself is freed by the thread (:328-331), not the caller.
- Sensor-slot bookkeeping: skipped CPUs leave zeroed c_sensdev slots; detach skips
  NULL c_sensdev (:483-484). Consistent.
- coretemp_msr_temp handles READ_VALID (:510-513) — the amdtemp DF-4461
  assert-on-invalid shape does NOT exist here. pkg temp has no VALID bit defined
  upstream either (matches Linux/FreeBSD).
- No div-by-zero anywhere (only subtraction), no attacker-controlled input at all
  (no ioctls, no writable sysctls, no user pointers; sensor reads are read-only).
- Tjmax table (:271-331): [70,110] sanity range; rdmsr_safe already used for
  TEMPERATURE_TARGET.
- devctl_notify buffers (:528-538, :574-582): ksnprintf-bounded, small ints. Safe.
- Observation (kern_sensors/acpi_cpu territory, cross-ref only): the 6 acpi_cpu
  sensordevs on the guest are not reachable as hw.sensors.* sysctl nodes — out of
  scope for this file.

## Bottom line
Low-severity, mechanism-proven panic DoS: raw rdmsr in the periodic sensor task on
CPUID-lying platforms; guest-reproduced consequence (fatal trap 9 on MSR_THERM_STATUS
read); fix build-validated with the graceful-degradation path demonstrated live.

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