DF-5637 / verdict.json
{ "finding_id": "DF-5637", "status": "reproduced", "verdict": "smbus_release_bus (sys/bus/smbus/smbconf.c:151-180) releases the underlying bridge (SMBUS_CALLBACK at :160 -> iicbus_release_bus via iicsmb.c:263-266) BEFORE validating sc->owner == dev (:166), then broadcasts wakeup(sc) (:177) even on the EACCES path. Reproduced with the DF-5636 rig on the unmodified production stack: a non-owners release returned EACCES while the iicbus exclusion under the still-official owner was verifiably gone (a direct DONTWAIT iicbus request succeeded); the same non-owner release woke a parked requester into a success return with the owner unchanged (no release at all); and in the first baseline session the teardown chain wedged the bus permanently (the real owners subsequent release failed EACCES at the callback, leaving sc->owner set and parking every later requester). fix.diff moves the ownership validation ahead of any parent callback, returns EACCES without side effects, and wakes only on actual ownership change: validated on the rebuilt kernel (probe refused EWOULDBLOCK bridge exclusion intact; no bogus wakeup: GOOD on fixed code). The crit_enter-only ownership update (per-CPU, no cross-CPU exclusion) is the DF-5566 MP twin and is noted, not separately demonstrated.", "reproduced": true, "impact": "dos", "confidence": "certain", "exploit_chain": "", "evidence": "run_baseline.log F3 lines NON-owner release(devB)=13 + iicbus probe ... =0 <<< iicbus TORN DOWN by the non-owner release while devA owns smbus; F3B GRANTED while another device verifiably OWNS the bus (no release ever happened); wedge: F1.5/F1.6 + f2 parked in smbreq; run_fixed.log EWOULDBLOCK: bridge exclusion intact and no bogus wakeup: GOOD on fixed code", "kernel_refs": [ "sys/bus/smbus/smbconf.c:160", "sys/bus/smbus/smbconf.c:166", "sys/bus/smbus/smbconf.c:170", "sys/bus/smbus/smbconf.c:177", "sys/bus/smbus/smbconf.c:165", "sys/bus/iicbus/iicsmb.c:263", "sys/bus/iicbus/iiconf.c:131" ], "poc_changes": "shared rig with DF-5636 (see its poc_changes); F3 adds the direct iicbus DONTWAIT probe as the teardown oracle and bridge-restore cleanup; F3B isolates the EACCES-wakeup leg", "attempts": 3, "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 f3; ./df5636ctl f3b (chain per run.sh)", "code_hash": "0d6a9fb46361a16b9421e6e44b59cf3ff1e8b00f4732809426d00d30d98d4fb6", "notes": "Low severity (DF-5566 twin band): needs a wrong-device_t release from kernel code, but the wedge chain (non-owner release -> real owner cannot release -> bus wedged, all requesters parked) turns a one-line driver mistake into a permanent bus DoS. MP-unsafety of the crit sections noted in VERDICT.md.", "recommended_fix": "Validate sc->owner == dev (crit section) and return EACCES before any SMBUS_CALLBACK parent release; release the bridge only after ownership is confirmed; wakeup(sc) only on actual ownership change (pack fix.diff, shared with DF-5636).", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "On the rebuilt kernel the non-owner release still correctly returns EACCES but the iicbus stays held (probe EWOULDBLOCK, bridge exclusion intact), the EACCES path wakes nobody (F3B GOOD on fixed code), and no wedge occurred across the full suite.", "fix_evidence": "run_fixed.log F3.2/F3.3 and F3B.3/F3B.3w lines vs run_baseline.log; fix.diff sha256 346fe6893056aecf467e64d12285a0de337461aee150737964c0c3f5f06fbc2a" } |