VYPR
Unrated severityNVD Advisory· Published Jun 9, 2026

CVE-2026-46330

CVE-2026-46330

Description

Linux kernel TCP ULP support for SMC is fundamentally broken, risking use-after-free and instability. The feature has been reverted.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Linux kernel TCP ULP support for SMC is fundamentally broken, risking use-after-free and instability. The feature has been reverted.

Vulnerability

The Linux kernel's TCP Unified Linux Programming (ULP) support for Socket Messaging Control (SMC) is fundamentally flawed. The implementation attempts to convert an active TCP socket into an SMC socket by modifying the underlying struct file, dentry, and inode in-place. This violates core VFS invariants, leading to potential use-after-free errors and general system instability. This vulnerability existed in versions prior to the revert commit [1].

Exploitation

Exploitation requires the ability to trigger the conversion of an active TCP socket into an SMC socket. The exact conditions or user interaction needed to reach this code path are not detailed in the available references, but the underlying flaw lies in the in-place modification of file system structures associated with an open file descriptor [1].

Impact

Successful exploitation of this vulnerability can lead to use-after-free errors and general system instability. The modification of core VFS invariants can result in unpredictable behavior and potential crashes, compromising the integrity and availability of the system [1].

Mitigation

The TCP ULP support for SMC has been reverted in the Linux kernel via commit d7cd421da9da2cc7b4d25b8537f66db5c8331c40. Users are advised to ensure their systems are updated to a kernel version that includes this revert. No specific patch release date is provided, but the revert indicates the feature is removed entirely due to its fundamental design flaws [1].

AI Insight generated on Jun 9, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

5
6c505d95c69e

