From: Paolo Abeni <pabeni@redhat.com>
To: Chuyf26@linux.alibaba.com
Cc: alibuda@linux.alibaba.com, dust.li@linux.alibaba.com,
sidraya@linux.ibm.com, mjambigi@linux.ibm.com,
tonylu@linux.alibaba.com, guwen@linux.alibaba.com,
netdev@vger.kernel.org, linux-rdma@vger.kernel.org,
linux-s390@vger.kernel.org
Subject: Re: [PATCH v2] net/smc: release the internal TCP sock on IPPROTO_SMC socket creation failure
Date: Thu, 20 Aug 2026 13:12:29 +0200 [thread overview]
Message-ID: <20260820111229.153086-1-pabeni@redhat.com> (raw)
In-Reply-To: <20260813060456.b48HqF9m6NTfFXvq_PL9w_Ih493OogqAqxfAHAfU74A@z>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://netdev-ai.bots.linux.dev/sashiko/
---
net/smc: release the internal TCP sock on IPPROTO_SMC socket creation failure
This adds a .destroy hook to smc_inet_prot and smc_inet6_prot that calls
smc_clcsock_release(), so the internal TCP sock created by
smc_inet_init_sock() is freed when socket creation fails after proto->init
has run. It also stores NULL into smc->clcsock at the top of
smc_inet_init_sock().
A couple of questions below.
> diff --git a/net/smc/smc_inet.c b/net/smc/smc_inet.c
> index a94084b4a498..b94a19499986 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,
[ ... ]
> @@ -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;
[Severity: Low]
Is the premise of this comment (and of the matching changelog paragraph,
"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") correct?
sk_alloc() always adds __GFP_ZERO, and sk_prot_alloc() then clears the
whole protocol object:
net/core/sock.c:sk_alloc() {
sk = sk_prot_alloc(prot, priority | __GFP_ZERO, family);
...
}
net/core/sock.c:sk_prot_alloc() {
sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO);
if (!sk)
return sk;
if (want_init_on_alloc(priority))
sk_prot_clear_nulls(sk, prot->obj_size);
...
}
sk_prot_clear_nulls() memsets everything except sk_node.next, and
smc_sock.clcsock sits well past sk_node, so isn't clcsock already NULL on
entry to .init even for a recycled SLAB_TYPESAFE_BY_RCU object, making this
store dead code?
The second sentence of the comment also seems hard to satisfy: the mutex
that smc_clcsock_release() takes is only initialized later, inside
smc_sk_init():
net/smc/af_smc.c:smc_sk_init() {
...
mutex_init(&smc->clcsock_release_lock);
...
}
So if .destroy really could run before .init completed, wouldn't
smc_clcsock_release() lock an uninitialized mutex regardless of this NULL
store? Could the comment and changelog paragraph be dropped or reworded to
match what the code actually guarantees?
>
> /* 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));
> +}
[Severity: High]
Can this free the internal TCP socket while the SMC sock is still on the
SMC diag hash list?
sk_common_release() runs .destroy before .unhash:
net/core/sock.c:sk_common_release() {
if (sk->sk_prot->destroy)
sk->sk_prot->destroy(sk);
...
sk->sk_prot->unhash(sk);
...
}
and the sk was already inserted into smc_v4_hashinfo/smc_v6_hashinfo by
smc_sk_init() -> sk->sk_prot->hash(sk) == smc_hash_sk() before
smc_create_clcsk() ran, so when smc_inet_destroy_sock() calls
smc_clcsock_release() the sock is still visible to the diag dumper.
The reader side walks that same hashinfo holding only the hashinfo rwlock,
and does an unlocked check-then-dereference of smc->clcsock:
net/smc/smc_diag.c:smc_diag_dump_proto() {
read_lock(&prot->h.smc_hash->lock);
head = &prot->h.smc_hash->ht;
...
sk_for_each(sk, head) {
...
}
net/smc/smc_diag.c:smc_diag_msg_common_fill() {
...
if (!smc->clcsock)
return;
r->id.idiag_sport = htons(smc->clcsock->sk->sk_num);
r->id.idiag_dport = smc->clcsock->sk->sk_dport;
...
}
while the writer holds only clcsock_release_lock:
net/smc/smc_close.c:smc_clcsock_release() {
mutex_lock(&smc->clcsock_release_lock);
if (smc->clcsock) {
tcp = smc->clcsock;
smc->clcsock = NULL;
sock_release(tcp);
}
...
}
With an empty lockset intersection, can a concurrent AF_SMC diag dump (for
example "ss --smc", which has no capability check in
smc_diag_handler_dump()) re-read smc->clcsock as NULL after the NULL check
and oops, or dereference the just-released struct socket / tcp_sock and copy
freed memory into the netlink reply?
The existing teardown path unhashes first and only then drops the clcsock:
net/smc/af_smc.c:__smc_release() {
sk->sk_prot->unhash(sk);
if (sk->sk_state == SMC_CLOSED) {
if (smc->clcsock) {
release_sock(sk);
smc_clcsock_release(smc);
...
}
Would it be better to keep that ordering here, for instance by unhashing
before releasing the clcsock in the destroy path, or by taking
clcsock_release_lock in the diag reader?
The lockless clcsock read in smc_diag is itself older than this patch (see
also smc_close_active_abort() and smc_close_passive_work()), but on the
socket-creation-failure path nothing was freed while the sk was hashed
before this change, since the clcsock was simply leaked.
>
> int __init smc_inet_init(void)
> {
> int rc;
--
This is an AI-generated review.
next prev parent reply other threads:[~2026-08-20 11:12 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260812071543.C94FD349CD8@smtp.subspace.kernel.org>
2026-08-12 14:44 ` [PATCH] net/smc: release the internal TCP sock on IPPROTO_SMC socket creation failure Sidraya Jayagond
2026-08-13 6:04 ` [PATCH v2] " Chuyf26
2026-08-20 11:12 ` Paolo Abeni [this message]
[not found] ` <202608130604.67D5j4VU1508130@pps.reinject>
2026-08-13 6:25 ` Sidraya Jayagond
2026-08-12 7:15 [PATCH] " Chuyf26
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260820111229.153086-1-pabeni@redhat.com \
--to=pabeni@redhat.com \
--cc=Chuyf26@linux.alibaba.com \
--cc=alibuda@linux.alibaba.com \
--cc=dust.li@linux.alibaba.com \
--cc=guwen@linux.alibaba.com \
--cc=linux-rdma@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=mjambigi@linux.ibm.com \
--cc=netdev@vger.kernel.org \
--cc=sidraya@linux.ibm.com \
--cc=tonylu@linux.alibaba.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox