From: bugzilla@dpdk.org
To: dev@dpdk.org
Subject: [DPDK/ethdev Bug 1886] net/avp: tx_burst callbacks free mbufs then return short count, causing double-free
Date: Thu, 19 Feb 2026 01:23:55 +0000 [thread overview]
Message-ID: <bug-1886-3@http.bugs.dpdk.org/> (raw)
http://bugs.dpdk.org/show_bug.cgi?id=1886
Bug ID: 1886
Summary: net/avp: tx_burst callbacks free mbufs then return
short count, causing double-free
Product: DPDK
Version: 25.11
Hardware: All
OS: All
Status: UNCONFIRMED
Severity: normal
Priority: Normal
Component: ethdev
Assignee: dev@dpdk.org
Reporter: stephen@networkplumber.org
Target Milestone: ---
Recent audit of how tx_pkt_burst is (or is not) being handled in drivers found
this.
The AVP PMD tx_burst callbacks (`avp_xmit_pkts` and `avp_xmit_scattered_pkts`)
violate the `rte_eth_tx_burst()` mbuf ownership contract. Both functions free
all mbufs they process, but return the result of `avp_fifo_put()` which may be
smaller. When the caller follows the standard pattern:
```c
n = rte_eth_tx_burst(port, txq, mbufs, nb_pkts);
for (i = n; i < nb_pkts; i++)
rte_pktmbuf_free(mbufs[i]);
```
any mbufs that were freed by the driver but not reported as consumed will be
freed a second time by the caller.
There are several additional bugs in the same code paths, listed below.
### Bug 1: Double-free in avp_xmit_pkts (avp_ethdev.c ~line 1917 vs 1926)
The function frees each mbuf at line 1917 (`rte_pktmbuf_free(m)`) inside the
processing loop which runs for `count` packets. At line 1924 it calls
`avp_fifo_put()` and returns the FIFO result `n` at line 1926. If the FIFO
fills between the earlier free-count check and the put, `n < count`, and
`tx_pkts[n..count-1]` get double-freed.
Fix: return `count` instead of `n`, since all `count` mbufs have already been
consumed.
### Bug 2: Double-free in avp_xmit_scattered_pkts (line 1793 vs 1809)
Same pattern. All `nb_pkts` mbufs are freed in the loop (line 1793) but
`avp_fifo_put()` result is returned (line 1809).
Fix: return `nb_pkts` instead of `n`.
### Bug 3: AVP host buffer leak on partial avp_fifo_get (lines 1862-1866)
```c
n = avp_fifo_get(alloc_q, (void **)&avp_bufs, count);
if (unlikely(n != count)) {
txq->errors++;
return 0;
}
```
If `avp_fifo_get()` returns a partial result (0 < n < count), those `n` AVP
buffers have been dequeued from the allocation queue but are never returned.
They are permanently leaked. The same pattern exists in
`avp_xmit_scattered_pkts` at lines 1769-1774.
Fix: return partial buffers to alloc_q before returning:
```c
if (unlikely(n != count)) {
if (n > 0)
avp_fifo_put(alloc_q, (void **)&avp_bufs[0], n);
return 0;
}
```
### Bug 4: Wrong variable in error comparison (line 1806)
```c
if (unlikely(n != orig_nb_pkts))
txq->errors += (orig_nb_pkts - n);
```
`n` is the result of putting `nb_pkts` entries, but it is compared against
`orig_nb_pkts` which is the original caller count before clamping by
`AVP_MAX_TX_BURST` and resource limits. These values differ whenever the
burst was clamped, so the error count is wrong.
Fix: compare against `nb_pkts`.
### Bug 5: Spurious error counting for unconsumed packets
Both TX functions increment `txq->errors` for all `nb_pkts` when returning 0
due to resource exhaustion or detach (lines 1714, 1761, 1832, 1855). Since
the function returns 0, no mbufs were consumed — the caller still owns all of
them. These are not transmission errors; they are backpressure. Inflating
`oerrors` is misleading.
Fix: remove the error increments on the early-return-zero paths.
### Bug 6: Oversized packets silently truncated (lines 1886-1899)
When a packet exceeds both `guest_mbuf_size` and `host_mbuf_size`,
`avp_xmit_pkts` truncates it to the smaller buffer size and transmits a
corrupt frame. Per the tx_burst contract, the driver should consume and
free the mbuf and count it in tx_errors, not send garbage.
Fix: set the AVP buffer length to 0 (skip the copy) and count the error.
## Steps to Reproduce
Code inspection of `drivers/net/avp/avp_ethdev.c` at tag v26.03-rc1.
The double-free (bugs 1-2) can trigger when the tx FIFO fills between the
`avp_fifo_free_count()` check and the `avp_fifo_put()` call. This is a race
against the host consumer and is timing-dependent.
The buffer leak (bug 3) triggers when `avp_fifo_get()` from the alloc queue
returns a partial result, which can occur under host-side memory pressure.
## Suggested Patch
A patch addressing all six issues is available. The key changes are:
- Return the number of mbufs freed (consumed) rather than the FIFO put count
- Return partially dequeued AVP buffers on allocation failure
- Remove error counting for unconsumed packets (backpressure is not an error)
- Drop oversized packets instead of truncating
- Fix the orig_nb_pkts vs nb_pkts comparison
--
You are receiving this mail because:
You are the assignee for the bug.
reply other threads:[~2026-02-19 1:23 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=bug-1886-3@http.bugs.dpdk.org/ \
--to=bugzilla@dpdk.org \
--cc=dev@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.