DF-2737 / verdict.json
{ "finding_id": "DF-2737", "status": "untested", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Info defense-in-depth finding, proven statically: the dynamic-oid teardown drain at sys/kern/kern_sysctl.c:391-398 is dead code because nothing in the kernel ever increments struct sysctl_oid.oid_running (grep over the whole tree returns only the declaration in sys/sys/sysctl.h:168 and the read/tsleep at kern_sysctl.c:391-395). CTLFLAG_DYING is consequently never set and the KASSERT at kern_sysctl.c:1386/1395 can never fire. Actual handler-vs-teardown safety rests entirely on the pcpu SLOCK-across-handler protocol (userland_sysctl:1569-1578, kernel_sysctl:1274-1276 vs _sysctl_xlock over all cpus:1641-1651), which the race hammer (12 kldload/kldunload coretemp cycles vs 4245 unprivileged sysctl -aN walks) confirmed holds on the INVARIANTS guest with no panic and a fully drained sysctloid arena. No runtime trigger exists, so no standalone exploit PoC was warranted for this Info finding; the pack records the prober and race-hammer evidence for the whole-file negative result. fix.diff (git apply --check clean) wires the counter up in sysctl_root AND makes sysctl_find_oid return ENOENT for DYING nodes so the drain cannot itself introduce the INVARIANTS panic race its comment's mechanism would otherwise enable.", "exploit_chain": "", "evidence": [ "rg -n oid_running sys/ -> only sys/sys/sysctl.h:168 and sys/kern/kern_sysctl.c:391,393,395: no increment/decrement anywhere", "findings/poc/DF-2737/race_hammer.txt: 12 coretemp load/unload cycles vs 4245 unpriv sysctl -aN walks, guest up, vmstat -m sysctloid drained", "findings/poc/DF-2737/run_user_prober.log: adversarial oldlenp/name2oid/oidfmt/truncation matrix, no panic on INVARIANTS kernel", "sys/kern/lwkt_thread.c:340: lockinit(&gd->gd_sysctllock, ..., LK_CANRECURSE) legitimizes the recursive XLOCK at kern_sysctl.c:383/241" ], "kernel_refs": [ "sys/kern/kern_sysctl.c:391", "sys/kern/kern_sysctl.c:1386", "sys/kern/kern_sysctl.c:1569", "sys/kern/kern_sysctl.c:1641", "sys/sys/sysctl.h:168" ], "poc_changes": "n/a (prober authored fresh for this pass-2 run; no seed PoC existed)", "attempts": 1, "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": 210, "guest_dirty": 0, "build_cmd": "cc -O -o /tmp/prober /tmp/prober.c", "run_cmd": "/tmp/prober (unprivileged user maxx)", "code_hash": "a5a9b4c2b7b560bb76a39f9bc2e5acb97c5d553c1474bf0c68aa90f1004b59ea", "notes": "Info-severity: no Phase V exploit run warranted (contract skips Low/Info). Guest left clean (temp files removed, modules unloaded, no reset needed). The pack doubles as the negative-result record for the pass-2 audit of sys/kern/kern_sysctl.c; see VERDICT.md section 'Negative results' for the seven candidate classes killed with path:line citations.", "recommended_fix": "Wire up oid_running in sysctl_root (atomic inc/dec + wakeup around handler invocation) and make sysctl_find_oid return ENOENT for CTLFLAG_DYING nodes instead of KASSERTing - see fix.diff", "fix_status": "not_testable", "fix_kernel_uname": "", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Info/defense-in-depth finding with no runtime trigger, so no baseline bad behavior exists to observe disappearing; a kernel rebuild cycle was not warranted. fix.diff is git-apply-able (git apply --check clean) and was code-reviewed against sysctl_root/sysctl_find_oid, including the mandatory DYING->ENOENT companion hunk without which wiring the counter would make the KASSERT at kern_sysctl.c:1386 raceable to panic.", "fix_evidence": ["findings/poc/DF-2737/fix.diff (git apply --check: APPLIES-CLEAN)"] } |