β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4328

sf_attach() bus_setup_intr() failure path double-invokes ether_ifdetach() and passes a NULL intr cookie to bus_teardown_intr()

Summary

On bus_setup_intr failure after ether_ifattach succeeded, the attach calls ether_ifdetach itself and then jumps to fail: which invokes sf_detach - device_is_attached is still true, so the full teardown runs a second time: ether_ifdetach again (non-idempotent: duplicate TAILQ_REMOVE/list corruption/panic) and bus_teardown_intr with the never-set NULL cookie. IRQ exhaustion at kldload/boot. Remove-premature-detach + NULL-guard fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4328 Β· 4 files
FileTypeDescriptionSize
README.md β€” 1.1 KB ↓ raw
VERDICT.md β€” 1.7 KB ↓ raw
fix.diff β€” 953 B view raw
verdict.json β€” 1.6 KB view raw

DF-4328 β€” sf_attach() bus_setup_intr() failure path: double ether_ifdetach()

and bus_teardown_intr(NULL cookie)

File: sys/dev/netif/sf/if_sf.c:773-787 (attach error path), sys/dev/netif/sf/if_sf.c:791-820 (sf_detach)

If bus_setup_intr() fails after ether_ifattach() succeeded, sf_attach() calls ether_ifdetach(ifp) itself and then jumps to fail: which invokes sf_detach(dev). device_is_attached() is still true there, so sf_detach() runs the full teardown a SECOND time: ether_ifdetach() again (double if_detach(): duplicate TAILQ_REMOVE from ifnetlist, duplicate ifnet_array_del, double devctl/route announcements, double mcl_inclimit decrement β€” list corruption/panic) and bus_teardown_intr(dev, sc->sf_irq, NULL) with the unset cookie.

Trigger: IRQ resource exhaustion / MSI setup failure at kldload or boot β€” privileged/admin-initiated. Severity Low.

Not run on the guest (requires forcing bus_setup_intr failure on a driver whose hardware is absent); source-level finding only. fix.diff removes the premature ether_ifdetach() and guards the teardown cookie.

VERDICT.md
↓ download raw

DF-4328 β€” verdict: NOT REPRODUCED ON GUEST (source-level; hardware/driver-gated)

Root cause (path:line)

  • sys/dev/netif/sf/if_sf.c:777-780 β€” on bus_setup_intr() failure: ether_ifdetach(ifp); device_printf(...); goto fail;
  • sys/dev/netif/sf/if_sf.c:786 β€” fail: sf_detach(dev);
  • sys/dev/netif/sf/if_sf.c:796 β€” device_is_attached(dev) is still true (device detach flags unchanged), so sf_detach executes:
  • :802 ether_ifdetach(ifp) β€” SECOND time. ether_ifdetach -> if_detach (sys/net/if.c:949+) is not idempotent: second run re-announces IFAN_DEPARTURE/devctl, re-runs TAILQ_REMOVE(&ifnetlist,...), ifnet_array_del() on an array no longer containing ifp, double mcl_inclimit decrement, double ifgroup teardown -> list corruption or panic.
  • :799 bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand) with sc->sf_intrhand == NULL (setup failed).

Why not reproduced

Requires an sf(4) device whose interrupt setup fails at attach (IRQ exhaustion); the guest has no AIC-6915 hardware, so neither the success nor the failure path of sf_attach can execute. Reported at source-level certainty (Low severity, root/admin trigger: kldload/boot-time only).

Fix

fix.diff: drop the duplicate ether_ifdetach() from the attach error path (sf_detach already performs it) and NULL-guard the teardown cookie.

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

no hardware path on guest to validate

fix.diff authored
↓ fix.diffper-fix-DF-4328

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md path:line analysis (if_sf.c:777-787, 796-820; sys/net/if.c:949+)

PoC changes

none (no PoC run)

Verified recommended fix

remove premature ether_ifdetach() in the attach error path; NULL-guard bus_teardown_intr cookie

Verdict

Source-level finding, not exercisable on the audit guest: sf_attach()'s bus_setup_intr() failure path double-ether_ifdetach'es the ifnet (sf_detach runs the teardown again because device_is_attached() is still true) and passes a NULL intr cookie to bus_teardown_intr. Non-idempotent if_detach corrupts ifnet lists / double-decrements cluster limits. Requires IRQ-setup failure at kldload/boot on sf(4) hardware (privileged trigger) - Low.