corecstat attaches on any Intel CPU outside family 06h β probe()/attach() model whitelist has no else-return, so the driver matches (e.g.) family-0x0F Pentium 4 and runs with an unassigned sc_version
Summary
Neither probe nor attach has an else-return for cpu_family != 0x06 - any non-06h Intel CPU attaches with sc_version=0 (Nehalem treatment). Guest-reproduced on stock QEMU CPU (family 0x0F): 6 devices attach, 17 rdmsr_safe rejections, phantom sensordev, 1Hz refresh per cpu; no panic (rdmsr_safe gating saved it - the DF-4735 family is defended here). Family-gate fix validated (attaches nothing).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4779 Β· 9 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 3.2 KB | β raw | |
| VERDICT.md | β | 3.0 KB | β raw | |
| build.sh | β | 66 B | view raw | |
| run.sh | β | 90 B | view raw | |
| build.log | β | 1.1 KB | view raw | |
| run.log | β | 4.0 KB | view raw | |
| env.txt | β | 745 B | view raw | |
| fix.diff | β | 703 B | view raw | |
| verdict.json | β | 2.9 KB | view raw |
DF-4779 β corecstat attaches on any Intel CPU outside family 06h (missing return ENXIO for cpu_family != 0x06)
File: sys/dev/powermng/corecstat/corecstat.c
Severity: Info (functional/robustness β no memory-safety impact) Β· Confidence: certain
Bucket: base:powermng
What the bug is
Both corecstat_probe() (corecstat.c:183-236) and corecstat_attach() (corecstat.c:259-324)
gate the model whitelist on if (cpu_family == 0x06) { switch (cpu_model) { ... default:
return (ENXIO); } } β but there is no else branch. For an Intel CPU with any family
other than 06h (e.g. family 0x0F Pentium 4 / NetBurst Xeon, family 05h), the whitelist is
skipped entirely and corecstat_probe() returns BUS_PROBE_GENERIC β a match β and
corecstat_attach() proceeds with sc->sc_version never assigned.
The driver's contract (header comment, corecstat.c:27-31) is "Nehalem and later Core CPUs"
β all of which are family 06h. corecstat_identify() gates on
cpu_vendor_id == CPU_VENDOR_INTEL (corecstat.c:160) but never on family.
Why it is memory-safe (why this is Info, not higher)
- The softc is allocated
M_ZEROby newbus (sys/kern/subr_bus.c:1953-1954), so the unassignedsc_versionis 0 β Nehalem/Westmere treatment. Even a garbage version could not overflow:sc_core_sens[3]takes at most 3 sensors for any version value (corecstat.c:460-471) andsc_pkg_sensis kmalloc'd for 7 with at most 7 added (corecstat.c:435-456). - Every MSR read that creates a sensor goes through
corecstat_try()βrdmsr_safe()(corecstat.c:594-603), so the DF-4735 raw-rdmsr-#GP family cannot fire here. The only rawrdmsr()calls (corecstat.c:531, 549) execute solely for sensors whose MSR already passedrdmsr_safeat attach.
What actually happens (guest-reproduced)
On the QEMU/KVM guest (vendor=GenuineIntel, family 0x0F, model 0x0B β "QEMU Virtual CPU
version 2.5+"), loading the stock, unmodified corecstat.ko:
corecstat0..corecstat5all attach ("<CPU Package C-State residency counters> on cpuN")- every residency MSR is gracefully rejected by
rdmsr_safeβ 17 console lines "msr node0 ... not available" (the version-0 Nehalem set: core C3/C6 everywhere, plus PC3/PC6/PC7 on the chip-representative cpu5) - a phantom empty sensordev
cpu_node0is installed andhw.sensors.dev_idmaxbumps 6 β 7 with zero sensors in it - the 1 Hz refresh task is registered on every cpu with zero sensors to refresh
kldunload corecstatis clean.
No panic, no corruption β pure wrong-attach + console spam + useless per-cpu sensor tasks on exactly the silicon the driver must reject (Pentium 4-class family 0x0F, etc.).
Reproduce
# on the DragonFly guest (as root), stock kernel, stock cpu (family 0x0F): sh build.sh # builds stock corecstat.ko from pristine /usr/src source sh run.sh # kldload, show dmesg + hw.sensors.dev_idmax, kldunload # expected: 6x attach lines, 17x "msr ... not available", dev_idmax 6->7->6, no panic
Fix
fix.diff adds the missing family gate to both probe and attach
(validated on the guest: with the fix, kldload produces no devices at all and
hw.sensors.dev_idmax stays 6).
VERDICT β DF-4779
Reproduced? YES (2 runs, plus fix validation)
On the stock QEMU/KVM guest β CPU vendor GenuineIntel, family 0x0F, model 0x0B
(not family 06h) β the stock, unmodified corecstat.ko (built from pristine
/usr/src/sys/dev/powermng/corecstat/corecstat.c, -Werror clean):
- All six
corecstatNdevices attach (corecstat0..5: <CPU Package C-State residency counters> on cpuN). Root cause:corecstat_probe()wraps its model whitelist inif (cpu_family == 0x06) { ... default: return (ENXIO); }with no else-return (corecstat.c:183-236) β any Intel family β 06h probes asBUS_PROBE_GENERIC.corecstat_attach()has the identical missing gate (corecstat.c:259-324). sc->sc_versionis never assigned on this path; newbus zero-allocation (sys/kern/subr_bus.c:1953-1954) makes it 0 β the driver probes the Nehalem MSR set (core C3 0x3fc / C6 0x3fd on every cpu; PC3 0x3f8 / PC6 0x3f9 / PC7 0x3fa on the chip-representative cpu5) β every read gracefully rejected byrdmsr_safe(corecstat.c:598), 17msr ... not availableconsole lines.- A phantom empty sensordev
cpu_node0is installed:hw.sensors.dev_idmax6 β 7 with zero sensors; per-cpu 1 Hz refresh tasks registered with zero sensors. kldunloadclean; no panic anywhere β the DF-4735 raw-rdmsr-#GP family cannot fire through this driver because every sensor-creating MSR read isrdmsr_safe-gated (corecstat.c:594-603) and the only rawrdmsr()calls (corecstat.c:531, 549) execute solely for try-validated MSRs.
Impact: none (functional/robustness)
No memory corruption is possible even with a garbage sc_version:
sc_core_sens[3] receives at most 3 sensors for any version value (corecstat.c:460-471)
and sc_pkg_sens is sized 7 with at most 7 added (corecstat.c:435-456). On real
family-0x0F/05h Intel silicon the observable effect is identical to the guest: wrong
attach, console spam, a useless sensor task per cpu, a phantom sensordev per chip.
Exploit chain: (none β not a memory-safety bug)
Fix validation: FIXED
fix.diff adds the family gate to both probe and attach. Guest-validated: with the fix,
kldload attaches nothing (no corecstatN: lines, no msr ... not available lines,
hw.sensors.dev_idmax stays 6), unload clean. Baseline (unfixed) attaches 6 devices and
bumps dev_idmax to 7 β the previously-observed wrong behavior is gone.
Files
run.logβ two verbatim guest runs + fix-validation capturebuild.logβ module build (stock source, -Werror, clean)env.txtβ guest kernel/CPUID statefix.diffβ the family gate
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.
Fix verification
fixedWith fix.diff (family gate in probe+attach) applied to the module source, the same kldload on the same family-0x0F guest attaches zero devices: no corecstatN lines, no MSR-probe console spam, hw.sensors.dev_idmax remains 6 (baseline attached 6 devices and bumped it to 7). Wrong-attach behavior eliminated.
run.log FIX VALIDATION block: '2' (both sites patched), BUILD_OK, KLDLOAD_RC=0, dev_idmax 6 before and after load (no phantom sensordev), UNLOAD_OK.
Confirmed kernel references
Detail
Evidence (decisive lines)
run.log: 'corecstat0..5: <CPU Package C-State residency counters> on cpuN' on family 0x0F + 17x 'msr ... not available' + hw.sensors.dev_idmax 6->7->6; VERDICT.md path:line analysis (corecstat.c:183-236, 259-324, subr_bus.c:1953)
PoC changes
No trigger program needed: the stock module kldload on the stock guest CPU is the trigger. build.sh/run.sh captured verbatim.
Verified recommended fix
Reject cpu_family != 0x06 in both corecstat_probe() and corecstat_attach() (see fix.diff).
Verdict
Reproduced on the stock QEMU guest (Intel vendor, family 0x0F): the missing family-06h gate in corecstat_probe()/corecstat_attach() lets corecstat attach all 6 per-cpu devices on unsupported Intel families, probing Nehalem MSRs (all gracefully rejected by rdmsr_safe), installing a phantom empty cpu_node0 sensordev (hw.sensors.dev_idmax 6->7) and a useless 1 Hz task per cpu. No panic, no corruption (M_ZERO softc pins sc_version=0; static arrays bound sensor counts for any version value) - functional/robustness defect only. Fix (family gate in probe+attach) validated on the guest: with it, kldload attaches nothing and dev_idmax stays 6.
No comments yet.