sctp_assoc_rm_peer() clears the cached chunk->transport back-pointer on only two of the output queue's chunk lists before freeing the transport: peer->transmitted and asoc->outqueue.out_chunk_list. A DATA chunk parked on asoc->outqueue.retransmit keeps pointing at the transport, so once sctp_transport_free() drops the last reference and the object is RCU-freed, that chunk is left with a dangling pointer. While the chunk sits on the retransmit queue the dangling pointer is not followed: sctp_check_transmitted() skips the flight-size accounting both for transmitted_queue == &q->retransmit and for gap-acked chunks. Two steps remove that cover. First, sctp_outq_flush_rtx() moves a gap-acked chunk onto a live transport's transmitted list without reassigning chunk->transport, unlike the ordinary resend path, which rebinds it in __sctp_packet_append_chunk(). Second, a later SACK that reneges on the TSN clears tsn_gap_acked. The chunk now sits on a transmitted list with tsn_gap_acked == 0, so the next SACK reaches tchunk->transport->flight_size -= sctp_data_size(tchunk); a read-modify-write inside the freed sctp_transport. The transport is freed by an ASCONF Delete-IP and the faulting accesses are driven by ordinary SACKs, both coming from the association peer, so an application that speaks SCTP and accepts multihoming is enough to reach this. KASAN reports a slab-use-after-free read of 4 bytes at offset 216 of a freed kmalloc-1k sctp_transport in sctp_check_transmitted(), the object having been freed from sctp_assoc_rm_peer() via sctp_process_asconf(). Clear ->transport for chunks on the retransmit queue as well, mirroring the existing out_chunk_list handling. The sink already guards with if (tchunk->transport), so a cleared back-pointer is skipped exactly like an already-acked chunk. The sacked and abandoned queues do not need the same treatment: chunks there never have ->transport dereferenced and are never migrated onto the retransmit queue or onto a transport's transmitted list. Discovered by XBOW, triaged by Baul Lee Reported privately to the maintainers on 2026-07-10 with root-cause analysis, a PoC, a KASAN log and this fix; posting to the list was requested as the follow-up. Fixes: df132eff4638 ("sctp: clear the transport of some out_chunk_list chunks in sctp_assoc_rm_peer") Reported-by: Federico Kirschbaum Reported-by: Baul Lee Cc: stable@vger.kernel.org Signed-off-by: Baul Lee --- net/sctp/associola.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 62d3cc155809..c95f68d21670 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -569,6 +569,10 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, sctp_transport_hold(active); } + list_for_each_entry(ch, &asoc->outqueue.retransmit, transmitted_list) + if (ch->transport == peer) + ch->transport = NULL; + list_for_each_entry(ch, &asoc->outqueue.out_chunk_list, list) if (ch->transport == peer) ch->transport = NULL; -- 2.50.1 (Apple Git-155)