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 07/11] NTB: ntb_transport: Clear link state before QP cleanup
Date: Mon, 07 Sep 2026 14:43:02 +0000	[thread overview]
Message-ID: <20260907144303.3D25A1F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260907142429.951930-8-den@valinux.co.jp>

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

New issues:
- [Medium] Coding Pattern Violation: Mixing guard() and goto-based cleanup

Pre-existing issues:
- [High] Memory Ordering Race leading to lost wakeups
- [High] Data Race in ntb_qp_link_cleanup allowing concurrent execution
- [High] DMA Memory Corruption due to unterminated transactions
- [High] Missing read memory barrier (dma_rmb) when reading payload after checking DESC_DONE_FLAG
- [High] Stale Data Transmission due to missing flush on link down
--

commit 3aa5fe6a4883f5e1056224f4eb903786b4edfe5a
Author: Koichiro Den <den@valinux.co.jp>

    NTB: ntb_transport: Clear link state before QP cleanup

    Cleanup leaves the transport link marked up after releasing its MWs, allowing
    client link-up requests to start QP link work prematurely. Clear link_is_up
    before cancelling QP work and releasing MWs. Additionally, ensure QP link
    work returns if the transport went down after it was queued.

> diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
> index 411017873a83b..4c0a29693ac23 100644
> --- a/drivers/ntb/ntb_transport.c
> +++ b/drivers/ntb/ntb_transport.c
> @@ -990,6 +990,8 @@ static void ntb_transport_link_cleanup(struct ntb_transport_ctx *nt)
>  
>  	guard(mutex)(&nt->link_event_lock);
>  
> +	WRITE_ONCE(nt->link_is_up, false);
> +
>  	qp_bitmap_alloc = nt->qp_bitmap & ~nt->qp_bitmap_free;
>  
>  	/* Pass along the info to any clients */

[Severity: High]
This is a pre-existing issue, but does this cleanup routine allow concurrent
execution?

Looking at ntb_transport_link_cleanup(), it calls ntb_qp_link_cleanup() on all
active QPs, and then synchronizes cancellation using cancel_work_sync():

drivers/ntb/ntb_transport.c:ntb_transport_link_cleanup() {
    ...
    for (i = 0; i < nt->qp_count; i++)
        if (nt->qp_bitmap_alloc & BIT_ULL(i)) {
            struct ntb_transport_qp *qp = &nt->qp_vec[i];
            ntb_qp_link_cleanup(qp);
            cancel_work_sync(&qp->link_cleanup);
        }
    ...
}

If the ntb_qp_link_cleanup_work() worker is concurrently executing, it will
also invoke ntb_qp_link_cleanup(). Since no lock synchronizes
ntb_qp_link_cleanup(), it can execute concurrently across threads. This could
lead to data races when resetting QP indices and cause duplicate concurrent
calls to the client's event_handler, potentially corrupting the client driver
state.

[Severity: High]
This is a pre-existing issue, but is it possible for active DMA transactions to
corrupt freed memory here?

Later in ntb_transport_link_cleanup(), it frees the backing DMA memory:

drivers/ntb/ntb_transport.c:ntb_transport_link_cleanup() {
    ...
    for (i = 0; i < nt->mw_count; i++)
        ntb_free_mw(nt, i);
    ...
}

ntb_free_mw() calls dma_free_attrs() without ensuring the DMA channel is
stopped. Prior to this, ntb_qp_link_cleanup() kills the RX tasklet with
tasklet_kill(&qp->rxc_db_work), but does not terminate active DMA engine
transactions (e.g., via dmaengine_terminate_all()).

If a DMA transfer was previously submitted, could it continue asynchronously in
hardware, writing into the freed memory pages and leading to IOMMU faults or
memory corruption?

[Severity: High]
This is a pre-existing issue, but does resetting the link context leave stale
data in the transmit queues?

When the link goes down, ntb_qp_link_down_reset() is called:

drivers/ntb/ntb_transport.c:ntb_qp_link_down_reset() {
    ...
    ntb_qp_link_context_reset(qp);
    remote_rx_info = READ_ONCE(qp->remote_rx_info);
    ...
}

