summaryrefslogtreecommitdiff
path: root/net/sctp/socket.c
diff options
context:
space:
mode:
authorKuniyuki Iwashima <kuniyu@google.com>2025-10-23 23:16:56 +0000
committerJakub Kicinski <kuba@kernel.org>2025-10-27 18:04:58 -0700
commitb7ddb55f31279f4e59acde3395fc03c3d94b6e5f (patch)
tree0903a91bda50ebc01a3709a9a70d511100974f04 /net/sctp/socket.c
parentc49ed521f1772ca9203d22a1e5950f337fd5f930 (diff)
sctp: Use sctp_clone_sock() in sctp_do_peeloff().
sctp_do_peeloff() calls sock_create() to allocate and initialise struct sock, inet_sock, and sctp_sock, but later sctp_copy_sock() and sctp_sock_migrate() overwrite most fields. What sctp_do_peeloff() does is more like accept(). Let's use sock_create_lite() and sctp_clone_sock(). Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Acked-by: Xin Long <lucien.xin@gmail.com> Link: https://patch.msgid.link/20251023231751.4168390-8-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r--net/sctp/socket.c36
1 files changed, 15 insertions, 21 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 826f17747f17..60d3e340dfed 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -5671,11 +5671,11 @@ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char __user *optv
/* Helper routine to branch off an association to a new socket. */
static int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id,
- struct socket **sockp)
+ struct socket **sockp)
{
struct sctp_association *asoc = sctp_id2assoc(sk, id);
- struct sctp_sock *sp = sctp_sk(sk);
struct socket *sock;
+ struct sock *newsk;
int err = 0;
/* Do not peel off from one netns to another one. */
@@ -5691,30 +5691,24 @@ static int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id,
if (!sctp_style(sk, UDP))
return -EINVAL;
- /* Create a new socket. */
- err = sock_create(sk->sk_family, SOCK_SEQPACKET, IPPROTO_SCTP, &sock);
- if (err < 0)
+ err = sock_create_lite(sk->sk_family, SOCK_SEQPACKET, IPPROTO_SCTP, &sock);
+ if (err)
return err;
- sctp_copy_sock(sock->sk, sk, asoc);
-
- /* Make peeled-off sockets more like 1-1 accepted sockets.
- * Set the daddr and initialize id to something more random and also
- * copy over any ip options.
- */
- sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sock->sk);
- sp->pf->copy_ip_options(sk, sock->sk);
-
- /* Populate the fields of the newsk from the oldsk and migrate the
- * asoc to the newsk.
- */
- err = sctp_sock_migrate(sk, sock->sk, asoc,
- SCTP_SOCKET_UDP_HIGH_BANDWIDTH);
- if (err) {
+ newsk = sctp_clone_sock(sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH);
+ if (IS_ERR(newsk)) {
sock_release(sock);
- sock = NULL;
+ *sockp = NULL;
+ return PTR_ERR(newsk);
}
+ lock_sock_nested(newsk, SINGLE_DEPTH_NESTING);
+ __inet_accept(sk->sk_socket, sock, newsk);
+ release_sock(newsk);
+
+ sock->ops = sk->sk_socket->ops;
+ __module_get(sock->ops->owner);
+
*sockp = sock;
return err;