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

struct bridge_ifinfo leaked on every span-port delete (bridge_ioctl_addspan allocates it; bridge_delete_span frees only the bif)

Summary

bridge_ioctl_addspan allocates bif_info (:1823) and stores it in bif->bif_info (:1828); bridge_delete_span frees only the bif (:1156), orphaning ~114 bytes of M_DEVBUF per spanport add/del cycle - via both the ioctl path and ifnet-detach. MEASURED on stock guest: devbuf in-use 3.12M -> 5.40M (+2.28MB) over 20000 cycles; zero growth on the fixed kernel. Root-gated unbounded kernel heap exhaustion for hosts whose automation cycles mirror ports. Fix: kfree(bif->bif_info) alongside the bif.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3279 Β· 10 files
FileTypeDescriptionSize
README.md β€” 635 B ↓ raw
verdict.json β€” 2.1 KB view raw
env.txt β€” 743 B view raw
build.log β€” 131 B view raw
fix.diff β€” 706 B view raw
run.sh β€” 99 B view raw
run.log β€” 829 B view raw
VERDICT.md β€” 2.0 KB ↓ raw
run_fixed.log β€” 674 B view raw
span_leak.c β€” 1.6 KB view raw

DF-3279 β€” struct bridge_ifinfo leaked on every span-port delete

What

bridge_ioctl_addspan() allocates a bridge_ifinfo for the span bif (if_bridge.c:1823-1828), but bridge_delete_span() frees only the bif (if_bridge.c:1155-1156) β€” the bif_info is never freed. Every spanport add/del cycle leaks ~114-120 bytes of M_DEVBUF kernel memory.

Reproduce (guest, as root)

cd /root/poc/df-3279
cc -O -o span_leak span_leak.c
# create bridge0 + tap0 first
./span_leak 20000
vmstat -m | grep devbuf

Expected

devbuf in-use grows by ~2.3 MB after 20000 cycles (measured: 3.12M -> 5.40M, i.e. ~114 bytes/cycle).

VERDICT.md
↓ download raw

DF-3279 β€” VERDICT

REPRODUCED β€” deterministic kernel memory leak (root-gated).

Evidence (baseline kernel, before fix)

$ vmstat -m | grep -E "^ *devbuf"   (before)
             devbuf   24.6K   3.12M       0    390M    49.1K
$ ./span_leak 20000                  (20000 spanport add/del cycles)
$ vmstat -m | grep -E "^ *devbuf"   (after)
             devbuf   44.2K   5.40M       0    390M    88.2K

Delta: +2.28 MB / 20000 cycles β‰ˆ 114 bytes leaked per cycle β€” matching sizeof(struct bridge_ifinfo) plus allocator rounding.

Root cause

bridge_ioctl_addspan() (if_bridge.c:1823): bif_info = kmalloc(sizeof(*bif_info), M_DEVBUF, M_WAITOK | M_ZERO); assigned to bif->bif_info (if_bridge.c:1828). Nothing else references it (span bifs are never passed to bridge_delete_member; the span branch of bridge_ioctl_gifs() at if_bridge.c:1482-1493 doesn't touch bif_info). bridge_delete_span() kfrees only bif β€” the bif_info is orphaned. Both the ioctl path and the ifnet-detach path (bridge_ifdetach_dispatch, if_bridge.c:1900-1904) go through bridge_delete_span, so both leak.

Impact

Unbounded kernel heap exhaustion by repeated BRDGADDS/BRDGDELS cycles β€” requires root (both ioctls are BC_F_SUSER-gated), so this is a resource-leak bug (Low) rather than a privilege issue. A long-running host where automation adds/removes span ports (e.g. per- session port mirroring) slowly bleeds unrecoverable kernel memory until reboot.

Fix validation

fix.diff (free bif_info in bridge_delete_span) applied with the combined patch; on the rebuilt kernel the same 20000-cycle loop left devbuf in-use unchanged (see run_fixed.log).

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

fixed
baseline reproduced→ patch + rebuild →patched clean

Fixed kernel: same 20000-cycle loop leaves devbuf in-use unchanged (266K -> 266K) vs +2.28MB on baseline.

findings/poc/DF-3279/run_fixed.log
↓ fix.diffDragonFly 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

Confirmed kernel references

Detail

Evidence (decisive lines)

['run.log: vmstat -m devbuf before/after on baseline and fixed kernels', 'fix.diff: kfree(bif->bif_info) in bridge_delete_span', 'run_fixed.log: zero growth over the identical 20000-cycle loop']

PoC changes

Written from scratch; needed for ETHER_ADDR_LEN from if_bridgevar.h.

Verified recommended fix

free bif->bif_info in bridge_delete_span (bundled with the DF-3277 list-head fix)

Verdict

Deterministic kernel heap leak: bridge_ioctl_addspan() allocates a bridge_ifinfo (if_bridge.c:1823-1828) that bridge_delete_span() never frees (frees only the bif, if_bridge.c:1155-1156). Measured on the stock guest: devbuf in-use grew 3.12M -> 5.40M (+2.28MB) over 20000 spanport add/del cycles = ~114 bytes/cycle. On the rebuilt kernel with bif_info freed: 266K -> 266K, zero growth.