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

wb_attach() allocates sc->wb_ldata but wb_detach() frees never-assigned sc->wb_ldata_ptr: ~296KB contigmalloc leak per attach/detach cycle

Summary

attach allocates into sc->wb_ldata but detach tests/frees sc->wb_ldata_ptr - a distinct softc field never assigned anywhere in the tree (grep-exhaustive). The guard is always false, so ~296KB of page-aligned contiguous kernel memory leaks on every detach, including all attach error paths. nfe-family attach/detach asymmetry. Free-the-right-field fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4269 Β· 5 files
FileTypeDescriptionSize
README.md β€” 1.3 KB ↓ raw
VERDICT.md β€” 1.5 KB ↓ raw
fix.diff β€” 891 B view raw
verdict.json β€” 2.0 KB view raw
env.txt β€” 700 B view raw

DF-4269 β€” wb_attach() allocates sc->wb_ldata but wb_detach() frees sc->wb_ldata_ptr (never assigned)

Files: sys/dev/netif/wb/if_wb.c:779-786 (attach), :852-859 (detach), sys/dev/netif/wb/if_wbreg.h:377-378 (two distinct softc fields).

What

sc->wb_ldata = contigmalloc(sizeof(struct wb_list_data) + 8, M_DEVBUF,   /* :779 */
    M_WAITOK | M_ZERO, 0, 0xffffffff, PAGE_SIZE, 0);
...
if (sc->wb_ldata_ptr) {                                                  /* :856 */
        contigfree(sc->wb_ldata_ptr, sizeof(struct wb_list_data) + 8,    /* :857 */
            M_DEVBUF);
}

wb_ldata_ptr (caddr_t, if_wbreg.h:377) is never assigned anywhere in the tree (verified: only occurrences are the declaration and the detach free). The allocation lives in sc->wb_ldata (if_wbreg.h:378). Every wb_detach() therefore frees NULL and leaks the contigmalloc block: ~296KB (sizeof(struct wb_list_data) + 8 = 64Γ—4096 + 64Γ—16 + 128Γ—256 + 8) of physically-contiguous, page-aligned kernel memory per attach/detach cycle β€” including every wb_attach() error path (they tail-call wb_detach, :827-829).

Impact

Unbounded kernel memory leak on module unload (kldunload if_wb.ko) / device removal / failed attach; repeat cycles exhaust kernel memory and contiguous pages. Privileged trigger, hardware-gated driver.

VERDICT.md
↓ download raw

VERDICT β€” DF-4269 (contigmalloc leak: wb_ldata vs wb_ldata_ptr)

Status: untested β€” no W89C840F hardware in the guest (env.txt). The leak is source-certain (grep-exhaustive): wb_ldata_ptr occurs exactly twice in the whole tree β€” the declaration (if_wbreg.h:377) and the detach free (if_wb.c:856-858) β€” and is never set, so if (sc->wb_ldata_ptr) is always false and the contigmalloc(sizeof(struct wb_list_data) + 8) from attach (if_wb.c:779-780) is never returned.

Impact

  • ~296KB (644096 + 6416 + 128*256 + 8 = 295,944 bytes) of page-aligned, physically-contiguous kernel memory leaked per attach/detach cycle.
  • Reachable by root via kldload/kldunload of if_wb.ko on any machine (the module builds and loads without the NIC; probe fails but attach already allocated? β€” no: on probe failure attach never runs, so the leak strictly requires the hardware to attach, or an attach-time failure after :779 (mii_phy_probe failure, bus_setup_intr failure), which also tail-calls wb_detach and leaks.
  • Severity Low: privileged unload + hardware presence; pure resource leak, no corruption.

Fix

Free sc->wb_ldata (fix.diff). The +8 size matches the allocation.

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

Fix validation requires the NIC; the guest has none.

fix.diff; VERDICT.md
↓ fix.diffper-fix-DF-4269

Confirmed kernel references

Detail

Evidence (decisive lines)

if_wb.c:779 (alloc into wb_ldata) vs if_wb.c:856-858 (free of wb_ldata_ptr); if_wbreg.h:377-378 (distinct fields); tree-wide grep for wb_ldata_ptr yields only the declaration + the free; VERDICT.md

PoC changes

No PoC (hardware-gated); analysis pack.

Verified recommended fix

Free sc->wb_ldata (the field that holds the contigmalloc result) in wb_detach.

Verdict

Source-certain memory leak. wb_attach() allocates sc->wb_ldata (if_wb.c:779-781, contigmalloc sizeof(struct wb_list_data)+8 = ~296KB page-aligned contiguous memory) but wb_detach() frees sc->wb_ldata_ptr (if_wb.c:856-859), a DIFFERENT softc field (if_wbreg.h:377-378) that is never assigned anywhere in the tree (grep-exhaustive: only the declaration and the free reference it). The guard 'if (sc->wb_ldata_ptr)' is therefore always false and the block leaks on every detach, including all wb_attach error paths (they tail-call wb_detach at if_wb.c:827-829). Root-triggered (kldunload/device removal) resource-exhaustion vector on a hardware-gated driver. Not kernel-reproduced: the guest has no W89C840F NIC (env.txt).