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

my_softc my_ldata_ptr (2056-byte DMA descriptor block) is never freed: leaked on every detach and every failed attach

Summary

my_attach kmallocs 2056 bytes; my_detach releases only irq and res - 'kfree' appears ZERO times in the whole driver. Every detach leaks the block, and the attach-fail label routes through my_detach, so the no-PHY ENXIO path and bus_setup_intr failure leak it too. Root can loop kldload/kldunload for unbounded kernel-heap exhaustion (2KB/cycle). kfree fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4257 Β· 6 files
FileTypeDescriptionSize
trigger.sh β€” 544 B view raw
env.txt β€” 1007 B view raw
VERDICT.md β€” 1.9 KB ↓ raw
fix.diff β€” 397 B view raw
manifest.json β€” 719 B view raw
verdict.json β€” 2.0 KB view raw
VERDICT.md
↓ download raw

DF-4257 VERDICT β€” my(4) leaks my_ldata_ptr on detach and on failed attach

Status: inconclusive on the audit guest (hardware-gated). Leak certain at source level.

Reproduction attempt

pciconf -l | grep 1516 on the audit guest: no Myson device (env.txt); my_probe (if_my.c:754-771) never returns 0, so my_attach never runs and neither the allocation nor the leak can occur. A purely software trigger does not exist: the allocation is tied to PCI device attachment.

Analysis

grep -n "my_ldata_ptr" sys/dev/netif/my/if_my.c yields exactly three uses: the kmalloc (870), the alias assignment (872, 882), and the pointer arithmetic β€” there is no kfree(sc->my_ldata_ptr, M_DEVBUF) anywhere in the driver. my_detach (971-992) releases my_irq (987) and my_res (989) only.

Two leak paths:

  1. Normal lifecycle: attach succeeds β†’ later my_detach (kldunload or device removal) frees everything except the 2,056-byte descriptor block. Repeatable by root without bound.
  2. Failed attach: every goto fail after line 870 (no PHY found at 936-939; bus_setup_intr failure at 955-961) dispatches to my_detach(dev) (966-968) which β€” because device_is_attached() is false β€” releases only the resources, leaking the block.

This is a distinct allocation from the mbuf leak in DF-1479 (which covers my_encap failure inside my_start): DF-4257 is the softc-owned DMA descriptor array.

Severity Low: kernel memory leak, 2 KB per event, root-driven unload or hardware-provoked attach failure. CWE-401. Fix is a one-line kfree in my_detach (fix.diff).

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

one-line kfree added in my_detach (fix.diff); hardware-gated, not validated on this guest

findings/poc/DF-4257/fix.diff
↓ fix.diffper-fix-DF-4257

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md (all my_ldata_ptr uses enumerated β€” no kfree exists); env.txt (no Myson PCI device on guest)

PoC changes

trigger.sh documents the kldload/kldunload loop + vmstat -m observation for affected hardware

Verified recommended fix

kfree(sc->my_ldata_ptr, M_DEVBUF) in my_detach before releasing resources

Verdict

my_attach allocates sc->my_ldata_ptr = kmalloc(sizeof(struct my_list_data)+8, M_DEVBUF, M_WAITOK) (sys/dev/netif/my/if_my.c:870-871) and my_detach (971-992) never kfree()s it β€” it releases only my_irq and my_res. Every detach leaks 2056 bytes, and every failed attach (no PHY found at 936-939, bus_setup_intr failure at 955-961 β€” both routed to my_detach via the fail label at 966-968) leaks it too; there is no kfree of my_ldata_ptr anywhere in the driver. Root can loop kldload/kldunload for unbounded kernel heap exhaustion. Distinct allocation from the DF-1479 mbuf leak. Not executable on the audit guest: pciconf shows no 1516 device (env.txt) so my_probe never matches and my_attach never runs.