{
  "finding_id": "DF-3277",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "List-head confusion: bridge_delete_span() TAILQ_REMOVEs the span bif against &sc->sc_iflists[mycpuid] although span bifs live on sc_spanlist (if_bridge.c:1155 vs 1832). Removing the last span entry clobbers sc_iflists[0].tqh_last to &sc->sc_spanlist.tqh_first; the LINK2 bonding round-robin TAILQ_INSERT_TAIL (if_bridge.c:2140) then writes a member bif into sc_spanlist.tqh_first, cross-linking the lists. Reproduced three times end-to-end on the stock guest with a full instrumentation chain: same-MAC STP tap pair (FORWARDING), link2 bridge, spanport add+del, ARP-frame learn+forward pinned to cpu0 (member order visibly rotated by the round-robin: tap2 tap1 tap0 -> tap2 tap0 tap1), then BRDGDELS(tap1) found the MEMBER on the span list -> panic: bridge_delete_span: not a span interface (bridge_ioctl_delspan -> bridge_delete_span, cpuid 0). On non-INVARIANTS kernels the same chain silently unlinks and kfrees a live member bif (if_bridge still set; other cpus still hold their bifs) -> UAF/double-free at teardown; the impact on this INVARIANTS guest is the deterministic KASSERT panic.",
  "exploit_chain": "spanport add/del (root) -> sc_iflists[0].tqh_last corrupted -> bonding INSERT_TAIL (packet-driven, LINK2 + same-MAC members) -> sc_spanlist.tqh_first = member bif -> delspan/destroy walks member bif as span: KASSERT panic (INVARIANTS) or unlink+kfree of live member bif -> UAF/double-free (stock kernels). Memory-corruption primitive is root-config-gated, then traffic-driven.",
  "evidence": [
    "run.log: full serial-console chain -- states FORWARDING, member-order rotation, rtable learn, then the panic",
    "panic.txt: second independent reproduction, identical stack (bridge_delete_span+0x87 <- bridge_ioctl_delspan+0x58)",
    "run_fixed.log: patched kernel -- same PoC, bonding still reorders, delspan(tap1) probe returns ENOENT, destroy clean, guest up",
    "fix.diff: one-line TAILQ_REMOVE head correction"
  ],
  "kernel_refs": [
    "sys/net/bridge/if_bridge.c:1155",
    "sys/net/bridge/if_bridge.c:1832",
    "sys/net/bridge/if_bridge.c:2135",
    "sys/net/bridge/if_bridge.c:2140",
    "sys/net/bridge/if_bridge.c:4576"
  ],
  "poc_changes": "Written from scratch. Three PoC-environment pitfalls solved en route (documented so the pack reproduces first try): (1) tap fds must be opened BEFORE bridge-up so bstp_ifupdstatus sees IFM_ACTIVE and bstp_initialization drives ports to FORWARDING (bstp_enable_port parks enabled ports in BLOCKING without a state selection); (2) frames must be ETHERTYPE_ARP -- NETISR_ARP has no hashfn so processing stays on cpu0 (ETHERTYPE_IP frames with ip_hl=0 are freed by ip_lengthcheck before the bridge); (3) process pinned to cpu0 via sched_setaffinity (DragonFly has no cpuset(1)/sys/cpuset.h).",
  "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": 45,
  "guest_dirty": 0,
  "build_cmd": "cc -O -Wall -o bond_corrupt bond_corrupt.c",
  "run_cmd": "./bond_corrupt   (root; prints chain state, panics at the delspan probe)",
  "code_hash": "2588551ee880d3826b6106c87ebe0aa305c94f48a9efe6cb280505d869a3c3e9",
  "notes": "Three baseline panics with identical signature. Tree byte-identical to DragonFlyBSD master (live upstream bug).",
  "recommended_fix": "bridge_delete_span: TAILQ_REMOVE(&sc->sc_spanlist, bif, bif_next) instead of &sc->sc_iflists[mycpuid]",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Thu Sep 10 00:48:01 UTC 2026  root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Rebuilt kernel (combined fix_all.diff): identical PoC runs to completion -- member learning and bonding round-robin still operate (on the correct list), the delspan(tap1) probe correctly returns ENOENT, ifconfig destroy completes cleanly, no panic, guest up.",
  "fix_evidence": "findings/poc/DF-3277/run_fixed.log; findings/poc/DF-3277/fix.diff"
}