Re: [PATCH net v2] sctp: drop a chunk if its transport was removed

Xin Long <[email protected]>
Newsgroups org.kernel.vger.linux-sctp,org.kernel.vger.netdev
Message-ID <CADvbK_cG6yTabSSEXCmEJ0MrqFG3ESHAtctupGUdRQwmeUYihQ@mail.gmail.com>
On Tue, Aug 18, 2026 at 9:38 PM Hyunwoo Kim <[email protected]> wrote:
>
> sctp_rcv() resolves the transport once per packet and leaves it in
> chunk->transport. The lookup reference, or the one sctp_add_backlog() takes
> if the socket is owned by userspace, keeps it around until the chunk has
> been processed.
>
> An authenticated ASCONF DEL-IP can remove it in the meantime.
> sctp_assoc_rm_peer() takes the transport out of the association and calls
> sctp_transport_free(), which tags it dead and drops the reference the
> association held. There is a window on both paths: the packet can sit on
> the socket backlog, and on the direct path the lookup completes before
> bh_lock_sock().
>
> The DATA chunk in that packet puts the removed transport back into
> asoc->peer.last_data_from. Once the packet is done that reference goes
> away and the transport is freed by RCU, so the next delayed SACK carries
> the pointer into the SACK chunk and sctp_outq_select_transport() reads the
> freed transport's state.
>
> Drop the chunk in sctp_inq_push(), next to the existing rcvr->dead check.
> Both paths reach it with the association's socket lock held. The peer
> retransmits it.
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Cc: [email protected]
> Signed-off-by: Hyunwoo Kim <[email protected]>
> ---
> Changes in v2:
> - Move the check from sctp_backlog_rcv() into sctp_inq_push(), so that the
> direct softirq path and the socket migration branch are covered as well.
> - Correct the Fixes tag.
> - v1: https://lore.kernel.org/all/an-oGfEatacPTSX-@v4bel/
> ---
>  net/sctp/inqueue.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
> index a024c08432471d..5f988b3a8814ff 100644
> --- a/net/sctp/inqueue.c
> +++ b/net/sctp/inqueue.c
> @@ -71,8 +71,11 @@ void sctp_inq_free(struct sctp_inq *queue)
>   */
>  void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk)
>  {
> -       /* Directly call the packet handling routine. */
> -       if (chunk->rcvr->dead) {
> +       /* Directly call the packet handling routine.  Drop the chunk if the
> +        * receiver or the transport it was looked up on is gone.
> +        */
> +       if (chunk->rcvr->dead ||
> +           (chunk->transport && chunk->transport->dead)) {
>                 sctp_chunk_free(chunk);
>                 return;
>         }
> --
> 2.43.0
>

Acked-by: Xin Long <[email protected]>

Note, this patch fixes the case when the transport is freed before the
chunks get processed. But the pre-existing issue reported in Sashiko-claude
[1] is the case when the transport is freed while the chunks are being
processed, which is very rare, the fix would be to set chunk->transport to
NULL instead. We need to confirm and address it separately.

[1] https://netdev-ai.bots.linux.dev/sashiko/#/patchset/aoUJHQmxL0LFIMCw%40v4bel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.