Revert "net/smc: Introduce TCP ULP support"

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"D. Wythe"Jan 28, 2026Fixed in 6.19.4via kernel-cna
1 file changed · +4 88
  • net/smc/af_smc.c+4 88 modified
    diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
    index f97f77b041d97..d8201eb3ac5f3 100644
    --- a/net/smc/af_smc.c
    +++ b/net/smc/af_smc.c
    @@ -3357,11 +3357,10 @@ int smc_create_clcsk(struct net *net, struct sock *sk, int family)
     	return 0;
     }
     
    -static int __smc_create(struct net *net, struct socket *sock, int protocol,
    -			int kern, struct socket *clcsock)
    +static int smc_create(struct net *net, struct socket *sock, int protocol,
    +		      int kern)
     {
     	int family = (protocol == SMCPROTO_SMC6) ? PF_INET6 : PF_INET;
    -	struct smc_sock *smc;
     	struct sock *sk;
     	int rc;
     
    @@ -3380,15 +3379,7 @@ static int __smc_create(struct net *net, struct socket *sock, int protocol,
     	if (!sk)
     		goto out;
     
    -	/* create internal TCP socket for CLC handshake and fallback */
    -	smc = smc_sk(sk);
    -
    -	rc = 0;
    -	if (clcsock)
    -		smc->clcsock = clcsock;
    -	else
    -		rc = smc_create_clcsk(net, sk, family);
    -
    +	rc = smc_create_clcsk(net, sk, family);
     	if (rc) {
     		sk_common_release(sk);
     		sock->sk = NULL;
    @@ -3397,76 +3388,12 @@ out:
     	return rc;
     }
     
    -static int smc_create(struct net *net, struct socket *sock, int protocol,
    -		      int kern)
    -{
    -	return __smc_create(net, sock, protocol, kern, NULL);
    -}
    -
     static const struct net_proto_family smc_sock_family_ops = {
     	.family	= PF_SMC,
     	.owner	= THIS_MODULE,
     	.create	= smc_create,
     };
     
    -static int smc_ulp_init(struct sock *sk)
    -{
    -	struct socket *tcp = sk->sk_socket;
    -	struct net *net = sock_net(sk);
    -	struct socket *smcsock;
    -	int protocol, ret;
    -
    -	/* only TCP can be replaced */
    -	if (tcp->type != SOCK_STREAM || sk->sk_protocol != IPPROTO_TCP ||
    -	    (sk->sk_family != AF_INET && sk->sk_family != AF_INET6))
    -		return -ESOCKTNOSUPPORT;
    -	/* don't handle wq now */
    -	if (tcp->state != SS_UNCONNECTED || !tcp->file || tcp->wq.fasync_list)
    -		return -ENOTCONN;
    -
    -	if (sk->sk_family == AF_INET)
    -		protocol = SMCPROTO_SMC;
    -	else
    -		protocol = SMCPROTO_SMC6;
    -
    -	smcsock = sock_alloc();
    -	if (!smcsock)
    -		return -ENFILE;
    -
    -	smcsock->type = SOCK_STREAM;
    -	__module_get(THIS_MODULE); /* tried in __tcp_ulp_find_autoload */
    -	ret = __smc_create(net, smcsock, protocol, 1, tcp);
    -	if (ret) {
    -		sock_release(smcsock); /* module_put() which ops won't be NULL */
    -		return ret;
    -	}
    -
    -	/* replace tcp socket to smc */
    -	smcsock->file = tcp->file;
    -	smcsock->file->private_data = smcsock;
    -	smcsock->file->f_inode = SOCK_INODE(smcsock); /* replace inode when sock_close */
    -	smcsock->file->f_path.dentry->d_inode = SOCK_INODE(smcsock); /* dput() in __fput */
    -	tcp->file = NULL;
    -
    -	return ret;
    -}
    -
    -static void smc_ulp_clone(const struct request_sock *req, struct sock *newsk,
    -			  const gfp_t priority)
    -{
    -	struct inet_connection_sock *icsk = inet_csk(newsk);
    -
    -	/* don't inherit ulp ops to child when listen */
    -	icsk->icsk_ulp_ops = NULL;
    -}
    -
    -static struct tcp_ulp_ops smc_ulp_ops __read_mostly = {
    -	.name		= "smc",
    -	.owner		= THIS_MODULE,
    -	.init		= smc_ulp_init,
    -	.clone		= smc_ulp_clone,
    -};
    -
     unsigned int smc_net_id;
     
     static __net_init int smc_net_init(struct net *net)
    @@ -3589,16 +3516,10 @@ static int __init smc_init(void)
     		pr_err("%s: ib_register fails with %d\n", __func__, rc);
     		goto out_sock;
     	}
    -
    -	rc = tcp_register_ulp(&smc_ulp_ops);
    -	if (rc) {
    -		pr_err("%s: tcp_ulp_register fails with %d\n", __func__, rc);
    -		goto out_ib;
    -	}
     	rc = smc_inet_init();
     	if (rc) {
     		pr_err("%s: smc_inet_init fails with %d\n", __func__, rc);
    -		goto out_ulp;
    +		goto out_ib;
     	}
     	rc = bpf_smc_hs_ctrl_init();
     	if (rc) {
    @@ -3610,8 +3531,6 @@ static int __init smc_init(void)
     	return 0;
     out_inet:
     	smc_inet_exit();
    -out_ulp:
    -	tcp_unregister_ulp(&smc_ulp_ops);
     out_ib:
     	smc_ib_unregister_client();
     out_sock:
    @@ -3647,7 +3566,6 @@ static void __exit smc_exit(void)
     {
     	static_branch_disable(&tcp_have_smc);
     	smc_inet_exit();
    -	tcp_unregister_ulp(&smc_ulp_ops);
     	sock_unregister(PF_SMC);
     	smc_core_exit();
     	smc_ib_unregister_client();
    @@ -3672,7 +3590,6 @@ MODULE_AUTHOR("Ursula Braun <ubraun@linux.vnet.ibm.com>");
     MODULE_DESCRIPTION("smc socket address family");
     MODULE_LICENSE("GPL");
     MODULE_ALIAS_NETPROTO(PF_SMC);
    -MODULE_ALIAS_TCP_ULP("smc");
     /* 256 for IPPROTO_SMC and 1 for SOCK_STREAM */
     MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 256, 1);
     #if IS_ENABLED(CONFIG_IPV6)
    -- 
    cgit 1.3-korg
    
    
    
df31a6b0a305

Revert "net/smc: Introduce TCP ULP support"

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"D. Wythe"Jan 28, 2026Fixed in 7.0via kernel-cna
1 file changed · +4 88
  • net/smc/af_smc.c+4 88 modified
    diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
    index f97f77b041d97..d8201eb3ac5f3 100644
    --- a/net/smc/af_smc.c
    +++ b/net/smc/af_smc.c
    @@ -3357,11 +3357,10 @@ int smc_create_clcsk(struct net *net, struct sock *sk, int family)
     	return 0;
     }
     
    -static int __smc_create(struct net *net, struct socket *sock, int protocol,
    -			int kern, struct socket *clcsock)
    +static int smc_create(struct net *net, struct socket *sock, int protocol,
    +		      int kern)
     {
     	int family = (protocol == SMCPROTO_SMC6) ? PF_INET6 : PF_INET;
    -	struct smc_sock *smc;
     	struct sock *sk;
     	int rc;
     
    @@ -3380,15 +3379,7 @@ static int __smc_create(struct net *net, struct socket *sock, int protocol,
     	if (!sk)
     		goto out;
     
    -	/* create internal TCP socket for CLC handshake and fallback */
    -	smc = smc_sk(sk);
    -
    -	rc = 0;
    -	if (clcsock)
    -		smc->clcsock = clcsock;
    -	else
    -		rc = smc_create_clcsk(net, sk, family);
    -
    +	rc = smc_create_clcsk(net, sk, family);
     	if (rc) {
     		sk_common_release(sk);
     		sock->sk = NULL;
    @@ -3397,76 +3388,12 @@ out:
     	return rc;
     }
     
    -static int smc_create(struct net *net, struct socket *sock, int protocol,
    -		      int kern)
    -{
    -	return __smc_create(net, sock, protocol, kern, NULL);
    -}
    -
     static const struct net_proto_family smc_sock_family_ops = {
     	.family	= PF_SMC,
     	.owner	= THIS_MODULE,
     	.create	= smc_create,
     };
     
    -static int smc_ulp_init(struct sock *sk)
    -{
    -	struct socket *tcp = sk->sk_socket;
    -	struct net *net = sock_net(sk);
    -	struct socket *smcsock;
    -	int protocol, ret;
    -
    -	/* only TCP can be replaced */
    -	if (tcp->type != SOCK_STREAM || sk->sk_protocol != IPPROTO_TCP ||
    -	    (sk->sk_family != AF_INET && sk->sk_family != AF_INET6))
    -		return -ESOCKTNOSUPPORT;
    -	/* don't handle wq now */
    -	if (tcp->state != SS_UNCONNECTED || !tcp->file || tcp->wq.fasync_list)
    -		return -ENOTCONN;
    -
    -	if (sk->sk_family == AF_INET)
    -		protocol = SMCPROTO_SMC;
    -	else
    -		protocol = SMCPROTO_SMC6;
    -
    -	smcsock = sock_alloc();
    -	if (!smcsock)
    -		return -ENFILE;
    -
    -	smcsock->type = SOCK_STREAM;
    -	__module_get(THIS_MODULE); /* tried in __tcp_ulp_find_autoload */
    -	ret = __smc_create(net, smcsock, protocol, 1, tcp);
    -	if (ret) {
    -		sock_release(smcsock); /* module_put() which ops won't be NULL */
    -		return ret;
    -	}
    -
    -	/* replace tcp socket to smc */
    -	smcsock->file = tcp->file;
    -	smcsock->file->private_data = smcsock;
    -	smcsock->file->f_inode = SOCK_INODE(smcsock); /* replace inode when sock_close */
    -	smcsock->file->f_path.dentry->d_inode = SOCK_INODE(smcsock); /* dput() in __fput */
    -	tcp->file = NULL;
    -
    -	return ret;
    -}
    -
    -static void smc_ulp_clone(const struct request_sock *req, struct sock *newsk,
    -			  const gfp_t priority)
    -{
    -	struct inet_connection_sock *icsk = inet_csk(newsk);
    -
    -	/* don't inherit ulp ops to child when listen */
    -	icsk->icsk_ulp_ops = NULL;
    -}
    -
    -static struct tcp_ulp_ops smc_ulp_ops __read_mostly = {
    -	.name		= "smc",
    -	.owner		= THIS_MODULE,
    -	.init		= smc_ulp_init,
    -	.clone		= smc_ulp_clone,
    -};
    -
     unsigned int smc_net_id;
     
     static __net_init int smc_net_init(struct net *net)
    @@ -3589,16 +3516,10 @@ static int __init smc_init(void)
     		pr_err("%s: ib_register fails with %d\n", __func__, rc);
     		goto out_sock;
     	}
    -
    -	rc = tcp_register_ulp(&smc_ulp_ops);
    -	if (rc) {
    -		pr_err("%s: tcp_ulp_register fails with %d\n", __func__, rc);
    -		goto out_ib;
    -	}
     	rc = smc_inet_init();
     	if (rc) {
     		pr_err("%s: smc_inet_init fails with %d\n", __func__, rc);
    -		goto out_ulp;
    +		goto out_ib;
     	}
     	rc = bpf_smc_hs_ctrl_init();
     	if (rc) {
    @@ -3610,8 +3531,6 @@ static int __init smc_init(void)
     	return 0;
     out_inet:
     	smc_inet_exit();
    -out_ulp:
    -	tcp_unregister_ulp(&smc_ulp_ops);
     out_ib:
     	smc_ib_unregister_client();
     out_sock:
    @@ -3647,7 +3566,6 @@ static void __exit smc_exit(void)
     {
     	static_branch_disable(&tcp_have_smc);
     	smc_inet_exit();
    -	tcp_unregister_ulp(&smc_ulp_ops);
     	sock_unregister(PF_SMC);
     	smc_core_exit();
     	smc_ib_unregister_client();
    @@ -3672,7 +3590,6 @@ MODULE_AUTHOR("Ursula Braun <ubraun@linux.vnet.ibm.com>");
     MODULE_DESCRIPTION("smc socket address family");
     MODULE_LICENSE("GPL");
     MODULE_ALIAS_NETPROTO(PF_SMC);
    -MODULE_ALIAS_TCP_ULP("smc");
     /* 256 for IPPROTO_SMC and 1 for SOCK_STREAM */
     MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 256, 1);
     #if IS_ENABLED(CONFIG_IPV6)
    -- 
    cgit 1.3-korg
    
    
    
d7cd421da9da

net/smc: Introduce TCP ULP support

https://github.com/torvalds/linuxTony LuDec 28, 2021via text-mined
1 file changed · +86 7
  • net/smc/af_smc.c+86 7 modified
    @@ -2700,8 +2700,8 @@ static const struct proto_ops smc_sock_ops = {
     	.splice_read	= smc_splice_read,
     };
     
    -static int smc_create(struct net *net, struct socket *sock, int protocol,
    -		      int kern)
    +static int __smc_create(struct net *net, struct socket *sock, int protocol,
    +			int kern, struct socket *clcsock)
     {
     	int family = (protocol == SMCPROTO_SMC6) ? PF_INET6 : PF_INET;
     	struct smc_sock *smc;
    @@ -2726,25 +2726,96 @@ static int smc_create(struct net *net, struct socket *sock, int protocol,
     	smc = smc_sk(sk);
     	smc->use_fallback = false; /* assume rdma capability first */
     	smc->fallback_rsn = 0;
    -	rc = sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP,
    -			      &smc->clcsock);
    -	if (rc) {
    -		sk_common_release(sk);
    -		goto out;
    +
    +	rc = 0;
    +	if (!clcsock) {
    +		rc = sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP,
    +				      &smc->clcsock);
    +		if (rc) {
    +			sk_common_release(sk);
    +			goto out;
    +		}
    +	} else {
    +		smc->clcsock = clcsock;
     	}
    +
     	smc->sk.sk_sndbuf = max(smc->clcsock->sk->sk_sndbuf, SMC_BUF_MIN_SIZE);
     	smc->sk.sk_rcvbuf = max(smc->clcsock->sk->sk_rcvbuf, SMC_BUF_MIN_SIZE);
     
     out:
     	return rc;
     }
     
    +static int smc_create(struct net *net, struct socket *sock, int protocol,
    +		      int kern)
    +{
    +	return __smc_create(net, sock, protocol, kern, NULL);
    +}
    +
     static const struct net_proto_family smc_sock_family_ops = {
     	.family	= PF_SMC,
     	.owner	= THIS_MODULE,
     	.create	= smc_create,
     };
     
    +static int smc_ulp_init(struct sock *sk)
    +{
    +	struct socket *tcp = sk->sk_socket;
    +	struct net *net = sock_net(sk);
    +	struct socket *smcsock;
    +	int protocol, ret;
    +
    +	/* only TCP can be replaced */
    +	if (tcp->type != SOCK_STREAM || sk->sk_protocol != IPPROTO_TCP ||
    +	    (sk->sk_family != AF_INET && sk->sk_family != AF_INET6))
    +		return -ESOCKTNOSUPPORT;
    +	/* don't handle wq now */
    +	if (tcp->state != SS_UNCONNECTED || !tcp->file || tcp->wq.fasync_list)
    +		return -ENOTCONN;
    +
    +	if (sk->sk_family == AF_INET)
    +		protocol = SMCPROTO_SMC;
    +	else
    +		protocol = SMCPROTO_SMC6;
    +
    +	smcsock = sock_alloc();
    +	if (!smcsock)
    +		return -ENFILE;
    +
    +	smcsock->type = SOCK_STREAM;
    +	__module_get(THIS_MODULE); /* tried in __tcp_ulp_find_autoload */
    +	ret = __smc_create(net, smcsock, protocol, 1, tcp);
    +	if (ret) {
    +		sock_release(smcsock); /* module_put() which ops won't be NULL */
    +		return ret;
    +	}
    +
    +	/* replace tcp socket to smc */
    +	smcsock->file = tcp->file;
    +	smcsock->file->private_data = smcsock;
    +	smcsock->file->f_inode = SOCK_INODE(smcsock); /* replace inode when sock_close */
    +	smcsock->file->f_path.dentry->d_inode = SOCK_INODE(smcsock); /* dput() in __fput */
    +	tcp->file = NULL;
    +
    +	return ret;
    +}
    +
    +static void smc_ulp_clone(const struct request_sock *req, struct sock *newsk,
    +			  const gfp_t priority)
    +{
    +	struct inet_connection_sock *icsk = inet_csk(newsk);
    +
    +	/* don't inherit ulp ops to child when listen */
    +	icsk->icsk_ulp_ops = NULL;
    +}
    +
    +static struct tcp_ulp_ops smc_ulp_ops __read_mostly = {
    +	.name		= "smc",
    +	.owner		= THIS_MODULE,
    +	.init		= smc_ulp_init,
    +	.clone		= smc_ulp_clone,
    +};
    +
     unsigned int smc_net_id;
     
     static __net_init int smc_net_init(struct net *net)
    @@ -2855,6 +2926,12 @@ static int __init smc_init(void)
     		goto out_sock;
     	}
     
    +	rc = tcp_register_ulp(&smc_ulp_ops);
    +	if (rc) {
    +		pr_err("%s: tcp_ulp_register fails with %d\n", __func__, rc);
    +		goto out_sock;
    +	}
    +
     	static_branch_enable(&tcp_have_smc);
     	return 0;
     
    @@ -2883,6 +2960,7 @@ static int __init smc_init(void)
     static void __exit smc_exit(void)
     {
     	static_branch_disable(&tcp_have_smc);
    +	tcp_unregister_ulp(&smc_ulp_ops);
     	sock_unregister(PF_SMC);
     	smc_core_exit();
     	smc_ib_unregister_client();
    @@ -2905,3 +2983,4 @@ MODULE_AUTHOR("Ursula Braun <ubraun@linux.vnet.ibm.com>");
     MODULE_DESCRIPTION("smc socket address family");
     MODULE_LICENSE("GPL");
     MODULE_ALIAS_NETPROTO(PF_SMC);
    +MODULE_ALIAS_TCP_ULP("smc");
    
6c505d95c69e

Revert "net/smc: Introduce TCP ULP support"

1 file changed · +4 88
  • net/smc/af_smc.c+4 88 modified
    diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
    index f97f77b041d97..d8201eb3ac5f3 100644
    --- a/net/smc/af_smc.c
    +++ b/net/smc/af_smc.c
    @@ -3357,11 +3357,10 @@ int smc_create_clcsk(struct net *net, struct sock *sk, int family)
     	return 0;
     }
     
    -static int __smc_create(struct net *net, struct socket *sock, int protocol,
    -			int kern, struct socket *clcsock)
    +static int smc_create(struct net *net, struct socket *sock, int protocol,
    +		      int kern)
     {
     	int family = (protocol == SMCPROTO_SMC6) ? PF_INET6 : PF_INET;
    -	struct smc_sock *smc;
     	struct sock *sk;
     	int rc;
     
    @@ -3380,15 +3379,7 @@ static int __smc_create(struct net *net, struct socket *sock, int protocol,
     	if (!sk)
     		goto out;
     
    -	/* create internal TCP socket for CLC handshake and fallback */
    -	smc = smc_sk(sk);
    -
    -	rc = 0;
    -	if (clcsock)
    -		smc->clcsock = clcsock;
    -	else
    -		rc = smc_create_clcsk(net, sk, family);
    -
    +	rc = smc_create_clcsk(net, sk, family);
     	if (rc) {
     		sk_common_release(sk);
     		sock->sk = NULL;
    @@ -3397,76 +3388,12 @@ out:
     	return rc;
     }
     
    -static int smc_create(struct net *net, struct socket *sock, int protocol,
    -		      int kern)
    -{
    -	return __smc_create(net, sock, protocol, kern, NULL);
    -}
    -
     static const struct net_proto_family smc_sock_family_ops = {
     	.family	= PF_SMC,
     	.owner	= THIS_MODULE,
     	.create	= smc_create,
     };
     
    -static int smc_ulp_init(struct sock *sk)
    -{
    -	struct socket *tcp = sk->sk_socket;
    -	struct net *net = sock_net(sk);
    -	struct socket *smcsock;
    -	int protocol, ret;
    -
    -	/* only TCP can be replaced */
    -	if (tcp->type != SOCK_STREAM || sk->sk_protocol != IPPROTO_TCP ||
    -	    (sk->sk_family != AF_INET && sk->sk_family != AF_INET6))
    -		return -ESOCKTNOSUPPORT;
    -	/* don't handle wq now */
    -	if (tcp->state != SS_UNCONNECTED || !tcp->file || tcp->wq.fasync_list)
    -		return -ENOTCONN;
    -
    -	if (sk->sk_family == AF_INET)
    -		protocol = SMCPROTO_SMC;
    -	else
    -		protocol = SMCPROTO_SMC6;
    -
    -	smcsock = sock_alloc();
    -	if (!smcsock)
    -		return -ENFILE;
    -
    -	smcsock->type = SOCK_STREAM;
    -	__module_get(THIS_MODULE); /* tried in __tcp_ulp_find_autoload */
    -	ret = __smc_create(net, smcsock, protocol, 1, tcp);
    -	if (ret) {
    -		sock_release(smcsock); /* module_put() which ops won't be NULL */
    -		return ret;
    -	}
    -
    -	/* replace tcp socket to smc */
    -	smcsock->file = tcp->file;
    -	smcsock->file->private_data = smcsock;
    -	smcsock->file->f_inode = SOCK_INODE(smcsock); /* replace inode when sock_close */
    -	smcsock->file->f_path.dentry->d_inode = SOCK_INODE(smcsock); /* dput() in __fput */
    -	tcp->file = NULL;
    -
    -	return ret;
    -}
    -
    -static void smc_ulp_clone(const struct request_sock *req, struct sock *newsk,
    -			  const gfp_t priority)
    -{
    -	struct inet_connection_sock *icsk = inet_csk(newsk);
    -
    -	/* don't inherit ulp ops to child when listen */
    -	icsk->icsk_ulp_ops = NULL;
    -}
    -
    -static struct tcp_ulp_ops smc_ulp_ops __read_mostly = {
    -	.name		= "smc",
    -	.owner		= THIS_MODULE,
    -	.init		= smc_ulp_init,
    -	.clone		= smc_ulp_clone,
    -};
    -
     unsigned int smc_net_id;
     
     static __net_init int smc_net_init(struct net *net)
    @@ -3589,16 +3516,10 @@ static int __init smc_init(void)
     		pr_err("%s: ib_register fails with %d\n", __func__, rc);
     		goto out_sock;
     	}
    -
    -	rc = tcp_register_ulp(&smc_ulp_ops);
    -	if (rc) {
    -		pr_err("%s: tcp_ulp_register fails with %d\n", __func__, rc);
    -		goto out_ib;
    -	}
     	rc = smc_inet_init();
     	if (rc) {
     		pr_err("%s: smc_inet_init fails with %d\n", __func__, rc);
    -		goto out_ulp;
    +		goto out_ib;
     	}
     	rc = bpf_smc_hs_ctrl_init();
     	if (rc) {
    @@ -3610,8 +3531,6 @@ static int __init smc_init(void)
     	return 0;
     out_inet:
     	smc_inet_exit();
    -out_ulp:
    -	tcp_unregister_ulp(&smc_ulp_ops);
     out_ib:
     	smc_ib_unregister_client();
     out_sock:
    @@ -3647,7 +3566,6 @@ static void __exit smc_exit(void)
     {
     	static_branch_disable(&tcp_have_smc);
     	smc_inet_exit();
    -	tcp_unregister_ulp(&smc_ulp_ops);
     	sock_unregister(PF_SMC);
     	smc_core_exit();
     	smc_ib_unregister_client();
    @@ -3672,7 +3590,6 @@ MODULE_AUTHOR("Ursula Braun <ubraun@linux.vnet.ibm.com>");
     MODULE_DESCRIPTION("smc socket address family");
     MODULE_LICENSE("GPL");
     MODULE_ALIAS_NETPROTO(PF_SMC);
    -MODULE_ALIAS_TCP_ULP("smc");
     /* 256 for IPPROTO_SMC and 1 for SOCK_STREAM */
     MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 256, 1);
     #if IS_ENABLED(CONFIG_IPV6)
    -- 
    cgit 1.3-korg
    
    
    
df31a6b0a305

Revert "net/smc: Introduce TCP ULP support"

1 file changed · +4 88
  • net/smc/af_smc.c+4 88 modified
    diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
    index f97f77b041d97..d8201eb3ac5f3 100644
    --- a/net/smc/af_smc.c
    +++ b/net/smc/af_smc.c
    @@ -3357,11 +3357,10 @@ int smc_create_clcsk(struct net *net, struct sock *sk, int family)
     	return 0;
     }
     
    -static int __smc_create(struct net *net, struct socket *sock, int protocol,
    -			int kern, struct socket *clcsock)
    +static int smc_create(struct net *net, struct socket *sock, int protocol,
    +		      int kern)
     {
     	int family = (protocol == SMCPROTO_SMC6) ? PF_INET6 : PF_INET;
    -	struct smc_sock *smc;
     	struct sock *sk;
     	int rc;
     
    @@ -3380,15 +3379,7 @@ static int __smc_create(struct net *net, struct socket *sock, int protocol,
     	if (!sk)
     		goto out;
     
    -	/* create internal TCP socket for CLC handshake and fallback */
    -	smc = smc_sk(sk);
    -
    -	rc = 0;
    -	if (clcsock)
    -		smc->clcsock = clcsock;
    -	else
    -		rc = smc_create_clcsk(net, sk, family);
    -
    +	rc = smc_create_clcsk(net, sk, family);
     	if (rc) {
     		sk_common_release(sk);
     		sock->sk = NULL;
    @@ -3397,76 +3388,12 @@ out:
     	return rc;
     }
     
    -static int smc_create(struct net *net, struct socket *sock, int protocol,
    -		      int kern)
    -{
    -	return __smc_create(net, sock, protocol, kern, NULL);
    -}
    -
     static const struct net_proto_family smc_sock_family_ops = {
     	.family	= PF_SMC,
     	.owner	= THIS_MODULE,
     	.create	= smc_create,
     };
     
    -static int smc_ulp_init(struct sock *sk)
    -{
    -	struct socket *tcp = sk->sk_socket;
    -	struct net *net = sock_net(sk);
    -	struct socket *smcsock;
    -	int protocol, ret;
    -
    -	/* only TCP can be replaced */
    -	if (tcp->type != SOCK_STREAM || sk->sk_protocol != IPPROTO_TCP ||
    -	    (sk->sk_family != AF_INET && sk->sk_family != AF_INET6))
    -		return -ESOCKTNOSUPPORT;
    -	/* don't handle wq now */
    -	if (tcp->state != SS_UNCONNECTED || !tcp->file || tcp->wq.fasync_list)
    -		return -ENOTCONN;
    -
    -	if (sk->sk_family == AF_INET)
    -		protocol = SMCPROTO_SMC;
    -	else
    -		protocol = SMCPROTO_SMC6;
    -
    -	smcsock = sock_alloc();
    -	if (!smcsock)
    -		return -ENFILE;
    -
    -	smcsock->type = SOCK_STREAM;
    -	__module_get(THIS_MODULE); /* tried in __tcp_ulp_find_autoload */
    -	ret = __smc_create(net, smcsock, protocol, 1, tcp);
    -	if (ret) {
    -		sock_release(smcsock); /* module_put() which ops won't be NULL */
    -		return ret;
    -	}
    -
    -	/* replace tcp socket to smc */
    -	smcsock->file = tcp->file;
    -	smcsock->file->private_data = smcsock;
    -	smcsock->file->f_inode = SOCK_INODE(smcsock); /* replace inode when sock_close */
    -	smcsock->file->f_path.dentry->d_inode = SOCK_INODE(smcsock); /* dput() in __fput */
    -	tcp->file = NULL;
    -
    -	return ret;
    -}
    -
    -static void smc_ulp_clone(const struct request_sock *req, struct sock *newsk,
    -			  const gfp_t priority)
    -{
    -	struct inet_connection_sock *icsk = inet_csk(newsk);
    -
    -	/* don't inherit ulp ops to child when listen */
    -	icsk->icsk_ulp_ops = NULL;
    -}
    -
    -static struct tcp_ulp_ops smc_ulp_ops __read_mostly = {
    -	.name		= "smc",
    -	.owner		= THIS_MODULE,
    -	.init		= smc_ulp_init,
    -	.clone		= smc_ulp_clone,
    -};
    -
     unsigned int smc_net_id;
     
     static __net_init int smc_net_init(struct net *net)
    @@ -3589,16 +3516,10 @@ static int __init smc_init(void)
     		pr_err("%s: ib_register fails with %d\n", __func__, rc);
     		goto out_sock;
     	}
    -
    -	rc = tcp_register_ulp(&smc_ulp_ops);
    -	if (rc) {
    -		pr_err("%s: tcp_ulp_register fails with %d\n", __func__, rc);
    -		goto out_ib;
    -	}
     	rc = smc_inet_init();
     	if (rc) {
     		pr_err("%s: smc_inet_init fails with %d\n", __func__, rc);
    -		goto out_ulp;
    +		goto out_ib;
     	}
     	rc = bpf_smc_hs_ctrl_init();
     	if (rc) {
    @@ -3610,8 +3531,6 @@ static int __init smc_init(void)
     	return 0;
     out_inet:
     	smc_inet_exit();
    -out_ulp:
    -	tcp_unregister_ulp(&smc_ulp_ops);
     out_ib:
     	smc_ib_unregister_client();
     out_sock:
    @@ -3647,7 +3566,6 @@ static void __exit smc_exit(void)
     {
     	static_branch_disable(&tcp_have_smc);
     	smc_inet_exit();
    -	tcp_unregister_ulp(&smc_ulp_ops);
     	sock_unregister(PF_SMC);
     	smc_core_exit();
     	smc_ib_unregister_client();
    @@ -3672,7 +3590,6 @@ MODULE_AUTHOR("Ursula Braun <ubraun@linux.vnet.ibm.com>");
     MODULE_DESCRIPTION("smc socket address family");
     MODULE_LICENSE("GPL");
     MODULE_ALIAS_NETPROTO(PF_SMC);
    -MODULE_ALIAS_TCP_ULP("smc");
     /* 256 for IPPROTO_SMC and 1 for SOCK_STREAM */
     MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 256, 1);
     #if IS_ENABLED(CONFIG_IPV6)
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

No source-code context for this CVE — mechanics is only generated when we can read the actual fix diff. Without that, the four sections (root cause, attack vector, affected code, fix) would be speculation rather than analysis.

References

2

News mentions

1