⬢ DragonFlyBSD Kernel Audit
DF-5522 / verdict.json
← back to finding ↓ download raw
{
  "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"
}