All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hidayath Khan <hidayath@linux.ibm.com>
To: alibuda@linux.alibaba.com, dust.li@linux.alibaba.com,
	sidraya@linux.ibm.com, mjambigi@linux.ibm.com,
	andrew+netdev@lunn.ch
Cc: tonylu@linux.alibaba.com, guwen@linux.alibaba.com,
	davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, pasic@linux.ibm.com,
	hidayath@linux.ibm.com, linux-s390@vger.kernel.org,
	netdev@vger.kernel.org
Subject: [PATCH net] net/smc: drop the abort_work reference when the work is cancelled
Date: Thu,  6 Aug 2026 10:15:49 +0200	[thread overview]
Message-ID: <20260806081549.595001-1-hidayath@linux.ibm.com> (raw)

The schedulers of conn->abort_work hand a socket reference to the work
item and rely on it to give the reference back:

        sock_hold(&smc->sk); /* sock_put in abort_work */
        if (!queue_work(smc_close_wq, &conn->abort_work))
                sock_put(&smc->sk);

The queue_work() failure case is handled, but the cancellation case is
not. smc_conn_free() cancels a still-pending abort_work:

        if (current_work() != &conn->abort_work)
                cancel_work_sync(&conn->abort_work);

and discards the return value.  When cancel_work_sync() returns true the
work was queued but had not started, so smc_conn_abort_work() never runs
and its sock_put() never happens.  The reference is lost.

As in smc_switch_conns(), a leaked sk_refcnt means the smc_sock is never
destroyed: its buffers stay allocated and the network namespace reference
a user socket holds is never released, so the netns cannot be torn down.

smc_cdc_msg_validate() queues abort_work from the receive tasklet when a
peer sends a CDC message with an out-of-order sequence number, so a
remote peer combined with a concurrent local close is enough to reach it.

Drop the reference when the work is cancelled, matching the pattern
smc_close_cancel_work() already uses for conn->close_work:

        if (cancel_work_sync(&smc->conn.close_work))
                sock_put(sk);

The sock_put() is safe here: every caller of smc_conn_free() passes the
connection of a socket it holds a reference to, so this cannot release
the last one.

Fixes: b286a0651e44 ("net/smc: handle incoming CDC validation message")
Cc: stable@vger.kernel.org
Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com>
Signed-off-by: Hidayath Khan <hidayath@linux.ibm.com>
---
 net/smc/smc_core.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
index c0027d2fe4e8..dd9fffbe41e0 100644
--- a/net/smc/smc_core.c
+++ b/net/smc/smc_core.c
@@ -1254,6 +1254,7 @@ static void smc_buf_unuse(struct smc_connection *conn,
 /* remove a finished connection from its link group */
 void smc_conn_free(struct smc_connection *conn)
 {
+	struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
 	struct smc_link_group *lgr = conn->lgr;
 
 	if (!lgr || conn->freed)
@@ -1277,8 +1278,13 @@ void smc_conn_free(struct smc_connection *conn)
 		tasklet_kill(&conn->rx_tsklet);
 	} else {
 		smc_cdc_wait_pend_tx_wr(conn);
-		if (current_work() != &conn->abort_work)
-			cancel_work_sync(&conn->abort_work);
+		/* If the work was pending (cancel returns true) it never ran,
+		 * so the sock_hold taken by its scheduler was never released.
+		 */
+		if (current_work() != &conn->abort_work) {
+			if (cancel_work_sync(&conn->abort_work))
+				sock_put(&smc->sk);
+		}
 	}
 	if (!list_empty(&lgr->list)) {
 		smc_buf_unuse(conn, lgr); /* allow buffer reuse */

base-commit: 2b1c2bc2355fd59cc75045e42d9dc5470ef5fa9a
-- 
2.52.0


             reply	other threads:[~2026-08-06  8:16 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-06  8:15 Hidayath Khan [this message]
2026-08-06  9:20 ` [PATCH net] net/smc: drop the abort_work reference when the work is cancelled Dust Li
2026-08-07  8:16 ` sashiko-bot
2026-08-10 23:19 ` Jakub Kicinski

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=20260806081549.595001-1-hidayath@linux.ibm.com \
    --to=hidayath@linux.ibm.com \
    --cc=alibuda@linux.alibaba.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=dust.li@linux.alibaba.com \
    --cc=edumazet@google.com \
    --cc=guwen@linux.alibaba.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=mjambigi@linux.ibm.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=pasic@linux.ibm.com \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.