The QP context and indices (like qp->tx_index) are reset to 0, but pending
entries in qp->tx_offl_q or other transmit queues are not flushed. These
pending entries already have their entry->tx_index populated with old index
values from before the link dropped.

When the tx_offload_thread processes them, could it write the data to the
old, stale index locations instead of starting correctly at index 0, causing
the remote receiver to hang or receive out-of-sequence packets?

[ ... ]

[Severity: Medium]
Does ntb_transport_link_work() mix scope-based guard macros with legacy
goto-based error cleanup?

The cleanup.md documentation explicitly mandates that usage of "goto" and
cleanup helpers must never be mixed in the same function.

drivers/ntb/ntb_transport.c:ntb_transport_link_work() {
    ...
    guard(mutex)(&nt->link_event_lock);
    ...
        rc = ntb_set_mw(nt, i, val64);
        if (rc)
            goto out1;
    ...
out1:
    for (i = 0; i < nt->mw_count; i++)
        ntb_free_mw(nt, i);
    ...
}

This function uses guard(mutex)(&nt->link_event_lock) at the beginning, but
continues to use goto out1; and goto out; for error handling and legacy cleanup
paths. Does this violate the established architectural cleanup pattern?

[ ... ]

> @@ -1149,7 +1151,9 @@ static void ntb_qp_link_work(struct work_struct *work)
>  	struct ntb_transport_ctx *nt = qp->transport;
>  	int val;
>  
> -	WARN_ON(!nt->link_is_up);
> +	/* Pair with the link publication in ntb_transport_link_work(). */
> +	if (!smp_load_acquire(&nt->link_is_up))
> +		return;
>  
>  	val = ntb_spad_read(nt->ndev, QP_LINKS);
>  

[Severity: High]
This is a pre-existing issue, but does this Dekker's algorithm pattern lack a
full memory barrier, potentially leading to lost wakeups?

In ntb_transport_link_work(), nt->link_is_up is stored and qp->client_ready is
read:

drivers/ntb/ntb_transport.c:ntb_transport_link_work() {
    ...
    smp_store_release(&nt->link_is_up, true);

    for (i = 0; i < nt->qp_count; i++) {
        struct ntb_transport_qp *qp = &nt->qp_vec[i];

        if (qp->client_ready)
            ntb_transport_schedule_qp_link(qp, 0);
    }
    ...
}

Concurrently, ntb_transport_link_up() stores qp->client_ready and reads
nt->link_is_up:

drivers/ntb/ntb_transport.c:ntb_transport_link_up() {
    ...
    qp->client_ready = true;
    ntb_transport_schedule_qp_link(qp, 0);
    ...
}

Inside ntb_transport_schedule_qp_link(), it checks
smp_load_acquire(&nt->link_is_up). Because smp_store_release() allows
subsequent loads to be reordered before the store, and smp_load_acquire()
allows preceding stores to be reordered after the load, both threads can read
false for the counterpart flag.

Could this result in a lost wakeup where the QP link fails to initialize?

[ ... ]

[Severity: High]
This is a pre-existing issue, but is a read memory barrier required after
checking the DESC_DONE_FLAG?

In ntb_process_rxc(), the descriptor's done flag is read from the DMA-mapped
memory to verify packet completion:

drivers/ntb/ntb_transport.c:ntb_process_rxc() {
    ...
    if (!(hdr->flags & DESC_DONE_FLAG)) {
        dev_dbg(&qp->ndev->pdev->dev, "done flag not set\n");
        qp->rx_ring_empty++;
        return -EAGAIN;
    }
    ...
}

However, there is no dma_rmb() issued after observing the flag. Could this
allow the CPU to speculatively read the subsequent header fields (e.g.,
hdr->ver, hdr->len) and the payload buffer before the done flag read
completes, resulting in stale data being processed?

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

  reply	other threads:[~2026-09-07 14:43 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 [this message]
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
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=20260907144303.3D25A1F00A3A@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.