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