netmap_mem_rings_create cleanup path leaks every allocated packet buffer: repeated failing ring creation permanently drains the global buffer pool (latent β module does not build on DFly)
Summary
On mid-way allocation failure, netmap_mem_rings_create jumps to cleanup which calls netmap_free_rings(na) - that helper only releases ring objects to the ring pool; it never releases the packet buffers whose indices sit in the successfully-allocated rings' slots. The correct teardown, netmap_mem_rings_delete, walks every slot and calls netmap_free_buf before freeing the rings. Each failed creation permanently leaks num_rings*slots buffers (bitmap bits stay 'in use', objfree never restored); repeated failing binds drain NETMAP_BUF_POOL to objfree==0 and every subsequent bind returns ENOMEM until reboot. LATENT (platform fact re-verified in-guest: module does not build - if_unused7 mismatch, build log in pack). Once netmap compiles: unpriv /dev/netmap user triggers allocation-failure loops -> global netmap memory-poisoned state. Fix: release slot buffers in the cleanup path mirroring rings_delete.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3396 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | β | 2.2 KB | β raw | |
| netmap_build.log | β | 12.2 KB | view raw | |
| fix.diff | β | 785 B | view raw | |
| manifest.json | β | 657 B | view raw | |
| verdict.json | β | 2.0 KB | view raw |
VERDICT β DF-3396: analysis-only (module does not build on DragonFly)
Root cause
netmap_mem_rings_create() (sys/net/netmap/netmap_mem2.c:918-993):
on allocation failure mid-way (either netmap_ring_malloc or
netmap_new_bufs failing for any ring) it jumps to cleanup: which
calls netmap_free_rings(na) (netmap_mem2.c:892-910). That helper only
releases the ring objects back to the ring pool
(netmap_ring_free per ring); it never releases the packet buffers
whose indices sit in the successfully-allocated rings' slots
(ring->slot[i].buf_idx, allocated by netmap_new_bufs at :948/:977).
Contrast the correct teardown, netmap_mem_rings_delete()
(netmap_mem2.c:995-1016), which walks every slot and calls
netmap_free_buf(na->nm_mem, ring->slot[i].buf_idx) before freeing
the rings.
Consequence (latent)
Each failed netmap_mem_rings_create permanently leaks
nkr_num_slots * num_rings buffers from the (global) NETMAP_BUF_POOL:
their bitmap bits stay clear ("in use") and objfree is never restored.
Repeated failing binds (e.g. rings too large for the current pool
configuration, or ring pool exhaustion after a sysctl resize) drain the
buffer pool until objfree hits 0 -> every subsequent netmap bind fails
with ENOMEM until reboot/module reload. Memory-pressure DoS by an
unprivileged user with access to /dev/netmap, requiring only the ability
to trigger allocation failure repeatedly.
Why no PoC
The netmap module does not build on this tree β verified concretely:
cd /usr/src/sys/net/netmap && make fails with
netmap_kern.h:747:27: error: 'struct ifnet' has no member named
'if_unused7' (15 errors, -Werror, EXIT=1) β see netmap_build.log.
The finding is therefore latent: it becomes reachable the moment the
module is fixed/ported. Consistent with pass-1 DF-0546..DF-0550, which
were filed at analysis confidence for the same reason.
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_testablefix.diff authored; cannot be built/validated because the netmap module itself does not compile on this tree.
fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
['VERDICT.md β cleanup-vs-delete asymmetry at netmap_mem2.c:987 vs :1005-1011', 'netmap_build.log β module build failure on this tree (15 errors)']
PoC changes
No executable PoC possible; analysis-only finding with concrete build-failure evidence.
Verified recommended fix
In the cleanup path, free each allocated ring's slot buffers (netmap_free_buf) before netmap_free_rings, mirroring netmap_mem_rings_delete.
Verdict
Latent (analysis-verified): netmap_mem_rings_create's cleanup path (netmap_mem2.c:987) frees ring objects but leaks every already-allocated packet buffer referenced by those rings' slots, unlike netmap_mem_rings_delete (:1005-1011) which frees slot buffers first; repeated failing ring creations drain the global buffer pool to permanent ENOMEM. PoC impossible on this tree: the netmap module itself does not compile (ifnet 'if_unused7' mismatch, netmap_build.log, EXIT=1).
No comments yet.