DF-4780 / verdict.json
{ "finding_id": "DF-4780", "status": "reproduced", "reproduced": 1, "impact": "panic", "confidence": "certain", "verdict": "Reproduced deterministically (2 runs): on the stock QEMU guest, a CPUID-model substitution module (patchcpu -> family 06h model 36h, a model corecstat_probe() itself whitelists) plus the stock corecstat.ko compiled with INVARIANTS (= any debug/LINT64-style kernel build) panics at driver attach: panic: assertion \"sc->sc_version != 0\" failed in corecstat_init_atom_cpu (corecstat.c:424), backtrace corecstat_attach -> devclass_add_driver -> module_register_init, guest dead in DDB. Root cause: the atom-v0 else-if ENXIO (corecstat.c:355-357) diverts only non-representative cpus; every original-Atom chip representative (models 0x1c/0x26/0x27/0x35/0x36) falls into corecstat_init_atom_cpu with version 0. On production kernels (KKASSERT compiled out, systm.h:94-119) the same impossible path executes harmlessly-but-wrongly (live-captured: core C1 0x660/C6 probes from a version-0 softc; rdmsr_safe-gated). Fix (guard init_atom_cpu on sc_version != 0) validated: same trigger, no panic, core C1/C6 probes gone, clean unload, guest up.", "exploit_chain": "", "evidence": "panic.txt: full console with the KKASSERT panic + backtrace + DDB; run.log: baseline panic run (RUN_RC=124, vm.sh status down) AND production-build fall-through showing the core5 C1/C6 MSR probes from a version-0 softc; fix_run.log: fixed module, only 3 package MSR probes, no panic, GUEST_STILL_UP; build.log: INVARIANTS variant 11840 bytes with panic string present vs fixed variant where the compiler dead-code-eliminates the (now provably-true) assert.", "kernel_refs": [ "sys/dev/powermng/corecstat/corecstat.c:355", "sys/dev/powermng/corecstat/corecstat.c:359", "sys/dev/powermng/corecstat/corecstat.c:424", "sys/dev/powermng/corecstat/corecstat.c:186", "sys/kern/subr_cpu_topology.c:125", "sys/sys/systm.h:94" ], "poc_changes": "Trigger uses a CPUID-advertisement substitution module (same pattern as the DF-4735 pack) instead of real Atom silicon; the panicked code is the stock unmodified driver. INVARIANTS is enabled for the module by prepending #define INVARIANTS 1 (kmod CFLAGS are reset by bsd.kmod.mk, and the stock production kernel compiles KKASSERT to nothing).", "attempts": 3, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026\troot@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 900, "guest_dirty": 0, "build_cmd": "sh build.sh (builds patchcpu.ko + INVARIANTS corecstat.ko from pristine /usr/src source)", "run_cmd": "sh run.sh (kldload /tmp/pc/patchcpu.ko; kldload /tmp/ccsi/corecstat.ko -> panic)", "code_hash": "e46b6dffc825050cff7dcb00479b560738ade3ca00c7839853c047f8515d66ed", "notes": "Panic class only (no memory corruption); unprivileged trigger does not exist - requires boot/kldload on original-Atom hardware or a VMM advertising those CPUIDs. Guest returned clean via vm.sh reset with-src.", "recommended_fix": "Guard the atom dispatch in corecstat_attach(): only call corecstat_init_atom_cpu() when sc->sc_version != 0 (see fix.diff).", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "With fix.diff applied (same INVARIANTS define as the baseline build), the identical trigger no longer panics: module loads fully (FIXED_LOADED), cpu5 probes only the 3 package MSRs (the version-0 core C1/C6 probe lines are gone), kldunload clean, guest stays up. Baseline panicked at the same point. With the fix, -O2 interprocedural analysis proves the KKASSERT condition always true and eliminates the panic path from the binary entirely.", "fix_evidence": "fix_run.log (PATCH_LOADED/FIXED_LOADED/LOAD_RC=0, only PC2/PC4/PC6 not available lines, UNLOAD_OK, GUEST_STILL_UP, vm.sh status up) vs run.log/panic.txt (baseline panic, guest down).", "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0 (X86_64_GENERIC) + fixed corecstat.kld module (INVARIANTS)" } |