From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f51.google.com (mail-pj1-f51.google.com [209.85.216.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 66CC33B774D for ; Wed, 7 Oct 2026 03:57:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.51 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791345468; cv=none; b=ApaAet3vYYDKcmqMXokb0b57Kuin7OJqeoJ8teyZ3BIbId29GTybGmpJ/vSBxbPHM4RAEzi7BTOq1+eCqdlTAj92lYnDsFeC2KR0nnHMcFaCM8ONRu2UdCjve7ePbHiVsC9HtDNLOJ6Famm9uwUnVBDw6N4575dKnT1BUxv8s6U= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791345468; c=relaxed/simple; bh=yNeF2VfrlVcw4qcdr9g71l1ukl3FUd+CWTZt6ay+YbU=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=CSQ10rN4OtTP+bVMfmyIALxiRQwVDxwxClHFFEl4cJhx3kxTfl+dKvQ6hw9Q+gIVNNC+tV1qWSey9EPlZUoJTE2KtvUt93XjYYFs9g+pWWZKoKuwkm3UX8B6a5jvIpQ3tvvH/dYHUjvoQAD7UAazHRlpQWbqKqY9Orp+3lZhFig= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=bECzfwFO; arc=none smtp.client-ip=209.85.216.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bECzfwFO" Received: by mail-pj1-f51.google.com with SMTP id 98e67ed59e1d1-3a865731ee4so1189176a91.2 for ; Tue, 06 Oct 2026 20:57:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1791345466; x=1791950266; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=3hjMMWqILo+RQ+ZlMN41DDpi4TQ1W3WpbzPCHm6Qne8=; b=bECzfwFOD9YX/RclfM3IOCeMkbrFevDI8Z07dCtIpfGSMs+6k4RKmfIoHCZo2aPe2K kCVaoPMtRkzxOe4G3hIfC3wzvIz2si4T2JUJ957yXDtuH0VBrGrqBWbr2K1Wil1kCZOk QvIgv91bkTXaEguO1E9jWacEvy0DYXcYdwuMeHIufblKBlZuWDMGjgbdL43y3EYClN0j 8KSbsGGrSTDt2dpvjYqKY+PspurDOxDdp53u8S12ZtWq7idfNZGMdXqTs4WHa3FItj+Q V+lGFmilcAbCOpoDtvbCbjAI/CQYeVDqGunAqLAGIUcCp4CrSxe5N0xBmZedpwZxiMf8 Ui/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1791345466; x=1791950266; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=3hjMMWqILo+RQ+ZlMN41DDpi4TQ1W3WpbzPCHm6Qne8=; b=baB07r0vS8m6PgRs3JzsgCVUuCCMqsJJqKXRBj7lQilWnmWIoau4sReqxLBnz9mZs0 IbSaC3lppufEd986BVB9EA4TPNO+vHTa6pMhq75MuouTqJNAkVelWEXUGcyGZok4Xho8 RvcK+nbyLmLf1ZjC1RWRGodJ7JcrYFDB4kKNknbM/GjlcYZ++SO3r+EuiJ+IPWx3qqtM 1RTmdWwYuUY+r4MpLkeEDG4ADT20qQ+hY3Pa+LvfbgRSI8EeW/gCloURneqyX7AqB0W3 XsKouMrTdnL7ZM2pC3V6fzlMBHuuaskq0RCAx5nviYzXJmIqkbFhDea6dlHWssEHMu4X FeaQ== X-Forwarded-Encrypted: i=1; AKwUvBwjJPYOWGU+RmZhEdUCHDdRxrarz0qqXUbBXnz/aYs354Gl1UpEKJfdZOMZ4yChPAASbn5pIsg=@vger.kernel.org X-Gm-Message-State: AFq9FYKf1tsb0EsANH4k1Z2OTTscPx8gwQC+jsqWi3cZjSY5Mhl90TIE QUAbVxamiXrvd5ZRUFfm9vaKqXY4C/pyuV3B1aBe2jsMrQSxFANZs+iY X-Gm-Gg: AYBFou37AWhMYtDEczJn9YlILtgCHeSf+jOB1Sd2kKTC3yj3tuYPMCFbgvYNMqmujDt 2b0EMxd5d5P5rxX29K5JYi3BhjwUYQrDawqfZGFl1LLVsthFjP3Ks00eVdgbGbtZ5S7jpbt49hG /1bnub+XhtOA4nkClwIV2EMJ7n28Roxl00leN4HeOaOOkynUZfTZqy+MOj5sPVGNSLk0zb/emgh oq0/MmxmwO+gtv4HZ19X+mucUUJmVmD5ZkewZJKWNUn/WcO6/UripsCINXb4BTX965pxYAJgmZM QZmyi6Fai1iuiCMTKHcsHa0aUukAufBUYqJs1o2ZsS+KO2BGmAhGjYwfBIRKKptiLNp5zQQYbTQ 1OAVlDRoRnnaQYwUSOk7AwUh5tP1mpy6+3tIILuEYXUZo6E74j6sFmyUyP9ocdZzyX3yDJu9Llt bvYsQnomjjfwYeOm4zJcn8/10j1q4W8BWN2JETRaBaXX1JbF/bryMUSIvLRkXWxhh1mdf9tEjWf PrhC8795IGtB9xChfTmUg== X-Received: by 2002:a17:90b:1344:b0:3a8:7bbc:3f3e with SMTP id 98e67ed59e1d1-3a8a1b0071cmr986825a91.41.1791345465698; Tue, 06 Oct 2026 20:57:45 -0700 (PDT) Received: from ancienth-X870E-Nova-WiFi ([125.186.72.2]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-3a89b625d01sm2397749a91.14.2026.10.06.20.57.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Oct 2026 20:57:45 -0700 (PDT) From: Daehyeon Ko <4ncienth@gmail.com> To: Marcelo Ricardo Leitner , Xin Long Cc: "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , linux-sctp@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Daehyeon Ko <4ncienth@gmail.com>, stable@vger.kernel.org Subject: [PATCH net v2] sctp: revalidate output stream after association connect wait Date: Wed, 7 Oct 2026 12:57:39 +0900 Message-ID: <20261007035739.3472432-1-4ncienth@gmail.com> X-Mailer: git-send-email 2.55.0 Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 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 A range check alone is insufficient. Stream reconfiguration can grow the output count again while the lock is released without recreating extensions freed by the earlier shrink. The stream can then be in range while its extension remains NULL. The send-buffer wait has the same issue. Factor the range and extension checks into a helper and repeat both after each send-path wait that drops the socket lock. Once the lock is reacquired, the validation remains stable through data creation and queueing. If validation fails after the connect wait, the auto-created association is already established. Return ESRCH so the existing caller path keeps it under state-machine ownership instead of freeing it directly, which would leave protocol, counter and socket state inconsistent. 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> --- Changes in v2: - Repeat full stream validation after both send-path waits. - Recreate a missing stream extension after shrink followed by growth. - Return ESRCH after the connect wait to retain the live association. v1: https://lore.kernel.org/r/20261002010449.3689454-1-4ncienth@gmail.com net/sctp/socket.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 4652fd90d9a6c4..aaeb58ce055771 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1786,6 +1786,18 @@ static int sctp_sendmsg_check_sflags(struct sctp_association *asoc, return 1; } +static int sctp_sendmsg_check_stream(struct sctp_association *asoc, + struct sctp_sndrcvinfo *sinfo) +{ + if (unlikely(sinfo->sinfo_stream >= asoc->stream.outcnt)) + return -EINVAL; + + if (unlikely(!SCTP_SO(&asoc->stream, sinfo->sinfo_stream)->ext)) + return sctp_stream_init_ext(&asoc->stream, sinfo->sinfo_stream); + + return 0; +} + static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, struct msghdr *msg, size_t msg_len, struct sctp_transport *transport, @@ -1800,16 +1812,9 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, long timeo; int err; - if (sinfo->sinfo_stream >= asoc->stream.outcnt) { - err = -EINVAL; + err = sctp_sendmsg_check_stream(asoc, sinfo); + if (err) goto err; - } - - if (unlikely(!SCTP_SO(&asoc->stream, sinfo->sinfo_stream)->ext)) { - err = sctp_stream_init_ext(&asoc->stream, sinfo->sinfo_stream); - if (err) - goto err; - } if (sp->disable_fragments && msg_len > asoc->frag_point) { err = -EMSGSIZE; @@ -1830,10 +1835,9 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, err = sctp_wait_for_sndbuf(asoc, transport, &timeo, msg_len); if (err) goto err; - if (unlikely(sinfo->sinfo_stream >= asoc->stream.outcnt)) { - err = -EINVAL; + err = sctp_sendmsg_check_stream(asoc, sinfo); + if (err) goto err; - } } if (sctp_state(asoc, CLOSED)) { @@ -1848,6 +1852,11 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, err = -ESRCH; goto err; } + err = sctp_sendmsg_check_stream(asoc, sinfo); + if (err) { + err = -ESRCH; + goto err; + } } else { wait_connect = true; } -- 2.55.0