All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Koichiro Den" <den@valinux.co.jp>
Cc: ntb@lists.linux.dev
Subject: Re: [PATCH net 1/4] NTB: ntb_transport: Recycle TX entries before client callbacks
Date: Tue, 18 Aug 2026 05:35:41 +0000	[thread overview]
Message-ID: <20260818053541.E5CD31F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260817053519.4135287-2-den@valinux.co.jp>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

Pre-existing issues:
- [High] Memory leak of client data buffers (e.g., network sk_buff) in ntb_process_tx() error path.
- [High] Uninitialized variable qp->last_cookie on the TX DMA path defeats DMA synchronization during queue teardown.
- [High] Pending TX queue entries and their associated payloads are permanently leaked when the DMA engine is terminated.
- [High] TOCTOU race on qp->tx_handler and qp->cb_data leads to a NULL pointer dereference.
--

--- Patch [1]: [PATCH net 1/4] NTB: ntb_transport: Recycle TX entries before client callbacks ---
commit 48d0145779a008cdeb1d647661138f0bd59414bb
Author: Koichiro Den <den@valinux.co.jp>

NTB: ntb_transport: Recycle TX entries before client callbacks

ntb_tx_copy_callback() invokes the client callback before returning the
entry to tx_free_q. The callback may wake a stopped client queue, only
for the next enqueue to find no local entry and return -EBUSY. The window
is narrow, but the retry is unnecessary.

Fixes: fce8a7bb5b4b ("PCI-Express Non-Transparent Bridge Support")
Cc: stable@vger.kernel.org
Signed-off-by: Koichiro Den <den@valinux.co.jp>

> diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
> index f59f926d4bfaa..e92b96f4afad8 100644
> --- a/drivers/ntb/ntb_transport.c
> +++ b/drivers/ntb/ntb_transport.c
[ ... ]
> @@ -1768,15 +1775,13 @@ static void ntb_tx_copy_callback(void *data,
>  	 * "link down" or similar.  Since no payload is being sent in these
>  	 * cases, there is nothing to add to the completion queue.
>  	 */
> -	if (entry->len > 0) {
> -		qp->tx_bytes += entry->len;
> -
> -		if (qp->tx_handler)
> -			qp->tx_handler(qp, qp->cb_data, entry->cb_data,
> -				       entry->len);
> -	}
> +	if (len > 0)
> +		qp->tx_bytes += len;
>  
>  	ntb_list_add(&qp->ntb_tx_free_q_lock, &entry->entry, &qp->tx_free_q);
> +
> +	if (len > 0 && qp->tx_handler)
> +		qp->tx_handler(qp, qp->cb_data, cb_data, len);

[Severity: High]
This is a pre-existing issue, but does this introduce a race condition leading
to a null pointer dereference?

In ntb_tx_copy_callback(), this code checks if qp->tx_handler is non-null
before calling it:

drivers/ntb/ntb_transport.c:ntb_tx_copy_callback() {
    ...
    if (len > 0 && qp->tx_handler)
        qp->tx_handler(qp, qp->cb_data, cb_data, len);
    ...
}

Concurrently, ntb_transport_free_queue() blindly zeroes qp->tx_handler and
qp->cb_data:

drivers/ntb/ntb_transport.c:ntb_transport_free_queue() {
    ...
    qp->cb_data = NULL;
    qp->rx_handler = NULL;
    qp->tx_handler = NULL;
    ...
}

Because there is no synchronization protecting the execution of the DMA tasklet
and the teardown clearing of these pointers, can the tasklet evaluate
qp->tx_handler as non-null, but then dereference a subsequently null
qp->tx_handler, or pass a null qp->cb_data pointer to the network callback?


[Severity: High]
This is a pre-existing issue, but does ntb_process_tx() leak the SKB?

If a transmitted packet length exceeds the maximum frame size, ntb_process_tx()
invokes qp->tx_handler() with NULL instead of the original packet buffer:

drivers/ntb/ntb_transport.c:ntb_process_tx() {
    ...
    if (entry->len > qp->tx_max_frame - sizeof(struct ntb_payload_header)) {
        if (qp->tx_handler)
            qp->tx_handler(qp, qp->cb_data, NULL, -EIO);
    ...
}

Because the network callback exits early if data is NULL, it fails to free the
SKB:

drivers/net/ntb_netdev.c:ntb_netdev_tx_handler() {
    ...
    skb = data;
    if (!skb || !ndev)
        return;
    ...
}

Furthermore, ntb_process_tx() returns 0 to the caller, preventing the network
stack from freeing it on failure.


[Severity: High]
This is a pre-existing issue, but does the uninitialized qp->last_cookie defeat
DMA synchronization during queue teardown?

ntb_transport_free_queue() attempts to wait for pending TX DMA transactions:

drivers/ntb/ntb_transport.c:ntb_transport_free_queue() {
    ...
    dma_sync_wait(chan, qp->last_cookie);
    ...
}

However, ntb_async_tx_submit() drops the DMA cookie instead of assigning it to
qp->last_cookie:

drivers/ntb/ntb_transport.c:ntb_async_tx_submit() {
    ...
    cookie = dmaengine_submit(txd);
    if (dma_submit_error(cookie))
        goto err_set_unmap;

    dmaengine_unmap_put(unmap);
    dma_async_issue_pending(chan);
    return 0;
    ...
}

Could the TX synchronization wait evaluate either 0 or an unrelated RX cookie on
the TX DMA channel, leading to premature termination of in-flight TX DMA
transfers?


[Severity: High]
This is a pre-existing issue, but are pending TX queue entries and their
associated payloads permanently leaked when the DMA engine is terminated?

During queue teardown, dmaengine_terminate_all() is called:

drivers/ntb/ntb_transport.c:ntb_transport_free_queue() {
    ...
    dmaengine_terminate_all(chan);
    ...
}

This aborts any pending or active DMA descriptors. The driver relies entirely
on DMA completion callbacks to return entries to qp->tx_free_q and to invoke
the client network teardown logic.

The teardown routine then only cleans up entries present in the idle lists:

drivers/ntb/ntb_transport.c:ntb_transport_free_queue() {
    ...
    while ((entry = ntb_list_rm(&qp->ntb_tx_free_q_lock, &qp->tx_free_q)))
        kfree(entry);

    while ((entry = ntb_list_rm(&qp->ntb_tx_offl_q_lock, &qp->tx_offl_q)))
        kfree(entry);
    ...
}

Will this permanently leak active entries and their corresponding client payloads
if transactions are in-flight during module unload or link down events?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260817053519.4135287-1-den@valinux.co.jp?part=1

  reply	other threads:[~2026-08-18  5:35 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-17  5:35 [PATCH net 0/4] net: ntb_netdev: Fix TX completion and error handling Koichiro Den
2026-08-17  5:35 ` [PATCH net 1/4] NTB: ntb_transport: Recycle TX entries before client callbacks Koichiro Den
2026-08-18  5:35   ` sashiko-bot [this message]
2026-08-17  5:35 ` [PATCH net 2/4] net: ntb_netdev: Fix TX busy and drop handling Koichiro Den
2026-08-17  5:35 ` [PATCH net 3/4] NTB: ntb_transport: Fail TX enqueue when the QP link is down Koichiro Den
2026-08-18  5:35   ` sashiko-bot
2026-08-17  5:35 ` [PATCH net 4/4] NTB: ntb_transport: Reject oversized TX buffers Koichiro Den
2026-08-18  5:35   ` sashiko-bot

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=20260818053541.E5CD31F00A3A@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=den@valinux.co.jp \
    --cc=ntb@lists.linux.dev \
    --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.