DF-5560 / verdict.json
{ "finding_id": "DF-5560", "status": "reproduced", "reproduced": true, "impact": "panic", "confidence": "certain", "verdict": "REPRODUCED as a deterministic kernel panic. iic_attach() (sys/bus/iicbus/iic.c:123-138) never assigns sc->sc_dev (declared :50); the zero-allocated softc leaves it NULL forever, and iicwrite (:197), iicread (:237) and iicioctl (:288) each do device_get_parent(sc->sc_dev) on entry -- movq 0x28(%rdi),%rax with %rdi==NULL -- so the FIRST read(2)/write(2)/ioctl(2) on any /dev/iicN faults the kernel. The FreeBSD original assigns sc->sc_dev = dev; the DragonFly port dropped it. Live proof on the guest with stock iic.ko (/dev/iic0 instantiated via the DF-5539 harness + the DF-5559 setup fix in iicbus.ko, which does not touch iic.c): open() succeeds, first I2CRDWR ioctl panics -- Fatal trap 12 ... fault virtual address = 0x28 ... Stopped at device_get_parent: movq 0x28(%rdi),%rax, current process = the PoC (panic.txt). fix.diff (sc->sc_dev = dev;) validated by rebuilding only iic.ko: zero panics across the full DF-5558 suite (hundreds of ioctls), device fully functional (success reads return the emulated TX pattern, failures return IIC_ENOACK). Impact: unconditional local DoS for anyone who can open the node; 0600 root:wheel on default config (and the DF-5559 attach bug usually prevents the node from existing at all -- the two bugs together explain why iic(4) has been dead-on-arrival on DragonFly and none of the iic.c ioctl bugs ever surfaced in the field). No escalation: fixed-offset NULL read, no controllable write.", "exploit_chain": "", "evidence": "panic.txt (full trap: fault va 0x28, current process 2071 rdwrleak, Stopped at device_get_parent: movq 0x28(%rdi),%rax, db> prompt, CPUs stopped); trigger.c (open + first ioctl); ../DF-5559/stock-probe-evidence.log (same panic captured in the stock-probe session); ../DF-5558/run2-full.log + run.log + fix_run.log (post-fix device fully functional, zero panics).", "kernel_refs": [ "sys/bus/iicbus/iic.c:50", "sys/bus/iicbus/iic.c:123-138", "sys/bus/iicbus/iic.c:197", "sys/bus/iicbus/iic.c:212", "sys/bus/iicbus/iic.c:237", "sys/bus/iicbus/iic.c:253", "sys/bus/iicbus/iic.c:288-289", "sys/bus/iicbus/iic.c:297-300" ], "poc_changes": "No seed PoC (found during the DF-5558 verification run when the first ioctl on the freshly-attached stock /dev/iic0 panicked instead of reaching I2CRDWR). trigger.c is the pre-fix-tweak copy of the DF-5558 PoC; the panic is the baseline observation, requiring no code beyond open()+ioctl().", "attempts": 1, "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": 900, "guest_dirty": 0, "build_cmd": "(trigger) cc -O2 -Wall -o rdwrleak rdwrleak.c on the guest; /dev/iic0 via the ../DF-5558 harness + setup fixes", "run_cmd": "./rdwrleak /dev/iic0 # first ioctl panics: see panic.txt", "code_hash": "e7930fc6f8528f283324cb6f49d8801ba58e530e09c747745b3a601fc2ab9568", "notes": "Found live during DF-5558 verification (the PoCs sanity ioctl panicked). Bucket suggestion: base:hw (family-consistent). Together with DF-5559 this explains why /dev/iicN is dead on stock DragonFly and the pass-1 iic.c findings never surfaced in the wild. Guest reset with-src after the run.", "recommended_fix": "Assign sc->sc_dev = dev in iic_attach() before make_dev (see fix.diff) -- restores the FreeBSD originals initialization.", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff applied to the guests /usr/src copy of sys/bus/iicbus/iic.c; only iic.ko rebuilt and reloaded. Baseline stock: first ioctl on /dev/iic0 panics the kernel (Fatal trap 12, fault 0x28, stopped in device_get_parent). Patched: zero panics; the same PoC plus the full DF-5558 suite (hundreds of ioctls incl. failing transfers) runs to completion with correct results.", "fix_evidence": "fix.diff; ../DF-5558/fix_build.log (iic.ko rebuild); ../DF-5558/run.log + fix_run.log (post-fix functionality); panic.txt (baseline)." } |