Re: [PATCH net] sctp: clear new_transport when removing a peer
Xin Long <[email protected]>
| Newsgroups | org.kernel.vger.linux-sctp,org.kernel.vger.linux-kernel,org.kernel.vger.netdev,org.kernel.vger.stable |
|---|---|
| Message-ID | <CADvbK_d8r56n6FHFEeyz0cpmdoFJ5HXJ4m0XipQqYXTiL-YLjw@mail.gmail.com> |
On Tue, Aug 11, 2026 at 11:28 AM Qing Ming <[email protected]> wrote: > > sctp_process_asconf_param() stores a newly added peer transport in > asoc->new_transport. After all parameters in the ASCONF chunk have been > processed, sctp_sf_do_asconf() uses this pointer to send a HEARTBEAT to the > new transport. > > An authenticated ASCONF from a remote SCTP peer can add a transport and > remove it again with a wildcard DEL-IP parameter in the same chunk. The > wildcard deletion preserves the transport on which the ASCONF arrived, but > removes the newly added transport through > sctp_assoc_del_nonprimary_peers(). The removal does not clear > asoc->new_transport, leaving it pointing to the removed transport. > > sctp_sf_do_asconf() then creates a HEARTBEAT whose chunk->transport points > to the removed transport without holding a transport reference. During > local address replacement, src_out_of_asoc_ok keeps this HEARTBEAT on > control_chunk_list. After the transport is freed by RCU, a successful > ASCONF_ACK for the replacement address releases the queued HEARTBEAT and > sctp_outq_select_transport() reads the freed transport's state. > > The issue was found during a static audit of SCTP objects. With an > authenticated peer, the reproducer triggered the same KASAN report in 2 > of 2 unpatched runs on a KASAN-enabled netdev/main kernel: > > BUG: KASAN: slab-use-after-free in sctp_outq_select_transport > Read of size 4 at addr ffff88800b9bd95c by task python3/197 > > Call Trace: > sctp_outq_select_transport+0x549/0x8b0 [sctp] > sctp_outq_flush+0x306/0x2c60 [sctp] > sctp_transport_immediate_rtx+0xaf/0x260 [sctp] > sctp_process_asconf_ack+0xa48/0xf70 [sctp] > > Allocated by task 197: > sctp_transport_new+0x68/0x650 [sctp] > sctp_assoc_add_peer+0x258/0x12a0 [sctp] > sctp_process_asconf+0x5e9/0x1090 [sctp] > > Last potentially related work creation: > __call_rcu_common.constprop.0+0x77/0xb70 > sctp_assoc_del_nonprimary_peers+0x7c/0xd0 [sctp] > sctp_process_asconf+0xd9c/0x1090 [sctp] > > The first invalid access was a four-byte read of transport->state at > net/sctp/outqueue.c:833. The same reproducer completed the full > authenticated ASCONF and local-address replacement sequence with this > change without a KASAN report or oops. > Could you also post the reproducer, at least to the maintainers? Thanks. > Clear new_transport when its peer is removed, before it can be used to > create the HEARTBEAT. > > Fixes: 6af29ccc223b ("sctp: Bundle HEAERTBEAT into ASCONF_ACK") > Cc: [email protected] > Assisted-by: Codex:gpt-5 > Signed-off-by: Qing Ming <[email protected]> > --- > net/sctp/associola.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/net/sctp/associola.c b/net/sctp/associola.c > index 5b0ae616e1ff..c65c83638cce 100644 > --- a/net/sctp/associola.c > +++ b/net/sctp/associola.c > @@ -543,6 +543,9 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, > asoc->addip_last_asconf->transport == peer) > asoc->addip_last_asconf->transport = NULL; > > + if (asoc->new_transport == peer) > + asoc->new_transport = NULL; > + > /* If we have something on the transmitted list, we have to > * save it off. The best place is the active path. > */ > > base-commit: cba9ccb47e9fa4cc77692fb896cc5ab57a667882 > -- > 2.53.0 >