Commit 8beeebe9 authored by D. Wythe's avatar D. Wythe Committed by Wang Liang
Browse files

net/smc: refactoring initialization of smc sock

stable inclusion
from stable-v6.6.66
commit f59b799e52f73c00d417957437b3cc77283261de
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBEAPB
CVE: CVE-2024-56641

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=f59b799e52f73c00d417957437b3cc77283261de



--------------------------------

[ Upstream commit d0e35656d83458d668593930f1568d464dde429c ]

This patch aims to isolate the shared components of SMC socket
allocation by introducing smc_sk_init() for sock initialization
and __smc_create_clcsk() for the initialization of clcsock.

This is in preparation for the subsequent implementation of the
AF_INET version of SMC.

Signed-off-by: default avatarD. Wythe <alibuda@linux.alibaba.com>
Reviewed-by: default avatarTony Lu <tonylu@linux.alibaba.com>
Reviewed-by: default avatarWenjia Zhang <wenjia@linux.ibm.com>
Reviewed-by: default avatarDust Li <dust.li@linux.alibaba.com>
Tested-by: default avatarNiklas Schnelle <schnelle@linux.ibm.com>
Tested-by: default avatarWenjia Zhang <wenjia@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Stable-dep-of: 0541db8ee32c ("net/smc: initialize close_work early to avoid warning")
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarWang Liang <wangliang74@huawei.com>
parent 88ee450e
Loading
Loading
Loading
Loading
+48 −38
Original line number Diff line number Diff line
@@ -363,25 +363,15 @@ static void smc_destruct(struct sock *sk)
		return;
}

static struct sock *smc_sock_alloc(struct net *net, struct socket *sock,
				   int protocol)
void smc_sk_init(struct net *net, struct sock *sk, int protocol)
{
	struct smc_sock *smc;
	struct proto *prot;
	struct sock *sk;

	prot = (protocol == SMCPROTO_SMC6) ? &smc_proto6 : &smc_proto;
	sk = sk_alloc(net, PF_SMC, GFP_KERNEL, prot, 0);
	if (!sk)
		return NULL;
	struct smc_sock *smc = smc_sk(sk);

	sock_init_data(sock, sk); /* sets sk_refcnt to 1 */
	sk->sk_state = SMC_INIT;
	sk->sk_destruct = smc_destruct;
	sk->sk_protocol = protocol;
	WRITE_ONCE(sk->sk_sndbuf, 2 * READ_ONCE(net->smc.sysctl_wmem));
	WRITE_ONCE(sk->sk_rcvbuf, 2 * READ_ONCE(net->smc.sysctl_rmem));
	smc = smc_sk(sk);
	INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work);
	INIT_WORK(&smc->connect_work, smc_connect_work);
	INIT_DELAYED_WORK(&smc->conn.tx_work, smc_tx_work);
@@ -391,6 +381,24 @@ static struct sock *smc_sock_alloc(struct net *net, struct socket *sock,
	sk->sk_prot->hash(sk);
	mutex_init(&smc->clcsock_release_lock);
	smc_init_saved_callbacks(smc);
	smc->limit_smc_hs = net->smc.limit_smc_hs;
	smc->use_fallback = false; /* assume rdma capability first */
	smc->fallback_rsn = 0;
}

static struct sock *smc_sock_alloc(struct net *net, struct socket *sock,
				   int protocol)
{
	struct proto *prot;
	struct sock *sk;

	prot = (protocol == SMCPROTO_SMC6) ? &smc_proto6 : &smc_proto;
	sk = sk_alloc(net, PF_SMC, GFP_KERNEL, prot, 0);
	if (!sk)
		return NULL;

	sock_init_data(sock, sk); /* sets sk_refcnt to 1 */
	smc_sk_init(net, sk, protocol);

	return sk;
}
@@ -3304,6 +3312,31 @@ static const struct proto_ops smc_sock_ops = {
	.splice_read	= smc_splice_read,
};

int smc_create_clcsk(struct net *net, struct sock *sk, int family)
{
	struct smc_sock *smc = smc_sk(sk);
	int rc;

	rc = sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP,
			      &smc->clcsock);
	if (rc) {
		sk_common_release(sk);
		return rc;
	}

	/* smc_clcsock_release() does not wait smc->clcsock->sk's
	 * destruction;  its sk_state might not be TCP_CLOSE after
	 * smc->sk is close()d, and TCP timers can be fired later,
	 * which need net ref.
	 */
	sk = smc->clcsock->sk;
	__netns_tracker_free(net, &sk->ns_tracker, false);
	sk->sk_net_refcnt = 1;
	get_net_track(net, &sk->ns_tracker, GFP_KERNEL);
	sock_inuse_add(net, 1);
	return 0;
}

static int __smc_create(struct net *net, struct socket *sock, int protocol,
			int kern, struct socket *clcsock)
{
@@ -3329,35 +3362,12 @@ static int __smc_create(struct net *net, struct socket *sock, int protocol,

	/* create internal TCP socket for CLC handshake and fallback */
	smc = smc_sk(sk);
	smc->use_fallback = false; /* assume rdma capability first */
	smc->fallback_rsn = 0;

	/* default behavior from limit_smc_hs in every net namespace */
	smc->limit_smc_hs = net->smc.limit_smc_hs;

	rc = 0;
	if (!clcsock) {
		rc = sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP,
				      &smc->clcsock);
		if (rc) {
			sk_common_release(sk);
			goto out;
		}

		/* smc_clcsock_release() does not wait smc->clcsock->sk's
		 * destruction;  its sk_state might not be TCP_CLOSE after
		 * smc->sk is close()d, and TCP timers can be fired later,
		 * which need net ref.
		 */
		sk = smc->clcsock->sk;
		__netns_tracker_free(net, &sk->ns_tracker, false);
		sk->sk_net_refcnt = 1;
		get_net_track(net, &sk->ns_tracker, GFP_KERNEL);
		sock_inuse_add(net, 1);
	} else {
	if (clcsock)
		smc->clcsock = clcsock;
	}

	else
		rc = smc_create_clcsk(net, sk, family);
out:
	return rc;
}
+5 −0
Original line number Diff line number Diff line
@@ -34,6 +34,11 @@
extern struct proto smc_proto;
extern struct proto smc_proto6;

/* smc sock initialization */
void smc_sk_init(struct net *net, struct sock *sk, int protocol);
/* clcsock initialization */
int smc_create_clcsk(struct net *net, struct sock *sk, int family);

#ifdef ATOMIC64_INIT
#define KERNEL_HAS_ATOMIC64
#endif