Re: [PATCH] sctp: detect and prevent references to a freed transport in sendmsg
From: Xin Long
Date: Mon Apr 07 2025 - 11:14:02 EST
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