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 09/11] NTB: ntb_transport: Stop QP work before freeing a queue
Date: Mon, 07 Sep 2026 14:50:53 +0000	[thread overview]
Message-ID: <20260907145054.D177D1F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260907142429.951930-10-den@valinux.co.jp>

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

Pre-existing issues:
- [High] ntb_transport_free() cancels work items before clearing context, which can cause a use-after-free if the hardware triggers a link event during shutdown.
- [High] Data race between `ntb_transport_link_cleanup` and `ntb_transport_free_queue` causes invocation of a NULL or freed event_handler.
- [High] Using the deprecated `dmaengine_terminate_all()` fails to wait for running DMA callbacks, causing a race with list draining and freeing.
- [Medium] Unallocated queues leak rx_free_q memory entries when the module is unloaded.
- [Medium] Memory leak of TX queue entries if DMA transfers are aborted during teardown.
--

commit 252961726612772103a0f740acf1bbca22443e1c
Author: Koichiro Den <den@valinux.co.jp>

NTB: ntb_transport: Stop QP work before freeing a queue

This commit cancels the link cleanup and delayed link work items before freeing
a queue pair (QP) to prevent use-after-free issues. It transitions to using
disable_work_sync() and enable_work() to stop workers instead of just
canceling them.

> diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
> index a902fce4ba602..d009bb5bb54bb 100644
> --- a/drivers/ntb/ntb_transport.c
> +++ b/drivers/ntb/ntb_transport.c
[ ... ]
> @@ -2209,6 +2214,10 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp)
>  
>  	pdev = qp->ndev->pdev;
>  
> +	qp->client_ready = false;
> +	disable_work_sync(&qp->link_cleanup);
> +	disable_delayed_work_sync(&qp->link_work);
> +	qp->link_is_up = false;
>  	qp->active = false;
>  
>  	if (qp->tx_offload_thread) {
[ ... ]
> @@ -2256,8 +2265,6 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp)
>  	ntb_db_set_mask(qp->ndev, qp_bit);
>  	tasklet_kill(&qp->rxc_db_work);
>  
> -	cancel_delayed_work_sync(&qp->link_work);
> -
>  	qp->cb_data = NULL;
>  	qp->rx_handler = NULL;
>  	qp->tx_handler = NULL;

[Severity: High]
This is a pre-existing issue, but there appears to be a data race when clearing
these handler pointers in ntb_transport_free_queue():

    qp->cb_data = NULL;
    qp->rx_handler = NULL;
    qp->tx_handler = NULL;
    qp->event_handler = NULL;

These pointers are cleared without holding any locks. If the physical link
goes down at the same time, the workqueue executes ntb_qp_link_cleanup(),
which checks qp->event_handler. Since ntb_transport_free_queue() clears
its allocation bit at the very end of the function, could the cleanup worker
race and call the event handler with a NULL pointer, or use qp->cb_data as
context after the client has freed the backing memory?

[Severity: Medium]
This is a pre-existing issue, but I noticed a potential leak of TX queue
entries in ntb_transport_free_queue() during DMA teardown:

    /* Try to be nice and wait for any queued DMA engine
     * transactions to process before smashing it with a rock
     */
    dma_sync_wait(chan, qp->last_cookie);
    dmaengine_terminate_all(chan);

If dma_sync_wait() times out or fails, dmaengine_terminate_all() will abort
pending transfers without invoking their completion callbacks. Since the TX
entries aren't tracked on a pending list like RX (where rx_post_q is properly
tracked and freed), will these bypassed entries be permanently leaked?

[Severity: High]
This is a pre-existing issue, but also in ntb_transport_free_queue() regarding
the DMA teardown:

    dma_sync_wait(chan, qp->last_cookie);
    dmaengine_terminate_all(chan);
    dma_release_channel(chan);

Using the deprecated dmaengine_terminate_all() fails to wait for running DMA
callbacks on other CPUs. Since a callback like ntb_rx_copy_callback() could
be running concurrently (e.g. in a tasklet) and accessing entries while
ntb_transport_free_queue() proceeds to drain and free the rx_post_q and
rx_free_q lists, could this lead to a use-after-free or list corruption?
Should we be using dmaengine_terminate_sync() instead to guarantee callbacks
have finished?

[Severity: High]
This is a pre-existing issue, but I noticed something in ntb_transport_free()
that might cause a use-after-free:

