Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

sctp: Use sk_clone() in sctp_accept().

sctp_accept() calls sctp_v[46]_create_accept_sk() to allocate a new
socket and calls sctp_sock_migrate() to copy fields from the parent
socket to the new socket.

sctp_v4_create_accept_sk() allocates sk by sk_alloc(), initialises
it by sock_init_data(), and copy a bunch of fields from the parent
socekt by sctp_copy_sock().

sctp_sock_migrate() calls sctp_copy_descendant() to copy most fields
in sctp_sock from the parent socket by memcpy().

These can be simply replaced by sk_clone().

Let's consolidate sctp_v[46]_create_accept_sk() to sctp_clone_sock()
with sk_clone().

We will reuse sctp_clone_sock() for sctp_do_peeloff() and then remove
sctp_copy_descendant().

Note that sock_reset_flag(newsk, SOCK_ZAPPED) is not copied to
sctp_clone_sock() as sctp does not use SOCK_ZAPPED at all.

Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Acked-by: Xin Long <lucien.xin@gmail.com>
Link: https://patch.msgid.link/20251023231751.4168390-6-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Kuniyuki Iwashima and committed by
Jakub Kicinski
16942cf4 151b98d1

+77 -40
+1 -3
net/ipv4/af_inet.c
··· 755 755 756 756 void __inet_accept(struct socket *sock, struct socket *newsock, struct sock *newsk) 757 757 { 758 - /* TODO: use sk_clone_lock() in SCTP and remove protocol checks */ 759 - if (mem_cgroup_sockets_enabled && 760 - (!IS_ENABLED(CONFIG_IP_SCTP) || sk_is_tcp(newsk))) { 758 + if (mem_cgroup_sockets_enabled) { 761 759 gfp_t gfp = GFP_KERNEL | __GFP_NOFAIL; 762 760 763 761 mem_cgroup_sk_alloc(newsk);
+76 -37
net/sctp/socket.c
··· 4842 4842 return 0; 4843 4843 } 4844 4844 4845 + static struct sock *sctp_clone_sock(struct sock *sk, 4846 + struct sctp_association *asoc, 4847 + enum sctp_socket_type type) 4848 + { 4849 + struct sock *newsk = sk_clone(sk, GFP_KERNEL, false); 4850 + struct inet_sock *newinet; 4851 + struct sctp_sock *newsp; 4852 + int err = -ENOMEM; 4853 + 4854 + if (!newsk) 4855 + return ERR_PTR(err); 4856 + 4857 + /* sk_clone() sets refcnt to 2 */ 4858 + sock_put(newsk); 4859 + 4860 + newinet = inet_sk(newsk); 4861 + newsp = sctp_sk(newsk); 4862 + 4863 + newsp->pf->to_sk_daddr(&asoc->peer.primary_addr, newsk); 4864 + newinet->inet_dport = htons(asoc->peer.port); 4865 + 4866 + newsp->pf->copy_ip_options(sk, newsk); 4867 + atomic_set(&newinet->inet_id, get_random_u16()); 4868 + 4869 + inet_set_bit(MC_LOOP, newsk); 4870 + newinet->mc_ttl = 1; 4871 + newinet->mc_index = 0; 4872 + newinet->mc_list = NULL; 4873 + 4874 + #if IS_ENABLED(CONFIG_IPV6) 4875 + if (sk->sk_family == AF_INET6) { 4876 + struct ipv6_pinfo *newnp = inet6_sk(newsk); 4877 + 4878 + newinet->pinet6 = &((struct sctp6_sock *)newsk)->inet6; 4879 + newinet->ipv6_fl_list = NULL; 4880 + 4881 + memcpy(newnp, inet6_sk(sk), sizeof(struct ipv6_pinfo)); 4882 + newnp->ipv6_mc_list = NULL; 4883 + newnp->ipv6_ac_list = NULL; 4884 + } 4885 + #endif 4886 + 4887 + skb_queue_head_init(&newsp->pd_lobby); 4888 + 4889 + newsp->ep = sctp_endpoint_new(newsk, GFP_KERNEL); 4890 + if (!newsp->ep) 4891 + goto out_release; 4892 + 4893 + SCTP_DBG_OBJCNT_INC(sock); 4894 + sk_sockets_allocated_inc(newsk); 4895 + sock_prot_inuse_add(sock_net(sk), newsk->sk_prot, 1); 4896 + 4897 + err = sctp_sock_migrate(sk, newsk, asoc, type); 4898 + if (err) 4899 + goto out_release; 4900 + 4901 + /* Set newsk security attributes from original sk and connection 4902 + * security attribute from asoc. 4903 + */ 4904 + security_sctp_sk_clone(asoc, sk, newsk); 4905 + 4906 + return newsk; 4907 + 4908 + out_release: 4909 + sk_common_release(newsk); 4910 + return ERR_PTR(err); 4911 + } 4912 + 4845 4913 /* 4.1.4 accept() - TCP Style Syntax 4846 4914 * 4847 4915 * Applications use accept() call to remove an established SCTP ··· 4919 4851 */ 4920 4852 static struct sock *sctp_accept(struct sock *sk, struct proto_accept_arg *arg) 4921 4853 { 4922 - struct sctp_sock *sp, *newsp; 4923 - struct sctp_endpoint *ep; 4924 - struct sock *newsk = NULL; 4925 4854 struct sctp_association *asoc; 4926 - long timeo; 4855 + struct sock *newsk = NULL; 4927 4856 int error = 0; 4857 + long timeo; 4928 4858 4929 4859 lock_sock(sk); 4930 - 4931 - sp = sctp_sk(sk); 4932 - ep = sp->ep; 4933 4860 4934 4861 if (!sctp_style(sk, TCP)) { 4935 4862 error = -EOPNOTSUPP; ··· 4946 4883 /* We treat the list of associations on the endpoint as the accept 4947 4884 * queue and pick the first association on the list. 4948 4885 */ 4949 - asoc = list_entry(ep->asocs.next, struct sctp_association, asocs); 4886 + asoc = list_entry(sctp_sk(sk)->ep->asocs.next, 4887 + struct sctp_association, asocs); 4950 4888 4951 - newsk = sp->pf->create_accept_sk(sk, asoc, arg->kern); 4952 - if (!newsk) { 4953 - error = -ENOMEM; 4954 - goto out; 4889 + newsk = sctp_clone_sock(sk, asoc, SCTP_SOCKET_TCP); 4890 + if (IS_ERR(newsk)) { 4891 + error = PTR_ERR(newsk); 4892 + newsk = NULL; 4955 4893 } 4956 - 4957 - newsp = sctp_sk(newsk); 4958 - newsp->ep = sctp_endpoint_new(newsk, GFP_KERNEL); 4959 - if (!newsp->ep) { 4960 - error = -ENOMEM; 4961 - goto out_release; 4962 - } 4963 - 4964 - skb_queue_head_init(&newsp->pd_lobby); 4965 - 4966 - sk_sockets_allocated_inc(newsk); 4967 - sock_prot_inuse_add(sock_net(sk), newsk->sk_prot, 1); 4968 - SCTP_DBG_OBJCNT_INC(sock); 4969 - 4970 - /* Populate the fields of the newsk from the oldsk and migrate the 4971 - * asoc to the newsk. 4972 - */ 4973 - error = sctp_sock_migrate(sk, newsk, asoc, SCTP_SOCKET_TCP); 4974 - if (error) 4975 - goto out_release; 4976 4894 4977 4895 out: 4978 4896 release_sock(sk); 4979 4897 arg->err = error; 4980 4898 return newsk; 4981 - 4982 - out_release: 4983 - sk_common_release(newsk); 4984 - newsk = NULL; 4985 - goto out; 4986 4899 } 4987 4900 4988 4901 /* The SCTP ioctl handler. */