All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Taehee Yoo" <ap420073@gmail.com>
Cc: dri-devel@lists.freedesktop.org, bpf@vger.kernel.org,
	media-ci@linuxtv.org
Subject: Re: [RFC PATCH net-next 11/13] bnxt_en: add knod XDP offload support
Date: Tue, 21 Jul 2026 07:18:00 +0000	[thread overview]
Message-ID: <20260721071800.8CFE91F00A3D@smtp.kernel.org> (raw)
In-Reply-To: <20260719175857.4071636-12-ap420073@gmail.com>

Thank you for your contribution! Sashiko AI review found 10 potential issue(s) to consider:
- [High] Memory leaks in `bnxt_rx_pkt` when `BNXT_RX_OFFLOAD_MODE` is active.
- [High] Incomplete error rollback during offload attach leads to NULL pointer dereferences.
- [High] Invalid free of knod core-owned memory in `bnxt_knod_uninit()`.
- [High] Detaching the offload accelerator silently corrupts standard XDP state.
- [High] Type confusion via unconditional cast of `netmem_ref` to `net_iov`.
- [High] Prematurely setting `bp->knodev` to NULL during detach triggers multiple NULL pointer dereferences.
- [High] Ignoring the return value of `bnxt_knod_init()` causes a NULL pointer dereference on unload.
- [High] Head-of-line blocking and packet stalls in `bnxt_rx_offload_act_handler` due to restrictive limit based on TX availability.
- [High] Unbalanced lifecycle operations for `knod_dev_start` leading to operational failure or resource leaks.
- [High] Incorrect queue bounds check in `bnxt_rx_offload_act_handler()` leads to out-of-bounds access and stalls.
--

--- Patch [11]: [RFC PATCH net-next 11/13] bnxt_en: add knod XDP offload support ---
commit bc105761ac52d8c362d8a3b4da5f278514f84ca4
Author: Taehee Yoo <ap420073@gmail.com>

bnxt_en: add knod XDP offload support

This commit introduces knod XDP offload support for the bnxt_en driver,
allowing it to register as a knod NIC. It sets up the transmission of
accelerator verdicts through the XDP TX ring and feeds received packets
to the accelerator over the per-queue SPSC ring.

> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> index 7513618793daf..6ddf4bafc3d47 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
[ ... ]
> @@ -2249,6 +2303,36 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
>  	len = flags >> RX_CMP_LEN_SHIFT;
>  	dma_addr = rx_buf->mapping;
>  
> +	if (BNXT_RX_OFFLOAD_MODE(bp)) {
> +		if (bnxt_alloc_rx_off_netmem(bp, rxr, rxr->rx_prod,
> +					     GFP_ATOMIC)) {
> +			bnxt_reuse_rx_data(rxr, cons, data);
> +			bnapi->cp_ring.sw_stats->rx.rx_buf_errors++;
> +		} else {
> +			struct knod_work_priv *wpriv;
> +			struct spsc_bd *bd;
> +
> +			if (bnapi->index >= KNOD_SPSC_MAX) {
> +				rc = 1;
> +				goto next_rx;

[Severity: High]
Does this path leak the current data buffer? It appears to jump to
next_rx without freeing or reusing data.

> +			}
> +
> +			wpriv = &bp->knodev->wpriv[bnapi->index];
> +			if (spsc_produce(&wpriv->spsc_bds, (void **)&bd)) {
> +				bnxt_reuse_rx_data(rxr, cons, data);

[Severity: High]
If the accelerator SPSC ring is full and spsc_produce() fails, doesn't
calling bnxt_reuse_rx_data() here permanently leak the newly allocated
replacement buffer by overwriting it with the old data?

> +			} else {
> +				bd->netmem = (netmem_ref)data;
> +				bd->len = len;
> +				bd->off = bp->rx_offset;
> +				bd->page_idx = net_iov_binding_idx(
> +					netmem_to_net_iov((netmem_ref)data));

[Severity: High]
Is it safe to unconditionally cast data to a net_iov here? The RX page pool
allows standard pages, so if a standard page is used, could this cause type
confusion and out-of-bounds reads?

> +				spsc_produce_commit(&wpriv->spsc_bds);
> +			}
> +		}
> +		rc = 1;
> +		goto next_rx;
> +	}
> +
>  	if (bnxt_xdp_attached(bp, rxr)) {
[ ... ]
> @@ -13356,6 +13489,7 @@ static int bnxt_open(struct net_device *dev)
>  						   BNXT_RESTART_ULP_SP_EVENT);
>  		}
>  	}
> +	bnxt_rx_offload_start(bp);

[Severity: High]
Is it intended to unconditionally call bnxt_rx_offload_start() here? If the
preceding __bnxt_open_nic() fails, this will start the accelerator while
the NIC remains down, which could leak active workers.

>  
>  	return rc;
>  }
[ ... ]
> @@ -17198,6 +17336,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
>  	bnxt_print_device_info(bp);
>  
>  	pci_save_state(pdev);
> +	bnxt_knod_init(bp);

