When message interleaving is enabled, the first send waits for association establishment before building its data chunks. The wait drops the socket lock, and handshake processing can reduce the output stream count to the peer-advertised inbound stream count. sctp_stream_init() then frees the extension of every removed stream. The sender currently resumes with the stream that it checked before the wait. If the peer removed that stream, sctp_outq_tail() later dereferences its NULL extension. Fatal-oops policies then panic the host. KASAN: null-ptr-deref in range [0x38-0x3f] RIP: sctp_outq_tail+0x49e/0xaa0 Call Trace: sctp_primitive_SEND sctp_sendmsg_to_asoc sctp_sendmsg Revalidate the output stream after the association connect wait. Return EINVAL if it falls outside the negotiated range. This matches the pre-wait check. Fixes: 668c9beb9020 ("sctp: implement assign_number for sctp_stream_interleave") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Daehyeon Ko <4ncienth@gmail.com> --- net/sctp/socket.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 4652fd90d9a6c..394d31cb698e0 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1848,6 +1848,11 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, err = -ESRCH; goto err; } + if (unlikely(sinfo->sinfo_stream >= + asoc->stream.outcnt)) { + err = -EINVAL; + goto err; + } } else { wait_connect = true; }