nfe_alloc_{rx,tx}_ring error paths destroy data[i].map in a loop over j β dmamap leak + tag map_count underflow on attach failure
Summary
Both ring-allocation failure paths run 'for (j...) bus_dmamap_destroy(ring->data_tag, ring->data[i].map);' - destroying the FAILING slot's map (NULL, since create sets *mapp=NULL on error) i times while the i successfully-created maps leak; dmat->map_count underflows by i because destroy decrements unconditionally. Verified NOT a double-free (busdma read). Index-typo fix [i]->[j].
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4052 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.9 KB | β raw | |
| VERDICT.md | β | 1.6 KB | β raw | |
| fix.diff | β | 633 B | view raw | |
| manifest.json | β | 628 B | view raw | |
| verdict.json | β | 2.2 KB | view raw |
DF-4052 β nfe_alloc_{rx,tx}_ring error paths destroy data[i].map in a loop over j (maps 0..i-1 leak; tag map_count underflows)
What
static int
nfe_alloc_rx_ring(...) /* :1642 */
{
...
for (i = 0; i < sc->sc_rx_ring_count; i++) {
error = bus_dmamap_create(ring->data_tag, BUS_DMA_WAITOK,
&ring->data[i].map);
if (error) {
...
goto fail;
}
}
return 0;
fail:
for (j = 0; j < i; ++j)
bus_dmamap_destroy(ring->data_tag, ring->data[i].map); /* :1726 - [i], not [j]! */
bus_dmamap_destroy(ring->data_tag, ring->data_tmpmap);
...
The cleanup loop iterates j but destroys ring->data[i].map β the map at
the failing index, which bus_dmamap_create has already set to NULL on
error (busdma_machdep.c:430: *mapp = NULL before return error). Each
iteration is therefore a NULL no-op while the i successfully-created maps
(data[0].map .. data[i-1].map) are leaked; additionally
bus_dmamap_destroy decrements dmat->map_count unconditionally
(busdma_machdep.c:440-448), so the tag's map count underflows by i and
the later bus_dma_tag_destroy runs against a bogus count.
The identical typo exists in nfe_alloc_tx_ring (:1987-1989).
Reachability
Requires bus_dmamap_create (a kmalloc(M_DEVBUF)) to fail mid-ring β
i.e. kernel-memory exhaustion during attach of an nfe(4) device β after
which attach aborts with the maps leaked forever (per attempt). Low
severity, OOM-gated, certain.
Fix
- bus_dmamap_destroy(ring->data_tag, ring->data[i].map);
+ bus_dmamap_destroy(ring->data_tag, ring->data[j].map);
in both functions (fix.diff).
Verification
Source-certain (double-checked that a NULL map destroy is a no-op and that
bus_dmamap_create NULLs *mapp on failure, so this is a leak, not a
double-free). Not runtime-verified: needs nfe hardware + induced
kmalloc failure. Status: untested.
DF-4052 VERDICT β [i]-vs-[j] typo in ring-allocation error paths
Status: untested (source-certain; Low severity; OOM + hardware gated)
if_nfe.c:1725-1726and:1988-1989: cleanup loopsfor (j = 0; j < i; ++j) bus_dmamap_destroy(ring->data_tag, ring->data[i].map);destroy the failing slot's map ([i])itimes instead of theisuccessfully-created maps ([0..i-1]).- Verified semantics that bound the impact:
bus_dmamap_createwrites*mapp = NULLbefore returning error (sys/platform/pc64/x86_64/busdma_machdep.c:425-433) β destroyingdata[i].mapis a NULL no-op β leak, not double-free (an early audit hypothesis, refuted by reading busdma).bus_dmamap_destroystill doesdmat->map_count--for NULL maps (busdma_machdep.c:440-448) β tag map-count underflow byi.- Trigger: kmalloc failure inside
bus_dmamap_createmid-ring duringnfe_attach(memory-pressure-gated) β attach fails,nfe_detachruns, andidmamaps (~64-88 bytes each) plus the bogus tag count persist. Repeatable per attach attempt. - No memory-safety consequence demonstrated; classic error-path resource leak. Low severity, confidence certain, not runtime-verifiable on this guest (no nForce NIC; inducing the OOM inside attach is not possible without the device).
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_testableHardware-gated; one-character index fix, source-level only.
findings/poc/DF-4052/fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
README.md/VERDICT.md with both loops quoted and the busdma semantics (NULL no-op destroy, unconditional map_count--) that bound impact to leak+counter-underflow
Verified recommended fix
Index the destroy loop with j, not i, in both nfe_alloc_rx_ring and nfe_alloc_tx_ring; see fix.diff
Verdict
Source-certain error-path typo: nfe_alloc_rx_ring (if_nfe.c:1725-1726) and nfe_alloc_tx_ring (:1988-1989) run 'for (j = 0; j < i; ++j) bus_dmamap_destroy(ring->data_tag, ring->data[i].map);' - destroying the failing slot's (NULL) map i times instead of the i successfully-created maps 0..i-1, which leak; dmat->map_count underflows by i because bus_dmamap_destroy decrements unconditionally (busdma_machdep.c:440-448). Verified NOT a double-free because bus_dmamap_create sets *mapp = NULL before returning error (busdma_machdep.c:425-433). Trigger is a bus_dmamap_create kmalloc failure mid-ring during attach (kernel memory pressure) on nfe(4) hardware - not reproducible on this guest (no nForce NIC), status untested. Low severity resource leak; classic pass-2 error-path class; one-character fix ([i] -> [j]) in both functions.
No comments yet.