⬢ DragonFlyBSD Kernel Audit
DF-2308 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-2308",
  "status": "not_reproduced",
  "reproduced": false,
  "impact": "none",
  "confidence": "certain",
  "verdict": "NOT REPRODUCED -- false positive: the I2CREAD copyout at sys/bus/iicbus/iic.c:347 does use the requested length (s->count) rather than the actual-read length (count from :344), but the claimed disclosure requires an iicbus_read backend that returns success with a short fill, and none exists in-tree. iicbb (iicbb.c:409-421, the only backend on the guest) fills every requested byte unconditionally (while(len) loop, *read=len, return 0; iicbb_readbyte has no failure mode), and pcf (pcf.c:586-640) short-reads only via an error return, which iic.c:345-346 handles by skipping the copyout entirely. Live proof with production modules on the DF-5539 harness rig: 3 runs x 51 success-path I2CREAD attempts at sizes 64..16384, each immediately preceded by the kernel-side M_TEMP groom (kmalloc+fill+kfree of the exact read size, marker DF5558STALEHEAP! + kernel-realm qwords) that DF-5558 used to prove same-size chunk recycling into iic.c kmallocs on this same rig -- every attempt returned rc=0 with pattern_bad=0, marker=no, kptr-qwords=0 (100% of bytes are the slave TX pattern 0xc0+i), i.e. zero bytes of the fresh chunk survive to userspace; all error-path probes returned EINVAL with the 0xAA-prefilled user buffer 100% untouched. The s->count-vs-count mismatch is real latent API misuse worth a hardening one-liner but discloses nothing with any in-tree backend.",
  "exploit_chain": "",
  "evidence": "run1.log/run2.log/run3.log: 51/51 success attempts per run, all rc=0 pattern_bad=0 marker=no kptr-qwords=0 plus error probes errno=22 untouched=YES. VERDICT.md: backend-by-backend code trace (iicbb.c:409-421, pcf.c:586-640, iic.c:345-347, iiconf.c:254-259). stock-vs-setup.disasm.txt + env.txt: stock I2CREAD logic under test on production iic.ko (setup fixes DF-5559/5560 disclosed and disasm-verified). panic-setup-df5560-incidental.txt: rig bring-up re-confirmation of sibling DF-5560.",
  "kernel_refs": [
    "sys/bus/iicbus/iic.c:343",
    "sys/bus/iicbus/iic.c:344",
    "sys/bus/iicbus/iic.c:345-346",
    "sys/bus/iicbus/iic.c:347",
    "sys/bus/iicbus/iicbb.c:409-421",
    "sys/bus/iicbus/iicbb.c:308-330",
    "sys/bus/iicbus/pcf/pcf.c:586-640",
    "sys/bus/iicbus/iiconf.c:254-259"
  ],
  "poc_changes": "No seed PoC existed. Authored iicread2308.c from scratch on the DF-5539/DF-5558 production-KLD rig: error-path probes (no-start, after-NACK, wrong-direction) plus groomed/ungroomed success-path I2CREAD at 6 sizes with full-buffer pattern check and marker search. Rig iterations: (1) a stale unpatched iic.ko from an earlier session panicked on the first ioctl (DF-5560 bug, capture kept) -- run.sh now clean-builds and objdump-verifies the setup store before loading; (2) DF patch(1) silently assumes -R on already-applied setup diffs -- switched to source-marker guards; (3) groom KLD build needed Makefile.groom renamed to Makefile and iicbus_if.m copied into the build dir; (4) E2/E3 probe expectations corrected for the harnesss ACK-falling-edge NACK arming (documented in VERDICT.md; kernel error-path invariants unaffected).",
  "attempts": 4,
  "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": 2400,
  "guest_dirty": 0,
  "build_cmd": "cd /root/df2308 && sh build.sh (harness KLDs via /root/df5539/build.sh; in-tree iicbus.ko/iic.ko with the two disclosed setup patches; groom5558.ko)",
  "run_cmd": "cd /root/df2308 && sh run.sh",
  "code_hash": "a226c1020f103d2a0b82c6454ab9e079d7983471444898a50ecd3d05b06889fe",
  "notes": "Reachability context: /dev/iicN is 0600 root:wheel (iic.c:128-130), so even if a short-read backend existed the oracle would be root-only on default configs. Incidental observations kept as notes: DF-5560 re-confirmed during bring-up; DF patch(1) -R-on-already-applied footgun. Hardening one-liner recorded in recommended_fix; no fix.diff per contract (pure false positive).",
  "recommended_fix": "Hardening (not a security fix): copy out the actual read length -- error = copyout(buf, s->buf, count); at iic.c:347 -- so a future backend honoring the short-read contract cannot disclose uninitialized tail bytes.",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "n/a -- false positive; no fix authored or validated per contract (the premise is unreachable with in-tree backends).",
  "fix_evidence": ""
}