⬢ DragonFlyBSD Kernel Audit
DF-4940 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4940",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "REPRODUCED: icoutput() unconditionally sets IFF_RUNNING (if_ic.c:347), so a single packet routed to a DOWN (or never-properly-up) ic0 \u2014 ip_output has no IFF_UP gate (ip_output.c:698,742) and if_down deletes no routes \u2014 flips the interface to RUNNING without iicbus_request_bus() and without buffer allocation. Demonstrated on the guest: flags 808810 -> 808850 (RUNNING while DOWN) after one ping, Opkts=1 (transmit over un-owned bus), and the following SIOCSIFFLAGS up allocated nothing (devbuf 819->819) while a control cycle allocated 2 (819->821). This permanently skips the up branch (if_ic.c:188) and thereby sustains the DF-2001 NULL-deref state; also causes un-owned bus transmissions and spurious iicbus release (parent callback fires before ownership check, iiconf.c:131-140). Fix (gate icoutput on UP|RUNNING + non-NULL buffers, drop the forced flag) validated: patched module returns ENETDOWN, no phantom RUNNING, proper up transition restored.",
  "exploit_chain": "admin brings ic0 up with address (or half-configures it: SIOCSIFADDR/SIOCSIFFLAGS wrapper leaves IFF_UP set even when the drivers bus request fails, if.c:2159-2171, if_ic.c:176) -> any unprivileged user sends a packet routed via ic0 while it is DOWN -> icoutput sets IFF_RUNNING -> every future ifconfig ic0 up skips allocation+bus acquisition -> on a never-allocated interface ic_obuf/ic_ifbuf stay NULL and every subsequent packet hits the bcopy NULL deref at if_ic.c:358 (sink owned by DF-2001) -> kernel panic (local DoS); additionally each such TX corrupts any in-flight transfer of the actual iicbus owner.",
  "evidence": "run.log B.step3: flags 808850 (RUNNING) on a down interface after ping (Opkts=1); B.step5: up allocates nothing (devbuf 819->819) vs control 819->821 (+2); FIX section: sendto: Network is down, flags stay 808810, proper 808851 after up.",
  "kernel_refs": [
    "sys/dev/netif/ic/if_ic.c:347",
    "sys/dev/netif/ic/if_ic.c:188-202",
    "sys/dev/netif/ic/if_ic.c:176",
    "sys/netinet/ip_output.c:698",
    "sys/netinet/ip_output.c:742",
    "sys/net/if.c:2134-2175",
    "sys/net/if.c:1730-1768",
    "sys/bus/iicbus/iiconf.c:125-148"
  ],
  "poc_changes": "New pass-2 finding, no seed PoC. Reproduction required the virtual-I2C-bridge harness (lpbbfake.ko, shared with DF-4939) and a destination address for the point-to-point interface. TX-while-down is reached via the surviving connected route (in_if_down purges cloned routes only).",
  "attempts": 2,
  "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": 300,
  "guest_dirty": 0,
  "build_cmd": "sh build.sh (harness); fix: apply fix.diff in guest /usr/src copy, cd sys/dev/netif/ic && make, install if_ic.ko, reboot",
  "run_cmd": "sh run.sh",
  "code_hash": "9ad16f1f7ec71d6be7f4a16b4b61439f8f4a3fda0d526bf72246be7045f53969",
  "notes": "Severity Low: requires if_ic present (I2C-attached system or attacker-loadable modules) plus prior admin configuration; direct NULL-deref sinks are DF-2001 (pass 1) and are cited, not re-claimed. Guest reset to clean-source snapshot after validation.",
  "recommended_fix": "Remove the unconditional ifp->if_flags |= IFF_RUNNING in icoutput; refuse to transmit unless (if_flags & (IFF_UP|IFF_RUNNING)) == both and buffers are non-NULL (fix.diff).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Patched if_ic.ko: ping-while-down returns ENETDOWN, no phantom RUNNING flag (808810 stays), subsequent up performs the proper transition (808851) with buffers reused (no leak). Baseline bad behaviors all absent.",
  "fix_evidence": "run.log FIX VALIDATION section (fixB.step1-4)"
}