From: Jun Yang <redacted>
sctp_wait_for_connect() drops the socket lock while it sleeps. An
out-of-the-blue ABORT can then be processed from the socket backlog and
unlink the association. If a concurrent shutdown(fd, SHUT_RD) sets
RCV_SHUTDOWN, the waiter breaks with err == 0 before checking
asoc->base.dead. Its final sctp_association_put() can then free the
association, leaving sctp_sendmsg_to_asoc() to continue with a dangling
pointer.
Check RCV_SHUTDOWN along with the wait error in sctp_sendmsg_to_asoc()
before using the association again. The check only accesses the socket,
so it needs no additional association reference. Return the existing
-ESRCH so that sctp_sendmsg() skips freeing a new association that may
already have been destroyed.
Keep sctp_wait_for_connect() unchanged to preserve its behavior for the
connect() caller.
Fixes: 668c9beb9020 ("sctp: implement assign_number for sctp_stream_interleave")
Cc: stable@vger.kernel.org
Reported-by: TencentOS Corvus AI <redacted>
Assisted-by: tencentos-corvus-ai:hy4-preview
Signed-off-by: Jun Yang <redacted>
---
v3:
- Check RCV_SHUTDOWN after the sendmsg connect wait, as suggested by
Xin Long, instead of taking an extra association reference and checking
asoc->base.dead.
- Keep the shared wait helper unchanged and retain the -ESRCH error path.
- Link to v2: https://lore.kernel.org/all/20260911090039.75646-1-juny24602@gmail.com/ (local)
- Review: https://lore.kernel.org/all/CADvbK_f=S-2waid_92PbOCh-LWjU5oiZT+__xWfttVeTHEPQTg@mail.gmail.com/ (local)
v2:
- Leave sctp_wait_for_connect() unchanged to preserve connect() semantics.
- Hold and validate the association in the sendmsg-only caller.
net/sctp/socket.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index c7b9e325ec1c..4652fd90d9a6 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1844,7 +1844,7 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc,
if (asoc->ep->intl_enable) {
timeo = sock_sndtimeo(sk, 0);
err = sctp_wait_for_connect(asoc, &timeo);
- if (err) {
+ if (err || sk->sk_shutdown & RCV_SHUTDOWN) {
err = -ESRCH;
goto err;
}--
2.54.0 (Apple Git-157)