From: Nicolai Buchwitz <nb@tipi-net.de>
To: sashiko@lists.linux.dev
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH net-next v8 4/7] net: bcmgenet: add XDP_TX support
Date: Thu, 30 Apr 2026 00:28:27 +0200 [thread overview]
Message-ID: <362a57c57af4eecd5214ea49070811f8@tipi-net.de> (raw)
In-Reply-To: <20260429211702.42E86C2BCB4@smtp.kernel.org>
On 29.4.2026 23:17, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 4 potential
> issue(s) to consider:
> - [High] Out-of-bounds array access in `bcmgenet_tx_reclaim` during
> interface teardown
> - [High] Incorrect DMA address calculation for local XDP_TX causes
> information leak and packet corruption
> - [High] Prepending `status_64` block overwrites XDP metadata and
> causes memory corruption
> - [Medium] XDP TX ring size is smaller than standard NAPI budget
> --
>
> commit 9add891fa4e7cf62ec26683116338b5877c21662
> Author: Nicolai Buchwitz <nb@tipi-net.de>
>
> net: bcmgenet: add XDP_TX support
>
> Implement XDP_TX using ring 16 (DESC_INDEX), the hardware default
> descriptor ring, dedicated to XDP TX for isolation from SKB TX queues.
>
>> diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
>> b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
>> index 1b60571446e1..3c3b0c44ea8a 100644
>> --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
>> +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
>> @@ -48,8 +48,10 @@
>>
>> #define GENET_Q0_RX_BD_CNT \
>> (TOTAL_DESC - priv->hw_params->rx_queues *
>> priv->hw_params->rx_bds_per_q)
>> +#define GENET_Q16_TX_BD_CNT 32
>
> Is it possible to drop packets here during bursts since this TX ring is
> smaller
> than the standard NAPI budget?
Yes, by design. If the ring fills, frames are dropped, which is standard
XDP backpressure. Same approach as bnxt, mvneta, and other drivers.
>
> The standard RX NAPI budget is 64, and TX completions are reclaimed
> only once
> before the RX loop. If the RX loop processes a full budget of 64
> packets and
> they all result in an XDP_TX action, the first 32 will fill the TX
> ring.
>
> The remaining 32 packets would fail in bcmgenet_xdp_xmit_frame()
> because
> ring->free_bds < 1, and be dropped.
>
> [ ... ]
>> @@ -2043,6 +2069,9 @@ static void bcmgenet_tx_reclaim_all(struct
>> net_device *dev)
>> do {
>> bcmgenet_tx_reclaim(dev, &priv->tx_rings[i++], true);
>> } while (i <= priv->hw_params->tx_queues &&
>> netif_is_multiqueue(dev));
>> +
>> + /* Also reclaim XDP TX ring */
>> + bcmgenet_tx_reclaim(dev, &priv->xdp_tx_ring, true);
>> }
>
> Can this cause an out-of-bounds array access during interface teardown?
>
> When bcmgenet_tx_reclaim_all() calls bcmgenet_tx_reclaim() with all ==
> true,
> it unconditionally calls netdev_tx_reset_queue(netdev_get_tx_queue(dev,
> ring->index)).
bcmgenet_tx_reclaim() does not call netdev_tx_reset_queue() or
netdev_get_tx_queue(). The only netdev_get_tx_queue() in the reclaim
path (in __bcmgenet_tx_reclaim, for BQL) is guarded by
"if (ring->index != DESC_INDEX)". The netdev_tx_reset_queue() loop in
bcmgenet_fini_dma() iterates indices 0..tx_queues only.
>
> The XDP TX ring has an index of 16 (DESC_INDEX), but the network device
> is
> allocated with only GENET_MAX_MQ_CNT + 1 TX queues (typically 5).
> Accessing
> index 16 of dev->_tx is out-of-bounds, and netdev_tx_reset_queue() will
> write
> to this invalid memory.
>
> [ ... ]
>> @@ -2299,11 +2328,96 @@ static struct sk_buff
>> *bcmgenet_xdp_build_skb(struct bcmgenet_rx_ring *ring,
>> return skb;
>> }
>>
>> +static bool bcmgenet_xdp_xmit_frame(struct bcmgenet_priv *priv,
>> + struct xdp_frame *xdpf, bool dma_map)
>> +{
> [ ... ]
>> + if (dma_map) {
> [ ... ]
>> + } else {
>> + struct page *page = virt_to_page(xdpf->data);
>> +
>> + /* For local XDP_TX the caller already prepended the TSB
>> + * into xdpf->data/len, so dma_len == xdpf->len.
>> + */
>> + dma_len = xdpf->len;
>> + mapping = page_pool_get_dma_addr(page) +
>> + sizeof(*xdpf) + xdpf->headroom;
>
> Does this calculation result in an incorrect DMA address?
>
> The calculation implicitly assumes that xdpf resides exactly at the
> beginning
> of the page. However, the driver configures the RX page pool with
> offset = XDP_PACKET_HEADROOM (typically 256 bytes).
>
> By omitting the distance from the start of the page to xdpf, the
> calculated
> DMA address points XDP_PACKET_HEADROOM bytes before the actual packet
> data,
> which could lead to transmitting uninitialized memory.
Correct, xdpf does reside at the start of the page.
xdp_convert_buff_to_frame()
stores the xdp_frame at xdp->data_hard_start, which equals
page_address(page)
for our page_pool layout. page_pool_get_dma_addr() returns the DMA
address
of the page start (not offset by .offset). sizeof(*xdpf) +
xdpf->headroom
equals xdpf->data - data_hard_start, pointing to the prepended TSB.
>
>> + dma_sync_single_for_device(kdev, mapping, dma_len,
>> + DMA_BIDIRECTIONAL);
>> + }
> [ ... ]
>> + case XDP_TX:
>> + /* Prepend a zeroed TSB (Transmit Status Block). The GENET
>> + * MAC has TBUF_64B_EN set globally, so hardware expects every
>> + * TX buffer to begin with a 64-byte struct status_64. Back
>> + * up xdp->data into the RSB area (which is no longer needed
>> + * after the BPF program ran) and zero it.
>> + */
>> + if (xdp->data - xdp->data_hard_start <
>> + sizeof(struct status_64) + sizeof(struct xdp_frame)) {
>> + page_pool_put_full_page(ring->page_pool, rx_page,
>> + true);
>> + return XDP_DROP;
>> + }
>> + xdp->data -= sizeof(struct status_64);
>> + xdp->data_meta -= sizeof(struct status_64);
>> + memset(xdp->data, 0, sizeof(struct status_64));
>
> Could this overwrite XDP metadata and cause memory corruption?
xdp_convert_buff_to_frame() validates (headroom - metasize) >=
sizeof(struct xdp_frame) and returns NULL otherwise; we drop the frame
in that case. The memset writes to [xdp->data - 64, xdp->data] before
the data shift, which was previously the RSB area, not the metadata
area. Both data and data_meta are shifted equally, preserving the
metasize gap.
>
> The space check does not account for metasize (xdp->data -
> xdp->data_meta).
> If the BPF program appended metadata, the memset() here completely
> overwrites
> it.
>
> Furthermore, if metasize is > 0, the shifted xdp->data_meta pointer
> could
> underflow and point exactly to or before xdp->data_hard_start. When
> xdp_convert_buff_to_frame() is subsequently called, it writes the
> xdp_frame
> structure at data_hard_start, which would overlap with the shifted
> data_meta.
Thanks
Nicolai
next prev parent reply other threads:[~2026-04-29 22:28 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-28 20:58 [PATCH net-next v8 0/7] net: bcmgenet: add XDP support Nicolai Buchwitz
2026-04-28 20:58 ` [PATCH net-next v8 1/7] net: bcmgenet: convert RX path to page_pool Nicolai Buchwitz
2026-05-01 1:37 ` Jakub Kicinski
2026-04-28 20:58 ` [PATCH net-next v8 2/7] net: bcmgenet: register xdp_rxq_info for each RX ring Nicolai Buchwitz
2026-04-28 20:58 ` [PATCH net-next v8 3/7] net: bcmgenet: add basic XDP support (PASS/DROP) Nicolai Buchwitz
2026-04-29 21:17 ` sashiko-bot
2026-04-29 22:24 ` Nicolai Buchwitz
2026-04-28 20:58 ` [PATCH net-next v8 4/7] net: bcmgenet: add XDP_TX support Nicolai Buchwitz
2026-04-29 21:17 ` sashiko-bot
2026-04-29 22:28 ` Nicolai Buchwitz [this message]
2026-05-01 1:39 ` Jakub Kicinski
2026-04-28 20:58 ` [PATCH net-next v8 5/7] net: bcmgenet: add XDP_REDIRECT and ndo_xdp_xmit support Nicolai Buchwitz
2026-04-29 21:17 ` sashiko-bot
2026-04-29 22:50 ` Nicolai Buchwitz
2026-05-01 1:40 ` Jakub Kicinski
2026-04-28 20:58 ` [PATCH net-next v8 6/7] net: bcmgenet: add XDP statistics counters Nicolai Buchwitz
2026-04-29 21:17 ` sashiko-bot
2026-04-29 22:39 ` Nicolai Buchwitz
2026-05-01 1:42 ` Jakub Kicinski
2026-04-28 20:58 ` [PATCH net-next v8 7/7] net: bcmgenet: reject MTU changes incompatible with XDP Nicolai Buchwitz
2026-04-29 21:17 ` sashiko-bot
2026-04-29 22:35 ` Nicolai Buchwitz
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=362a57c57af4eecd5214ea49070811f8@tipi-net.de \
--to=nb@tipi-net.de \
--cc=bpf@vger.kernel.org \
--cc=sashiko@lists.linux.dev \
/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.