Thread (1 message) 1 message, 1 author, 4d ago

Re: [PATCH v2] net/smc: release the internal TCP sock on IPPROTO_SMC socket creation failure

From: Sidraya Jayagond <sidraya@linux.ibm.com>
Date: 2026-08-13 06:25:35
Also in: linux-rdma, linux-s390


On 13/08/26 11:34 am, Chuyf26 wrote:
quoted hunk
IPPROTO_SMC sockets create an internal TCP sock ("clcsock") from the
proto->init hook. When socket creation fails after proto->init has
run - e.g. a cgroup BPF program attached to BPF_CGROUP_INET_SOCK_CREATE
denies the socket - sk_common_release() only invokes sk_prot->destroy
if it is set, but neither smc_inet_prot nor smc_inet6_prot defines it,
and smc_destruct() returns early unless sk_state is SMC_CLOSED. As a
result, every failing socket(AF_INET, SOCK_STREAM, IPPROTO_SMC) call
leaks one tcp_sock, so an unprivileged task able to attach a deny-all
BPF_CGROUP_INET_SOCK_CREATE program to its own cgroup can grow kernel
memory unboundedly.

Add a .destroy hook to both protos that releases the clcsock via
smc_clcsock_release(), which is safe here because it skips a NULL
clcsock under clcsock_release_lock. Also initialize clcsock to NULL
when setting the sock up: the smc_sock slab is SLAB_TYPESAFE_BY_RCU,
so recycled objects are not zeroed.

Fixes: d25a92ccae6b ("net/smc: Introduce IPPROTO_SMC")
Reported-by: Abaci <redacted>
Assisted-by: abaci:qwen3.8-max
Signed-off-by: Chuyf26 <redacted>
---
 net/smc/smc_inet.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
diff --git a/net/smc/smc_inet.c b/net/smc/smc_inet.c
index a94084b..b94a194 100644
--- a/net/smc/smc_inet.c
+++ b/net/smc/smc_inet.c
@@ -15,13 +15,16 @@
 
 #include "smc_inet.h"
 #include "smc.h"
+#include "smc_close.h"
 
 static int smc_inet_init_sock(struct sock *sk);
+static void smc_inet_destroy_sock(struct sock *sk);
 
 static struct proto smc_inet_prot = {
 	.name		= "INET_SMC",
 	.owner		= THIS_MODULE,
 	.init		= smc_inet_init_sock,
+	.destroy	= smc_inet_destroy_sock,
 	.hash		= smc_hash_sk,
 	.unhash		= smc_unhash_sk,
 	.release_cb	= smc_release_cb,
@@ -68,6 +71,7 @@ static struct proto smc_inet6_prot = {
 	.name		= "INET6_SMC",
 	.owner		= THIS_MODULE,
 	.init		= smc_inet_init_sock,
+	.destroy	= smc_inet_destroy_sock,
 	.hash		= smc_hash_sk,
 	.unhash		= smc_unhash_sk,
 	.release_cb	= smc_release_cb,
@@ -109,6 +113,14 @@ static struct inet_protosw smc_inet6_protosw = {
 static int smc_inet_init_sock(struct sock *sk)
 {
 	struct net *net = sock_net(sk);
+	struct smc_sock *smc = smc_sk(sk);
+
+	/*
+	 * The smc_sock slab is SLAB_TYPESAFE_BY_RCU and recycled objects
+	 * are not zeroed. .destroy may run even if .init never completed,
+	 * so make sure smc_clcsock_release() sees a valid clcsock.
+	 */
+	smc->clcsock = NULL;
 
 	/* init common smc sock */
 	smc_sk_init(net, sk, IPPROTO_SMC);
@@ -116,6 +128,17 @@ static int smc_inet_init_sock(struct sock *sk)
 	return smc_create_clcsk(net, sk, sk->sk_family);
 }
 
+static void smc_inet_destroy_sock(struct sock *sk)
+{
+	/*
+	 * If inet_create()/inet6_create() fail after .init has created the
+	 * internal TCP sock (e.g. rejected by a cgroup BPF program),
+	 * sk_common_release() ends up here. Release the TCP sock, otherwise
+	 * it leaks on every failed IPPROTO_SMC socket() call.
+	 */
+	smc_clcsock_release(smc_sk(sk));
+}
+
 int __init smc_inet_init(void)
 {
 	int rc;
Thank you for fixing this.
Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com>
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help