⬢ DragonFlyBSD Kernel Audit
DF-3589 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3589",
  "status": "not_reproduced",
  "reproduced": 0,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Not reproducible ON THIS GUEST: the attack needs the CTLFLAG_ANYBODY sysctl tree hw.psm.synaptics.* (or hw.psm.elantech.*), which is created only after a successful Synaptics/Elantech probe (psm.c:6741-6744, 7209-7211); the QEMU i8042 emulates a plain IntelliMouse Explorer, so the nodes do not exist (verified: sysctl: unknown oid) and psmsmoother() never runs. The mechanism itself is proven to the machine-code level with the guests own toolchain: the divisor expression from psm.c:4337 (div_x clamped into [div_min,div_max] times multiplicator, all ANYBODY-writable with only an arg < 1 lower bound, psm.c:5767-5780) with div_min=div_max=multiplicator=65536 wraps the int32 product to exactly 0 and the idiv traps -- userland SIGFPE exit 136 on the identical expression (divzero_expr.c), kernel equivalent is an unrecoverable divide-by-zero panic on the first touchpad movement packet (window_min=1 also writable). On any Synaptics/Elantech laptop this is a persistent unprivileged kernel panic; trigger.sh provides the hardware procedure.",
  "exploit_chain": "unprivileged sysctl hw.psm.synaptics.multiplicator=65536 div_min=65536 div_max=65536 window_min=1 (CTLFLAG_ANYBODY bypasses SYSCAP_NOSYSCTL_WR, kern_sysctl.c:1446) -> touch/move finger on touchpad -> psmsmoother() computes squelch_x / (65536*65536) -> int32 product wraps to 0 -> idiv #DE -> kernel panic; values persist so every subsequent touch re-panics until admin resets the nodes.",
  "evidence": "run.log (divzero_expr output: product=0, SIGFPE exit 136, plus unknown oid proof the guest lacks the nodes); VERDICT.md (line-by-line kernel-side argument: value ranges, clamps, reachability on packet #1); fix.diff (git apply --check OK)",
  "kernel_refs": [
    "sys/dev/misc/psm/psm.c:4336-4344",
    "sys/dev/misc/psm/psm.c:4307-4309",
    "sys/dev/misc/psm/psm.c:5767-5780",
    "sys/dev/misc/psm/psm.c:6048-6056",
    "sys/dev/misc/psm/psm.c:6099-6117",
    "sys/dev/misc/psm/psm.c:6741-6744",
    "sys/dev/misc/psm/psm.c:7209-7211",
    "sys/kern/kern_sysctl.c:1446"
  ],
  "poc_changes": "Authored from scratch (no seed): divzero_expr.c isolates the exact kernel expression for toolchain-level proof; trigger.sh is the real-hardware procedure.",
  "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": 20,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -Wall -o divzero_expr divzero_expr.c",
  "run_cmd": "./divzero_expr ; echo exit=$?",
  "code_hash": "1430c12a9d135c2d470a045a5a02f9e3904580da3bd34d52b1c2675567556b98",
  "notes": "Hardware-gated: needs a Synaptics/Elantech touchpad (ubiquitous on laptops) for the panic to manifest; the QEMU guest cannot instantiate the sysctl tree without patching the kernel, which would falsify the config. Impact none reflects THIS guest only; class on target hardware is unprivileged local DoS (kernel panic).",
  "recommended_fix": "Bound multiplicator/div_min/div_max/div_max_na/div_len at 100000 in synaptics_sysctl() and compute the smoother divisor as int64 (fix.diff)",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Baseline cannot be produced on this guest (sysctl tree absent), so patched-vs-baseline kernel builds were not performed. fix.diff bounds the five divisor-feeding sysctls at 100000 and widens the divisor product to int64 in psmsmoother(); with either half applied a zero divisor is impossible (div_x>=1, multiplicator>=1, 64-bit product >= 1). git apply --check passes.",
  "fix_evidence": "findings/poc/DF-3589/fix.diff (git apply --check OK)"
}