DF-3589 / verdict.json
{ "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)" } |