drivers/ntb/ntb_transport.c:ntb_transport_free() {
    ...
    cancel_work_sync(&nt->link_cleanup);
    cancel_delayed_work_sync(&nt->link_work);
    ...
    ntb_link_disable(ndev);
    ntb_clear_ctx(ndev);
    ...
}

If ntb_link_disable() triggers a hardware link down interrupt, and
ntb_clear_ctx() hasn't been called yet to unregister callbacks, the ISR
could invoke ntb_transport_event_callback(), which reschedules
nt->link_cleanup:

        schedule_work(&nt->link_cleanup);

Since nt is freed shortly after with kfree(nt), wouldn't the scheduled work
item remain on the workqueue and dereference the freed memory when executed?

[Severity: Medium]
This is a pre-existing issue, but there appears to be a memory leak related
to unallocated QPs during module unload.

When the link comes up, ntb_transport_setup_qp_mw() allocates entries for all
QPs up to nt->qp_count, regardless of active client allocations:

        for (i = qp->rx_alloc_entry; i < qp->rx_max_entry; i++) {
                entry = kzalloc_node(sizeof(*entry), GFP_KERNEL, node);
                ...
                ntb_list_add(&qp->ntb_rx_q_lock, &entry->entry,
                             &qp->rx_free_q);
                qp->rx_alloc_entry++;
        }

However, during teardown, ntb_transport_free() only explicitly frees
allocated QPs:

        /* verify that all the qp's are freed */
        for (i = 0; i < nt->qp_count; i++) {
                qp = &nt->qp_vec[i];
                if (qp_bitmap_alloc & BIT_ULL(i))
                        ntb_transport_free_queue(qp);
        }

By deliberately skipping unallocated QPs during cleanup, won't their
populated rx_free_q lists be completely leaked when the driver executes
kfree(nt->qp_vec)?

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

  reply	other threads:[~2026-09-07 14:50 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-07 14:24 [PATCH 00/11] NTB: ntb_transport: Miscellaneous fixes Koichiro Den
2026-09-07 14:24 ` [PATCH 01/11] NTB: ntb_transport: Remove the device debugfs directory Koichiro Den
2026-09-07 14:36   ` sashiko-bot
2026-09-07 14:24 ` [PATCH 02/11] NTB: ntb_transport: Start TX offload thread after queue setup Koichiro Den
2026-09-07 14:37   ` sashiko-bot
2026-09-07 14:24 ` [PATCH 03/11] NTB: ntb_transport: Prepare remote RX info accesses for MW teardown Koichiro Den
2026-09-07 14:38   ` sashiko-bot
2026-09-07 14:24 ` [PATCH 04/11] NTB: ntb_transport: Clear QP pointers when freeing an MW Koichiro Den
2026-09-07 14:42   ` sashiko-bot
2026-09-09  4:57     ` Koichiro Den
2026-09-07 14:24 ` [PATCH 05/11] NTB: ntb_transport: Avoid deadlock when cancelling link work Koichiro Den
2026-09-07 14:45   ` sashiko-bot
2026-09-07 14:24 ` [PATCH 06/11] NTB: ntb_transport: Publish link state after QP setup Koichiro Den
2026-09-07 14:47   ` sashiko-bot
2026-09-09  4:42     ` Koichiro Den
2026-09-07 14:24 ` [PATCH 07/11] NTB: ntb_transport: Clear link state before QP cleanup Koichiro Den
2026-09-07 14:43   ` sashiko-bot
2026-09-09  4:47     ` Koichiro Den
2026-09-07 14:24 ` [PATCH 08/11] NTB: ntb_transport: Abort link setup on QP MW allocation failure Koichiro Den
2026-09-07 14:45   ` sashiko-bot
2026-09-07 14:24 ` [PATCH 09/11] NTB: ntb_transport: Stop QP work before freeing a queue Koichiro Den
2026-09-07 14:50   ` sashiko-bot [this message]
2026-09-07 14:24 ` [PATCH 10/11] NTB: ntb_transport: Stop RX tasklet scheduling " Koichiro Den
2026-09-07 14:24 ` [PATCH 11/11] NTB: ntb_transport: Drain RX tasklets during link cleanup Koichiro Den
2026-09-07 14:50   ` 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=20260907145054.D177D1F00A3A@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.