⬢ DragonFlyBSD Kernel Audit
DF-5563 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5563",
  "status": "reproduced",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "iicbus_request_bus() parks requester threads in tsleep(sc, PCATCH, \"iicreq\", 0) on the iicbus softc with no timeout and no detach drain (iiconf.c:63/67, iicbus.c:156-162); kldunload of the i2c stack frees the softc and unmaps iicbus.ko text under the parked thread, and the pending SIGKILL makes it resume at unloaded iicbus.ko+0x1ab -> Fatal trap 12, supervisor read instruction, page not present (captured for both the rig-device entry and the real /dev/iic0 I2CSTART entry, iic.c:297-300). Line-traced collateral: a colliding wakeup(sc) after softc reuse re-enters the loops and writes sc->owner (iiconf.c:105) through a freed device chain. Root-gated like DF-5521 but on the waiter side, which that fix does not cover.",
  "exploit_chain": "root: open /dev/iic0 (0600) blocking -> ioctl(I2CSTART) -> iicbus_request_bus(IIC_WAIT|IIC_INTR) -> fakebb/lpbb-style busy callback -> tsleep(sc, PCATCH, 0) parked forever; kldunload iic df5563_rig iicbb_reg iicbb iicbus (all rc=0, devclass_delete_driver force-detaches, softc+text freed); kill -9 -> PCATCH wake -> resume at unmapped iicbus.ko+0x1ab -> kernel page fault -> panic in DDB. Kthread variant needs no /dev node: ipmi_ssif/cyapa SMB_WAIT sleepers have no PCATCH at all (iiconf.c:67).",
  "evidence": "panic.txt and panic_variant_a.txt: Fatal trap 12 ... fault virtual address = 0xffffffff826001ab, instruction pointer = 0x8:0xffffffff826001ab, current process = 2031/1480 (kldstat in run_f1_variantB.log / run_f1_variantA.log shows iicbus.ko at 0xffffffff82600000 size 0x1000 = the unloaded text). run_fixed_validation.log: fixed kernel parks (S1 iicreq), all 5 unloads rc=0, NO panic, uptime healthy, ioctl returns ENXIO via drain.",
  "kernel_refs": [
    "sys/bus/iicbus/iiconf.c:56-76",
    "sys/bus/iicbus/iiconf.c:63",
    "sys/bus/iicbus/iiconf.c:67",
    "sys/bus/iicbus/iiconf.c:85-117",
    "sys/bus/iicbus/iiconf.c:101-105",
    "sys/bus/iicbus/iicbus.c:156-162",
    "sys/bus/iicbus/iicbus/Makefile",
    "sys/kern/subr_bus.c:853-899",
    "sys/bus/iicbus/iic.c:297-300"
  ],
  "poc_changes": "Reused the DF-5539/5558 fakebb rig shape; added a busy-callback sysctl (hw.df5563.busy -> EWOULDBLOCK, the lpbb ppbus-held contract), a /dev/df5563 ioctl surface over iicbus_request_bus/release_bus with each how variant, and self/release owner tokens; fixed include set (sys/device.h for struct dev_ops), a missing how argument, and unused-variable errors; needed the disclosed DF-5559/DF-5560 setup fixes for the /dev/iic0 variant. Fix development: added sys/kernel.h (hz), sys/spinlock.h include in iicbus.h (incomplete struct spinlock), explicit softc cast in iicbus_attach, and timeout-as-spurious-wakeup in iicbus_poll after DFs tsleep(EWOULDBLOCK-on-timeout) made WAIT callers bail after 1s.",
  "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": 2100,
  "guest_dirty": 0,
  "build_cmd": "cd /root/df5563 && sh build.sh  (after: cd /usr/src && patch -p1 --fuzz=2 < /root/df5559/fix.diff && patch -p1 --fuzz=2 < /root/df5560/fix.diff && (cd sys/bus/iicbus/iicbus && make) && (cd sys/bus/iicbus/iic && make))",
  "run_cmd": "sh /root/df5563/run_f1.sh ; (vm.sh reset with-src + restage) ; sh /root/df5563/run_f1a.sh ; fix: run_fixed_validation.log sequence",
  "code_hash": "ebe006166647097cef900f01cd62c0d0bf74cb841e9a9b1a6f7c536898950ab4",
  "notes": "Both entry variants panic at the SAME deterministic address (instruction after tsleep return in iicbus_poll). Colliding-wakeup UAF-write variant (sc->owner=dev into reused softc memory) line-traced but not needed for the verdict. In-tree kthread sleepers (ipmi_ssif.c:81,181; cyapa.c:1176,1624 via SMB_WAIT passthrough) hit the no-PCATCH twin at iiconf.c:67 and cannot even be signaled. Guest reset with-src done at the end of the run.",
  "recommended_fix": "Bounded PCATCH polling + dying/waiters drain protocol in iiconf.c/iicbus.c/iicbus.h (see fix.diff); also closes DF-5564/DF-5565.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "With fix.diff applied (iicbus.ko rebuilt+reloaded), the identical F1 sequence parks the requester, all five module unloads still return rc=0 (iicbus_detach now wakes+drains waiters), kill -9 finds the process already exited with ENXIO, no panic, guest healthy, and the attach sanity round trip (write_ok=1 read_ok=1) plus a full reload of the chain succeed. patch -R --dry-run confirms the shipped diff matches the validated tree.",
  "fix_evidence": "findings/poc/DF-5563/run_fixed_validation.log (F1V_PASS / F2V_PASS / immediate EWOULDBLOCK / SANITY lines); fix.diff"
}