On Fri, Apr 4, 2025 at 10:54 AM Ricardo Cañuelo Navarro <rcn@xxxxxxxxxx> wrote: > > sctp_sendmsg() re-uses associations and transports when possible by > doing a lookup based on the socket endpoint and the message destination > address, and then sctp_sendmsg_to_asoc() sets the selected transport in > all the message chunks to be sent. > > There's a possible race condition if another thread triggers the removal > of that selected transport, for instance, by explicitly unbinding an > address with setsockopt(SCTP_SOCKOPT_BINDX_REM), after the chunks have > been set up and before the message is sent. This can happen if the send > buffer is full, during the period when the sender thread temporarily > releases the socket lock in sctp_wait_for_sndbuf(). > > This causes the access to the transport data in > sctp_outq_select_transport(), when the association outqueue is flushed, > to result in a use-after-free read. > > This change avoids this scenario by having sctp_transport_free() signal > the freeing of the transport, tagging it as "dead". In order to do this, > the patch restores the "dead" bit in struct sctp_transport, which was > removed in > commit 47faa1e4c50e ("sctp: remove the dead field of sctp_transport"). > > Then, in the scenario where the sender thread has released the socket > lock in sctp_wait_for_sndbuf(), the bit is checked again after > re-acquiring the socket lock to detect the deletion. This is done while > holding a reference to the transport to prevent it from being freed in > the process. > > If the transport was deleted while the socket lock was relinquished, > sctp_sendmsg_to_asoc() will return -EAGAIN to let userspace retry the > send. > > The bug was found by a private syzbot instance (see the error report [1] > and the C reproducer that triggers it [2]). > > Link: https://people.igalia.com/rcn/kernel_logs/20250402__KASAN_slab-use-after-free_Read_in_sctp_outq_select_transport.txt [1] > Link: https://people.igalia.com/rcn/kernel_logs/20250402__KASAN_slab-use-after-free_Read_in_sctp_outq_select_transport__repro.c [2] > Cc: stable@xxxxxxxxxxxxxxx > Fixes: df132eff4638 ("sctp: clear the transport of some out_chunk_list chunks in sctp_assoc_rm_peer") > Suggested-by: Xin Long <lucien.xin@xxxxxxxxx> > Signed-off-by: Ricardo Cañuelo Navarro <rcn@xxxxxxxxxx> Acked-by: Xin Long <lucien.xin@xxxxxxxxx> Thanks