{
  "finding_id": "DF-5636",
  "status": "reproduced",
  "verdict": "smbus_request_bus (sys/bus/smbus/smbconf.c:126-141) returns success without acquiring ownership on two paths: after any wakeup (the loops if (error == 0) break exits without re-checking sc->owner or setting sc->owner = dev) and for SMB_DONTWAIT (the if (error == EWOULDBLOCK) error = 0 fixup converts the fast-fail refusal into a phantom grant). Reproduced on the unmodified production smbus stack (fakebb rig hosting real iicbb/iicbus/iicsmb + in-kernel smbus): a woken waiter returned 0 while sc->owner stayed NULL, a second requester was granted immediately (double grant), SMB_DONTWAIT returned 0 while another device verifiably owned the bus, and a non-owners EACCES release (smbconf.c:177 unconditional wakeup) woke a parked waiter into a success return while the real owner still held the bus. The iicsmb bridge transfer methods perform no arbitration of their own, so a phantom grant puts two kernel threads inside one SMBus transaction (ichsmb KASSERT panic class, interleaved wire transactions elsewhere). fix.diff (re-check after poll, no EWOULDBLOCK-to-success, PCATCH+hz park, validate-before-bridge-release) was applied to /usr/src, the kernel rebuilt and rebooted: all phantom grants gone, DONTWAIT refused with EWOULDBLOCK, woken waiters claim ownership, park killable.",
  "reproduced": true,
  "impact": "dos",
  "confidence": "certain",
  "exploit_chain": "",
  "evidence": "run.log F1 lines T(devB): request RETURNED 0 + sc->owner=0 (caller=devB) <<< PHANTOM GRANT and F1.4 double grant; F2 line SMB_DONTWAIT)=0 ... <<< PHANTOM GRANT (must be EWOULDBLOCK); F3B line GRANTED while another device verifiably OWNS the bus; run_fixed.log shows owner=devB claim, EWOULDBLOCK refusals and GOOD on fixed code on kernel #3",
  "kernel_refs": [
    "sys/bus/smbus/smbconf.c:126",
    "sys/bus/smbus/smbconf.c:131",
    "sys/bus/smbus/smbconf.c:134",
    "sys/bus/smbus/smbconf.c:137",
    "sys/bus/smbus/smbconf.c:96",
    "sys/bus/smbus/smbconf.c:177",
    "sys/bus/iicbus/iicsmb.c:250",
    "sys/bus/iicbus/iicsmb.c:276",
    "sys/bus/iicbus/iiconf.c:99",
    "sys/dev/smbus/smb/smb.c:240",
    "sys/dev/misc/ipmi/ipmi_ssif.c:81",
    "sys/dev/smbus/cyapa/cyapa.c:1176"
  ],
  "poc_changes": "seed sketch rewritten as the family-standard fakebb KLD rig: real production chain (iicbb/iicbus/iicsmb modules + in-kernel smbus), three distinct device_t owner tokens, in-kernel kthreads with started/done handshakes and owner-pointer sampling after every request; two rig iterations (build.sh Makefile copy bug; sys/string.h->bzero; robust cleanup after the DF-5637 teardown wedge; hz/2 release timing so the wakeup, not the 1s poll timeout, drives the fixed-kernel F1)",
  "attempts": 6,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 (baseline) / #3: Fri Oct 9 02:13:57 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (fix validation)",
  "runtime_sec": 4950,
  "guest_dirty": 0,
  "build_cmd": "sh ./build.sh (iicbb_reg.ko + df5636_rig.ko + df5636ctl); fix: patch -p1 < fix.diff in /usr/src && make quickkernel+installkernel KERNCONF=X86_64_GENERIC",
  "run_cmd": "sh ./run.sh  (kldload chain; ./df5636ctl f1|f2|f3|f3b; ./df5636ctl park + kill -9 + unpark)",
  "code_hash": "0d6a9fb46361a16b9421e6e44b59cf3ff1e8b00f4732809426d00d30d98d4fb6",
  "notes": "No memory corruption (protocol grants, not bytes) so no uid0 chain; ceiling is mutual-exclusion bypass -> concurrent SMBus transactions (ichsmb KASSERT panic class; interleaved IPMI SSIF/cyapa transfers). Triggers: any contended wakeup (routine on multi-child buses) or SMB_DONTWAIT (/dev/smb nonblocking ioctls, cyapa/atmel O_NONBLOCK opens - root-only devices or kernel threads) => Medium. The baseline run also captured DF-5637s teardown chain live (non-owner release made the real owners later release EACCES, wedging the bus owner). kthread kprintf lines intermittently absent from console (observed quirk); the rig reports the threads sampled verdict from the ioctl thread instead. Guest reset (with-src) performed after the run.",
  "recommended_fix": "Rewrite the smbus_request_bus ownership loop to re-check sc->owner after every smbus_poll return (continue on wake and on WAIT poll-timeout, unwind the bridge request only on interruption or refused DONTWAIT), set error=0 only when ownership is claimed, keep DONTWAIT EWOULDBLOCK; validate smbus_release_bus ownership BEFORE the parent callback and drop the EACCES-path wakeup; make smbus_poll always PCATCH with an hz bound (see pack fix.diff).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "fix.diff applied to /usr/src/sys/bus/smbus/smbconf.c, kernel rebuilt (quickkernel, smbconf.o recompiled) and rebooted (kernel #3): F1 summary 0x3->0x0 with the woken waiter CLAIMING owner and devC parking; F2 0x1->0x0 with SMB_DONTWAIT refused EWOULDBLOCK; F3B 0x1->0x0 no bogus wakeup: GOOD on fixed code; park S2/killable (was D4/unkillable). Baseline behaviors all gone.",
  "fix_evidence": "run_fixed.log (full fixed-kernel dmesg section) + run.log baseline differential; fix.diff sha256 346fe6893056aecf467e64d12285a0de337461aee150737964c0c3f5f06fbc2a"
}