[Severity: High]
Could this leave the driver in a corrupted state if memory allocation fails?
bnxt_knod_init() can return -ENOMEM, but the error is ignored here. If it
fails, bp->knetdev remains NULL, which might lead to a NULL pointer
dereference during module unload in bnxt_knod_uninit().

>  
>  	return 0;
>  init_err_cleanup:
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
> index 9e5009be8e989..a264a2cf8302a 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
[ ... ]
> @@ -441,19 +446,123 @@ static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog)
>  	return 0;
>  }
>  
> +
> +static int bnxt_xdp_offload_set(struct bnxt *bp, int enable)
> +{
[ ... ]
> +	if (enable) {
> +		bnxt_set_rx_skb_mode(bp, BNXT_FLAG_RX_OFFLOAD_MODE);
> +		xdp_features_set_redirect_target_locked(dev, true);
> +	} else {
> +		xdp_features_clear_redirect_target_locked(dev);
> +		bnxt_set_rx_skb_mode(bp, false);

[Severity: High]
Does detaching the offload accelerator silently corrupt standard XDP state?
If a standard XDP program is still active (bp->xdp_prog), explicitly clearing
the BNXT_FLAG_RX_PAGE_MODE flag here without restoring the correct settings
for the active standard XDP program could cause packet processing failures.

> +	}
> +	bp->tx_nr_rings_xdp = tx_xdp;
> +	bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tc + tx_xdp;
> +	tx_cp = bnxt_num_tx_to_cp(bp, bp->tx_nr_rings);
> +	bp->cp_nr_rings = max_t(int, tx_cp, bp->rx_nr_rings);
> +	bnxt_set_tpa_flags(bp);
> +	bnxt_set_ring_params(bp);
> +
> +	if (netif_running(dev))
> +		return bnxt_open_nic(bp, true, false);

[Severity: High]
When attaching offload to an already-running interface, is the accelerator
ever started? This restarts the NIC via bnxt_open_nic(), but it seems to
omit a call to bnxt_rx_offload_start(), which might leave the accelerator
unable to process packets.

> +
> +	return 0;
> +}
[ ... ]
> +static int bnxt_rx_offload_xdp_attach(struct knod_dev *knodev)
> +{
> +	struct bnxt *bp = netdev_priv(knodev->netdev);
> +	int rc;
> +
> +	WRITE_ONCE(bp->knodev, knodev);
> +	rc = bnxt_xdp_offload_set(bp, true);
> +	if (rc)
> +		WRITE_ONCE(bp->knodev, NULL);

[Severity: High]
Could this error handling path lead to a NULL pointer dereference? If
bnxt_xdp_offload_set() sets BNXT_FLAG_RX_OFFLOAD_MODE but subsequently
fails, bp->knodev is set back to NULL without clearing the offload flag. A
later stats read or interface up might see the flag and dereference the
NULL knodev.

> +
> +	return rc;
> +}
> +
> +static int bnxt_rx_offload_xdp_detach(struct knod_dev *knodev)
> +{
> +	struct bnxt *bp = netdev_priv(knodev->netdev);
> +
> +	WRITE_ONCE(bp->knodev, NULL);
> +	bnxt_xdp_offload_set(bp, false);

[Severity: High]
Is it safe to set bp->knodev to NULL before shutting down the interface?
Since BNXT_RX_OFFLOAD_MODE is still active until bnxt_xdp_offload_set()
finishes, concurrent NAPI polling in bnxt_rx_pkt() or teardown paths like
bnxt_rx_offload_clear_napi() could observe the flag and dereference the NULL
pointer.

> +
> +	return 0;
> +}
[ ... ]
> +int bnxt_rx_offload_act_handler(struct bnxt_napi *bnapi, int budget)
> +{
> +	struct bnxt_tx_ring_info *txr = bnapi->tx_ring[0];
> +	struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
> +	struct spsc_bd *bds[NAPI_POLL_WEIGHT];
> +	u32 tx_avail, cnt, i, nxmit = 0;
> +	struct knod_dev *knodev;
> +	struct knod_work_priv *wpriv;
> +	struct napi_struct *napi;
> +	struct bnxt *bp = bnapi->bp;
> +	dma_addr_t mapping;
> +
> +	knodev = bp->knodev;
> +	if (!knodev)
> +		return 0;
> +
> +	if (bnapi->index >= bp->dev->real_num_tx_queues) {

[Severity: High]
Should this bounds check compare against KNOD_SPSC_MAX instead of the number
of TX queues? If there are more RX queues than TX queues, valid RX NAPI
instances might return early and abandon packets. Conversely, if there are
many TX queues, this could fail to properly bound accesses to the wpriv array.

> +		this_cpu_inc(knodev->stats->tx_dropped);
> +		return 0;
> +	}
> +
> +	wpriv = &knodev->wpriv[bnapi->index];
> +	napi = READ_ONCE(wpriv->napi);
> +	if (!napi)
> +		return 0;
> +
> +	tx_avail = bnxt_tx_avail(bp, txr);
> +	cnt = min_t(u32, NAPI_POLL_WEIGHT, tx_avail);
> +	cnt = min_t(u32, cnt, budget);
> +	if (!cnt)
> +		return 0;

[Severity: High]
Could this early return cause head-of-line blocking and permanent packet
stalls? If the TX ring is full (tx_avail == 0), cnt becomes 0. Returning
immediately skips knod_dev_xdp_drain_pass(), which could trap packets meant
for the host stack indefinitely.

> +
> +	spsc_release(&wpriv->spsc_bds, (void **)bds, cnt, &cnt);
> +	if (!cnt)
> +		return 0;
> +
> +	for (i = 0; i < cnt; i++) {
> +		switch (bds[i]->act) {
> +		case KNOD_ACT_INFLIGHT:
> +		case KNOD_IPSEC_INFLIGHT:
> +			goto stop_release;
> +		case XDP_TX:
> +			mapping = netmem_to_net_iov(bds[i]->netmem)->desc.dma_addr +
> +				  bds[i]->off;

[Severity: High]
Can this path be reached when netmem is a standard page rather than a DMABUF?
If so, using netmem_to_net_iov() without verifying netmem_is_net_iov() could
misinterpret standard page structure fields as DMA addresses, potentially
causing memory corruption.

> +			__bnxt_xmit_netmem(bp, txr, mapping, bds[i]->len,
> +					   bds[i]->netmem);
[ ... ]
> +void bnxt_knod_uninit(struct bnxt *bp)
> +{
> +	knod_netdev_unregister(bp->knetdev);
> +	kfree(bp->knetdev);
> +	bp->knetdev = NULL;
> +	kfree(bp->knodev);

[Severity: High]
Is it correct to call kfree(bp->knodev) here? bp->knodev points to a
struct knod_dev allocated and managed by the knod core framework, so freeing
it from the driver could result in heap corruption or a use-after-free
during device unbind.

> +	WRITE_ONCE(bp->knodev, NULL);
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260719175857.4071636-1-ap420073@gmail.com?part=11

  reply	other threads:[~2026-07-21  7:18 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-19 17:58 [RFC PATCH net-next 00/13] net: knod: in-kernel network offload device Taehee Yoo
2026-07-19 17:58 ` [RFC PATCH net-next 01/13] net: knod: add uapi and core headers Taehee Yoo
2026-07-21  7:17   ` sashiko-bot
2026-07-19 17:58 ` [RFC PATCH net-next 02/13] net: devmem: extend memory provider for knod Taehee Yoo
2026-07-20 19:43   ` Mina Almasry
2026-07-21 16:15     ` Taehee Yoo
2026-07-21  7:17   ` sashiko-bot
2026-07-19 17:58 ` [RFC PATCH net-next 03/13] net: core: add XDP_MODE_HW offload hook " Taehee Yoo
2026-07-21  7:17   ` sashiko-bot
2026-07-19 17:58 ` [RFC PATCH net-next 04/13] net: knod: add offload device core and control plane Taehee Yoo
2026-07-21  7:17   ` sashiko-bot
2026-07-19 17:58 ` [RFC PATCH net-next 05/13] bpf: offload: allow PERCPU_ARRAY maps for offloaded programs Taehee Yoo
2026-07-21  7:17   ` sashiko-bot
2026-07-19 17:58 ` [RFC PATCH net-next 06/13] drm/amdkfd: prepare kfd core for the knod provider Taehee Yoo
2026-07-21  7:17   ` sashiko-bot
2026-07-19 17:58 ` [RFC PATCH net-next 07/13] drm/amdkfd: add knod provider core Taehee Yoo
2026-07-21  7:17   ` sashiko-bot
2026-07-19 17:58 ` [RFC PATCH net-next 08/13] drm/amdkfd: add GPU instruction emitter and disassembler Taehee Yoo
2026-07-20 20:05   ` Natalie Vock
2026-07-20 20:53     ` Andrew Lunn
2026-07-21 16:36       ` Hoyeon Lee
2026-07-19 17:58 ` [RFC PATCH net-next 09/13] drm/amdkfd: add BPF-to-GPU JIT offload Taehee Yoo
2026-07-19 17:58 ` [RFC PATCH net-next 10/13] net/mlx5e: add knod XDP offload support Taehee Yoo
2026-07-21  7:17   ` sashiko-bot
2026-07-19 17:58 ` [RFC PATCH net-next 11/13] bnxt_en: " Taehee Yoo
2026-07-21  7:18   ` sashiko-bot [this message]
2026-07-19 17:58 ` [RFC PATCH net-next 12/13] selftests: drivers/net: add knod tests Taehee Yoo
2026-07-21  7:18   ` sashiko-bot
2026-07-19 17:58 ` [RFC PATCH net-next 13/13] drm/amdkfd: add IPsec full-packet offload Taehee Yoo
2026-07-21  7:18   ` sashiko-bot
2026-07-20 19:18 ` [RFC PATCH net-next 00/13] net: knod: in-kernel network offload device Mina Almasry
2026-07-21 15:17   ` Taehee Yoo

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=20260721071800.8CFE91F00A3D@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=ap420073@gmail.com \
    --cc=bpf@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=media-ci@linuxtv.org \
    --cc=sashiko-reviews@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.