DF-4928 / verdict.json
{ "finding_id": "DF-4928", "status": "reproduced", "reproduced": 1, "impact": "none", "confidence": "certain", "verdict": "Reproduced live on the DragonFly 6.5-DEVELOPMENT audit guest (QEMU/KVM, CPUID Origin=GenuineIntel Family=0xf Model=0x6b): corepower_probe() accepts a non-family-06 CPU because the model whitelist at corepower.c:165-197 is a skip-guard (the switch is simply not entered for family != 6) rather than a reject, leaving rdmsr_safe(MSR_RAPL_POWER_UNIT) via corepower_try() (:199) as the only gate - which this VMM passes since it services the MSR. attach() then executes the raw rdmsr() at :273 and returns ENXIO at :331-332 (sc_have_sens==0). dmesg pair corepower0: <CPU On-Die Power Usage Estimation> on cpu5 / device_probe_and_attach: corepower0 attach returned 6 captured in run.log; no sensors, no #GP, kldload/kldunload clean, guest alive. Impact none: every sensor MSR is individually rdmsr_safe-verified at attach before the refresh paths raw reads (:289-329 gate :393/:402), so no panic path is reachable - this is a hardening finding recording the gating shape (the coretemp DF-4735 #GP family pattern) plus the raw-rdmsr-where-rdmsr_safe-was-available miss at :273.", "exploit_chain": "", "evidence": "run.log: CPU line Origin=\"GenuineIntel\" Id=0x60fb1 Family=0xf Model=0x6b followed by kldload -> corepower0: <CPU On-Die Power Usage Estimation> on cpu5 + device_probe_and_attach: corepower0 attach returned 6, (no sensors - as expected), clean kldunload, uptime OK. env.txt: guest uname + hw.model + dev_idmax.", "kernel_refs": [ "sys/dev/powermng/corepower/corepower.c:165-197", "sys/dev/powermng/corepower/corepower.c:199", "sys/dev/powermng/corepower/corepower.c:273", "sys/dev/powermng/corepower/corepower.c:331-332" ], "poc_changes": "Authored from scratch (Info finding; no prior sketch). Trigger is a pure shell sequence: kldload corepower as root, capture dmesg/sysctl, kldunload, uptime.", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 60, "guest_dirty": 0, "build_cmd": "sh build.sh (no-op; kernel module shipped as /boot/kernel/corepower.ko)", "run_cmd": "sh trigger.sh (as root)", "code_hash": "none (shell trigger)", "notes": "Everything else in corepower.c audited clean in this pass: identify child_no check is a child-COUNT guard (subr_cpu_topology.c:122-133), not an inverted chip filter; detach ordering safe because kern_sensors runs callbacks under thr->lock and sensor_task_unregister2 takes the same lock (kern_sensors.c:300-339, :252-266); no div-by-zero (secs literal 1); 32-bit energy-wrap delta bounded <= 0xFFFFFFFF so no u64->u32 truncation; sysctl strings ksnprintf-bounded; sensor_task_register2 cannot fail with M_WAITOK so unregister2(NULL) unreachable.", "recommended_fix": "Reject non-Intel/non-family-06 CPUIDs explicitly at the top of corepower_probe() and use rdmsr_safe() for MSR_RAPL_POWER_UNIT in corepower_attach() (fix.diff).", "fix_status": "not_testable", "fix_baseline_reproduced": 1, "fix_patched_reproduced": null, "fix_verdict": "Two-line hardening (fix.diff, applies clean via patch --dry-run). No kernel rebuild/validation performed: Info-severity finding, and per contract a single-fix kernel build is mandated only for reproduced memory-corruption findings. The patched behavior is trivially predictable (probe returns ENXIO for family != 6 before any attach attempt).", "fix_evidence": "fix.diff hunks at corepower.c:159 and :275; baseline behavior in run.log." } |