DF-5522 / verdict.json
{ "finding_id": "DF-5522", "status": "reproduced", "reproduced": true, "impact": "none", "confidence": "certain", "verdict": "REPRODUCED (protocol conformance, no memory-safety impact): iicsmb_bwrite (iicsmb.c:463-482) never transmits the SMBus block byte-count after the command byte and iicsmb_bread (iicsmb.c:485-507) never consumes the slaves count byte after the repeated start -- it transfers *count raw bytes. Live wire capture with the production chain (isa->dfa_iic0->iicbus0->iicsmb0->smbus0->smb0) against a deliberately spec-compliant emulated slave: stock modules put de ad be ef 99 immediately after 07 with no count byte, and block reads returned the slaves count byte shifted into data[0]; with fix.diff the wire is [07][05][data] and reads consume the device count (req_len=1 then req_len=8, rcount=8, unshifted data a0..a7, deterministic). Every other in-tree smbus driver does both halves (ichsmb programs ICH_D0=count; intpm/amdsmb equivalent) -- the bridge is the odd one out, and ipmi_ssif (the only in-tree kernel block consumer) cannot work over it (reply parsing shifts one byte; Block Writes malformed). Severity Low per family precedent DF-5385 (ig4 write-side variant). FIX VALIDATED live (run.fixed.log).", "exploit_chain": "", "evidence": "run.baseline.log (stock: WRITE len=1 bytes: 07 followed directly by WRITE len=5 bytes: de ad be ef 99 -- no count byte; reads shift the slave count into data); run.fixed.log (patched: WRITE len=1 bytes: 05 count byte present; READ req_len=1 consumes count then READ req_len=8 -- rcount=8, rbuf=a0..a7 unshifted); fix.diff", "kernel_refs": [ "sys/bus/iicbus/iicsmb.c:463", "sys/bus/iicbus/iicsmb.c:474", "sys/bus/iicbus/iicsmb.c:485", "sys/bus/iicbus/iicsmb.c:499", "sys/bus/smbus/ichsmb/ichsmb.c:120", "sys/dev/misc/ipmi/ipmi_ssif.c:184", "sys/dev/misc/ipmi/ipmi_ssif.c:260" ], "poc_changes": "shared rig with DF-5521; the rigs slave was made spec-compliant on purpose (byte stream [count][data...] continuing across reads within a transaction) so the bridges wire behavior is directly observable", "attempts": 3, "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": 9600, "guest_dirty": 0, "build_cmd": "same as DF-5521 (shared rig/PoC; see build.sh)", "run_cmd": "/root/df5521_poc proto then dmesg | grep df5521-wire (stock vs fix.diff-patched modules)", "code_hash": "16fea8b1ba1d070dbd19dae52d1bcdaa1d4d6aeb3c9d4ad4d534a430677d5eb4", "notes": "Functional/data-integrity class (SMBus 2.0 block protocol violation in both directions), not memory corruption -- lengths remain bounded by callers (ipmi_ssif passes SMBUS_DATA_SIZE=32; /dev/smb clamps rcount). The rewritten bread in fix.diff also carries the [1,32] validation of DF-5523; the new bwrite count-byte error path inherits DF-1095s known started-state issue until that separate fix lands.", "recommended_fix": "bwrite: transmit the count byte between cmd and data; bread: read the devices count byte first, clamp to min(device count, *count, 32), transfer exactly that many bytes and report it as *count. See fix.diff (validated live).", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "Stock: wire shows no count byte on Block Write and no count consumption on Block Read (data one-byte-shifted). Patched (fix.diff): wire shows [cmd][count][data]; reads consume the count (req_len=1) then honor the device block length (req_len=8, rcount=8, rbuf=a0..a7 unshifted); behavior deterministic across 6 consecutive ioctls. Validated as part of the combined fixed-module build shared with DF-5521/5523/5525.", "fix_evidence": "run.fixed.log vs run.baseline.log; fix.diff" } |