* [PATCH net] sctp: fix transport UAF via the retransmit queue
@ 2026-07-26 6:04 Baul Lee
0 siblings, 0 replies; only message in thread
From: Baul Lee @ 2026-07-26 6:04 UTC (permalink / raw)
To: netdev, linux-sctp, linux-kernel
Cc: marcelo.leitner, lucien.xin, davem, edumazet, kuba, pabeni, horms,
federico.kirschbaum, Baul Lee, stable
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 <baul.lee@xbow.com>
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 <federico.kirschbaum@xbow.com>
Reported-by: Baul Lee <baul.lee@xbow.com>
Cc: stable@vger.kernel.org
Signed-off-by: Baul Lee <baul.lee@xbow.com>
---
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)
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-07-26 6:05 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-26 6:04 [PATCH net] sctp: fix transport UAF via the retransmit queue Baul Lee
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox