Re: [PATCH] NTB: ntb_transport: Mark the transport link down on cleanup

[email protected] Fri, 17 Jul 2026 06:30:27 +0000
Newsgroups dev.linux.lists.ntb
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 6 potential issue(=
s) to consider:

New issues:
- [High] Calling cancel_delayed_work_sync(&nt->link_work) while holding the=
 nt->link_event_lock mutex causes an AB-BA deadlock.
- [Medium] Leaving nt->link_work pending when transitioning nt->link_is_up =
to false allows a race condition that incorrectly re-establishes the link.

Pre-existing issues:
- [Critical] qp->rx_buff is accessed by the rxc_db_work tasklet after the u=
nderlying memory window is freed.
- [High] Race condition in ntb_transport_free() allows concurrent double fr=
ee of DMA memory windows.
- [High] Incorrect teardown ordering in ntb_transport_free() allows backgro=
und works to be rescheduled after cancellation.
- [High] Silent packet drops in ntb_transport_tx_enqueue() return a false s=
uccess, leaking client buffers like sk_buff.
--

--- Patch [1]: [PATCH] NTB: ntb_transport: Mark the transport link down on =
cleanup ---
commit bd7368d1b1384a2ec346e8cb7ab08bf47c5b276c
Author: Koichiro Den <[email protected]>
Subject: NTB: ntb_transport: Mark the transport link down on cleanup

This commit restores a missing state transition in the NTB transport driver.
It ensures the transport link state is marked as down during link cleanup,
preventing queue pair cleanup workers from retrying handshakes against a
down peer.

> diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
> index f59f926d4bfaa..5b9fccd1383dd 100644
> --- a/drivers/ntb/ntb_transport.c
> +++ b/drivers/ntb/ntb_transport.c
> @@ -974,6 +974,8 @@ static void ntb_transport_link_cleanup(struct ntb_tra=
nsport_ctx *nt)
> =20
>  	if (!nt->link_is_up)
>  		cancel_delayed_work_sync(&nt->link_work);

[Severity: High]
Can this synchronous cancellation cause a deadlock with the link work?

If ntb_transport_link_cleanup() is called from
ntb_transport_link_cleanup_work() which holds nt->link_event_lock:

ntb_transport_link_cleanup_work() {
    guard(mutex)(&nt->link_event_lock);
    ntb_transport_link_cleanup(nt);
}

And ntb_transport_link_work() attempts to acquire the same mutex as its
first operation:

ntb_transport_link_work() {
    guard(mutex)(&nt->link_event_lock);
}

Could this block indefinitely waiting for the mutex while the cleanup worker
waits for the work to finish? By resetting nt->link_is_up to false in the
new branch below, subsequent cleanups seem guaranteed to hit this path.

> +	else
> +		nt->link_is_up =3D false;

[Severity: Medium]
When setting the link down here, should we also cancel the delayed work?

If nt->link_work is already pending in the workqueue, could it execute after
this cleanup completes? If the remote peer hasn't processed its own link
down event yet, the work might read valid SPAD values and mistakenly set
nt->link_is_up back to true.

> =20
>  	for (i =3D 0; i < nt->mw_count; i++)
>  		ntb_free_mw(nt, i);

[Severity: Critical]
This isn't a bug introduced by this patch, but is it safe to free the memory
windows while the rxc_db_work tasklet might still be running?

If a doorbell interrupt fires asynchronously, the tasklet executes
ntb_process_rxc() and accesses qp->rx_buff (a pointer into the freed memory
window) before the qp->active flag is checked.

Does this need to synchronize with or disable the tasklet before calling
ntb_free_mw()?


[Severity: High]
This is a pre-existing issue, but is there a race condition protecting these
memory windows during module removal?

ntb_transport_free() calls ntb_transport_link_cleanup() directly without
holding the nt->link_event_lock mutex. If a link event concurrently schedul=
es
ntb_transport_link_cleanup_work() (which does take the lock), could both
paths simultaneously enter ntb_free_mw() and trigger a double free when
calling dma_free_attrs()?


[Severity: High]
This is also a pre-existing issue, but does ntb_transport_free() cancel
background works in the correct order?

It calls cancel_delayed_work_sync() for the link works before calling
ntb_link_disable(ndev). If a hardware link interrupt fires in the interim,
ntb_transport_event_callback() will requeue the work items.

After the context is freed, could the newly queued works execute and access
freed memory?


[Severity: High]
This isn't a bug introduced by this patch, but does
ntb_transport_tx_enqueue() silently drop packets and leak client buffers?

When qp->link_is_up is false, it returns 0 (success) immediately:

ntb_transport_tx_enqueue() {
    if (!qp->link_is_up)
        return 0;
}

Callers like ntb_netdev_start_xmit() expect a non-zero return code on
failure. Since 0 is returned, the caller assumes the transport layer took
ownership of the buffer.

Because the packet is dropped and no callback will be fired, does this leak
the buffer?

--=20
Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260717061223.2203=
[email protected]?part=3D1