⬢ DragonFlyBSD Kernel Audit
DF-4217 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4217",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Source-certain, runtime hardware-gated (inconclusive per family convention). ae_stop_rxmac() (if_ae.c:288) and ae_stop_txmac() (:324) wait for device idle with `for (i = 0; i < AE_IDLE_TIMEOUT; i--)` \u2014 the counter only decrements from 0, so the guard (i<100) is permanently true; unless the device reports idle the kernel thread busy-waits in DELAY(100) forever holding ifp->if_serializer, and the post-loop timeout branch (`i == AE_IDLE_TIMEOUT`) is unreachable (i can never be 100 again). Sibling loops ae_stop():255 / ae_reset():1510 correctly use i++. Dead/halted/surprise-removed device (reads 0xFFFFFFFF) or malicious passthrough NIC => permanent wedge of every stop path (ifconfig down :1221, init-from-intr :799/:770, watchdog :983, detach :1417, suspend :1786, shutdown :1801, statchg :366). Termination model proven on the audit guest (run.log RC=0: as-written shape unbounded \u2014 10M-iteration self-cap hit, i=-9999999, timeout branch never taken; fixed i++ exits at exactly 100 reads). End-to-end trigger hardware-gated: no 1969:2048 on guest, if_ae not in X86_64_GENERIC, guest src md5 == audited tree. DoS only.",
  "exploit_chain": "On real hardware: device enters non-idle state (fault, surprise removal, D3 glitch, or crafted passthrough NIC holding AE_IDLE_* bits set) -> `ifconfig ae0 down` (or intr-error reinit / suspend / detach) -> ae_stop_rxmac/ae_stop_txmac loop never exits -> calling thread (or interrupt thread) spins forever holding ifp->if_serializer; one CPU pegged, interface dead until reboot. No privilege path.",
  "evidence": "run.log (guest: [1] 10,000,000 capped iterations, timeout branch NOT taken, i=-9999999; [2] fixed variant exactly 100 reads; RC_4217=0), stoploop.c (exact-shape model), env.txt (NO_ATTANSIC_PCI_1969, if_ae not in kernel config, guest-src md5 match), fix.diff (i-- -> i++ at :288/:324, git-apply clean)",
  "kernel_refs": [
    "sys/dev/netif/ae/if_ae.c:288",
    "sys/dev/netif/ae/if_ae.c:324",
    "sys/dev/netif/ae/if_ae.c:255",
    "sys/dev/netif/ae/if_aevar.h:41",
    "sys/dev/netif/ae/if_ae.c:799",
    "sys/dev/netif/ae/if_ae.c:1221",
    "sys/dev/netif/ae/if_ae.c:366"
  ],
  "poc_changes": "No seed PoC. Authored stoploop.c from scratch (exact loop-shape termination model, bugged + fixed variants); built and executed on the audit guest.",
  "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": 120,
  "guest_dirty": 0,
  "build_cmd": "vm.sh run_root cc -O2 -Wall -Wextra -o /tmp/df4217 /tmp/stoploop.c (after scp -F dfbsd-qemu/config stoploop.c dfbsd:/tmp/)",
  "run_cmd": "vm.sh run_root /tmp/df4217; echo RC_4217=$?",
  "code_hash": "7ac099b964be6dc8a966dc3322a304eb56a151f85183a0b1137cb0458d1fb217",
  "notes": "Pass-2 result for if_ae.c (GLM 5.3). Pure control-flow defect (loop counter decremented); local DoS only. Model is self-capping and safe to run on any guest. fix.diff validated with git apply --check against the audited tree.",
  "recommended_fix": "Change `i--` to `i++` in both idle-wait loops (ae_stop_rxmac if_ae.c:288, ae_stop_txmac if_ae.c:324) \u2014 see fix.diff.",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Baseline loop-termination defect proven by the model (unbounded as-written, exactly-100-reads fixed). The ae-specific fix path cannot be runtime-validated (no Attansic L2 hardware on the guest); fix.diff is a two-character mechanical change per site, git-apply clean against the audited tree, restoring the exact bounded shape of the correct sibling loops ae_stop():255 / ae_reset():1510.",
  "fix_evidence": "fix.diff; run.log [1] vs [2] contrast (unbounded vs exactly 100 reads)"
}