DF-5638 / verdict.json
{ "finding_id": "DF-5638", "status": "reproduced", "verdict": "smbus_poll (sys/bus/smbus/smbconf.c:92-94) parks SMB_WAIT|SMB_NOINTR callers in tsleep(sc, 0, \"smbreq\", 0) -- no PCATCH, no timeout (SMB_NOINTR is 0 per smbconf.h:42; in-tree plain-SMB_WAIT callers: ipmi_ssif.c:81,181 and cyapa.c:1176,1624). Reproduced on the stock kernel with the DF-5636 rig: a user process calling smbus_request_bus(devB, SMB_WAIT) while another device held the bus entered state D4 on wchan smbreq and SURVIVED kill -9; the pending SIGKILL was delivered only after the bus was released (and the wake path handed it a phantom grant besides). The check-then-sleep window in the first do-while (smbconf.c:120-124) can additionally strand a waiter on a free bus forever. fix.diff makes smbus_poll always PCATCH with an hz bound: on the rebuilt kernel the parker sits in S2 smbreq and kill -9 kills it immediately, and the timeout turns any lost wakeup into a 1-second retry. Residual: no detach drain (noted in VERDICT.md).", "reproduced": true, "impact": "dos", "confidence": "certain", "exploit_chain": "", "evidence": "run_baseline.log PARK section: D4 smbreq before and after kill -9, unwedge via unpark, <<< phantom grant on wake; run_fixed.log: S2 smbreq + kill -9 WORKED: parker died (PCATCH fix effective)", "kernel_refs": [ "sys/bus/smbus/smbconf.c:88", "sys/bus/smbus/smbconf.c:92", "sys/bus/smbus/smbconf.c:120", "sys/bus/smbus/smbconf.h:42", "sys/dev/misc/ipmi/ipmi_ssif.c:81", "sys/dev/smbus/cyapa/cyapa.c:1176", "sys/dev/smbus/cyapa/cyapa.c:1624" ], "poc_changes": "shared rig with DF-5636; the PARK/UNPARK ioctls park a real user process (not a kthread) so unkillability is observable via ps/kill", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0 (baseline) / #3: Fri Oct 9 02:13:57 UTC 2026 (fix validation), x86_64", "runtime_sec": 4950, "guest_dirty": 0, "build_cmd": "sh ./build.sh; fix: patch -p1 < fix.diff && make quickkernel+installkernel KERNCONF=X86_64_GENERIC", "run_cmd": "./df5636ctl park & sleep 1; ps -o pid,stat,wchan -p $!; kill -9 $!; sleep 1; ps ...; ./df5636ctl unpark", "code_hash": "0d6a9fb46361a16b9421e6e44b59cf3ff1e8b00f4732809426d00d30d98d4fb6", "notes": "Low severity (DF-5563/5564 twin band). The kldunload-under-parked-waiter freed-text variant is defused practically by PCATCH+hz (waiter killable, re-checks every second) but a proper detach drain remains future family-wide work.", "recommended_fix": "Make smbus_poll always sleep with PCATCH and an hz-bounded timeout (and treat the timeout as a re-check, per DF-5636s loop fix); see pack fix.diff, shared with DF-5636.", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "Patched kernel: parker state S2 (killable) vs D4 (unkillable) on stock; kill -9 terminates the parked process immediately; the 1s poll bound self-heals lost wakeups.", "fix_evidence": "run_fixed.log PARK killability section vs run_baseline.log PARK section; fix.diff sha256 346fe6893056aecf467e64d12285a0de337461aee150737964c0c3f5f06fbc2a" } |