From: Jun Yang <juny24602@gmail.com>
To: netdev@vger.kernel.org
Cc: Jun Yang <junvyyang@tencent.com>,
stable@kernel.org, TencentOS Corvus AI <corvus@tencent.com>,
Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>,
Xin Long <lucien.xin@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>,
linux-sctp@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH net] sctp: re-point retained control chunks on association migration
Date: Thu, 30 Jul 2026 17:05:25 +0800 [thread overview]
Message-ID: <20260730090537.27629-1-juny24602@gmail.com> (raw)
From: Jun Yang <junvyyang@tencent.com>
sctp_control_set_owner_w() records the owning socket in a control chunk's
skb->sk as a bare pointer. sctp_sock_migrate() re-owns the association's
DATA chunks via sctp_for_each_tx_datachunk(), but that walk keys off
chunk->msg and so skips control chunks: any control chunk the association
still holds (for example the saved stream-reset request
asoc->strreset_chunk, the ASCONF request/ack lists, or
asoc->addip_last_asconf) keeps pointing at the old socket after the
association is moved to the new one.
Once the old socket is freed, a later retransmit reaches
sctp_packet_transmit() -> skb_set_owner_w(head, chunk->skb->sk) and
operates on the freed socket -- refcount_add() on its sk_wmem_alloc,
then sk->sk_write_space() from sock_wfree() -- a use-after-free of
struct sock.
Re-point every control chunk the association still holds at the new
socket right after sctp_assoc_migrate(), as is already done for DATA
chunks. Control chunks carry no socket wmem charge and their skb
destructor does not use skb->sk, so a bare owner update is sufficient.
Fixes: d04adf1b3551 ("sctp: reset owner sk for data chunks on out queues when migrating a sock")
Cc: stable@kernel.org
Reported-by: TencentOS Corvus AI <corvus@tencent.com>
Signed-off-by: Jun Yang <junvyyang@tencent.com>
---
net/sctp/socket.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index c7b9e325ec1c..9a6da4e0d741 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -9522,6 +9522,30 @@ static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk)
sctp_skb_set_owner_r(skb, sk);
}
+/* Control chunks record their owning socket in skb->sk as a bare pointer and
+ * are not reached by sctp_for_each_tx_datachunk(); re-point the ones the
+ * association still holds so migration does not leave them on the old socket.
+ */
+static void sctp_ctrl_set_owner_w(struct sctp_chunk *chunk, struct sock *sk)
+{
+ if (chunk && chunk->skb)
+ chunk->skb->sk = sk;
+}
+
+static void sctp_for_each_tx_ctrlchunk(struct sctp_association *assoc, struct sock *sk)
+{
+ struct sctp_chunk *chunk;
+
+ list_for_each_entry(chunk, &assoc->outqueue.control_chunk_list, list)
+ sctp_ctrl_set_owner_w(chunk, sk);
+ list_for_each_entry(chunk, &assoc->asconf_ack_list, transmitted_list)
+ sctp_ctrl_set_owner_w(chunk, sk);
+ list_for_each_entry(chunk, &assoc->addip_chunk_list, list)
+ sctp_ctrl_set_owner_w(chunk, sk);
+ sctp_ctrl_set_owner_w(assoc->strreset_chunk, sk);
+ sctp_ctrl_set_owner_w(assoc->addip_last_asconf, sk);
+}
+
/* Populate the fields of the newsk from the oldsk and migrate the assoc
* and its messages to the newsk.
*/
@@ -9633,6 +9657,7 @@ static int sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
sctp_for_each_tx_datachunk(assoc, true, sctp_clear_owner_w);
sctp_assoc_migrate(assoc, newsk);
sctp_for_each_tx_datachunk(assoc, false, sctp_set_owner_w);
+ sctp_for_each_tx_ctrlchunk(assoc, newsk);
/* If the association on the newsk is already closed before accept()
* is called, set RCV_SHUTDOWN flag.
--
2.55.0
reply other threads:[~2026-07-30 9:05 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260730090537.27629-1-juny24602@gmail.com \
--to=juny24602@gmail.com \
--cc=corvus@tencent.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=junvyyang@tencent.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sctp@vger.kernel.org \
--cc=lucien.xin@gmail.com \
--cc=marcelo.leitner@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=stable@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.