mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Jaeyeong Lee <lee@jaeyeong.cc>
To: Bernard Metzler <bernard.metzler@linux.dev>
Cc: Jason Gunthorpe <jgg@ziepe.ca>, Leon Romanovsky <leon@kernel.org>,
	linux-rdma@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2] RDMA/siw: Fix early peer close handling on listeners
Date: Wed, 04 Nov 2026 10:10:00 +0000	[thread overview]
Message-ID: <20261104100953.125140-1-lee@jaeyeong.cc> (raw)

A TCP child socket inherits the listener callbacks and sk_user_data before
kernel_accept() associates it with a new connection endpoint. If the peer
closes during this window, siw_cm_llp_state_change() queues a PEER_CLOSE
work item against the listening endpoint.

The worker releases that endpoint without removing it from the listener
list. A later listener teardown then walks the dangling entry, causing a
use-after-free in siw_destroy_listen().

Ignoring close notifications while the endpoint is LISTENING is not
sufficient. The endpoint remains IDLE for a short interval after listen()
starts accepting connections, and a close delivered before the accepted
socket is handed to its new endpoint would otherwise be lost.

Ignore close notifications from unaccepted child sockets during the IDLE
interval as well. During accept, serialize the endpoint handoff with TCP
state changes and reject a child that has already reached TCP_CLOSE or
TCP_CLOSE_WAIT. Live accepted sockets continue through the normal close
path.

The issue was found by static analysis. It was reproduced with SIW over
loopback in an x86_64 QEMU guest. KASAN reported the listener endpoint
use-after-free on the unpatched kernel. Tests covering RST before accept,
an MPA request followed by FIN, and an extended post-listen IDLE window
completed without KASAN or lockdep reports after this change.

Fixes: 6c52fdc244b5 ("rdma/siw: connection management")
Cc: stable@vger.kernel.org
Signed-off-by: Jaeyeong Lee <lee@jaeyeong.cc>
---
Changes in v2:
- Cover the IDLE interval between listen() and the LISTENING transition.
- Serialize accepted-socket handoff and reject an already closed child.

 drivers/infiniband/sw/siw/siw_cm.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/sw/siw/siw_cm.c b/drivers/infiniband/sw/siw/siw_cm.c
index ed49818793dde..92fcbcabb5984 100644
--- a/drivers/infiniband/sw/siw/siw_cm.c
+++ b/drivers/infiniband/sw/siw/siw_cm.c
@@ -973,6 +973,7 @@ static void siw_accept_newconn(struct siw_cep *cep)
 	struct socket *s = cep->sock;
 	struct socket *new_s = NULL;
 	struct siw_cep *new_cep = NULL;
+	bool peer_closed;
 	int rv = 0; /* debug only. should disappear */
 
 	if (cep->state != SIW_EPSTATE_LISTENING)
@@ -1009,11 +1010,23 @@ static void siw_accept_newconn(struct siw_cep *cep)
 	}
 	new_cep->sock = new_s;
 	siw_cep_get(new_cep);
-	new_s->sk->sk_user_data = new_cep;
 
 	if (siw_tcp_nagle == false)
 		tcp_sock_set_nodelay(new_s->sk);
+
+	lock_sock(new_s->sk);
+	write_lock_bh(&new_s->sk->sk_callback_lock);
 	new_cep->state = SIW_EPSTATE_AWAIT_MPAREQ;
+	new_s->sk->sk_user_data = new_cep;
+	peer_closed = new_s->sk->sk_state == TCP_CLOSE ||
+		      new_s->sk->sk_state == TCP_CLOSE_WAIT;
+	write_unlock_bh(&new_s->sk->sk_callback_lock);
+	release_sock(new_s->sk);
+
+	if (peer_closed) {
+		rv = -ECONNRESET;
+		goto error;
+	}
 
 	rv = siw_cm_queue_work(new_cep, SIW_CM_WORK_MPATIMEOUT);
 	if (rv)
@@ -1361,6 +1374,10 @@ static void siw_cm_llp_state_change(struct sock *sk)
 
 	case TCP_CLOSE:
 	case TCP_CLOSE_WAIT:
+		if (cep->state == SIW_EPSTATE_LISTENING ||
+		    (cep->state == SIW_EPSTATE_IDLE &&
+		     !READ_ONCE(sk->sk_socket)))
+			break;
 		if (cep->qp)
 			cep->qp->tx_ctx.tx_suspend = 1;
 		siw_cm_queue_work(cep, SIW_CM_WORK_PEER_CLOSE);
-- 
2.43.0



                 reply	other threads:[~2026-11-04 10:10 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20261104100953.125140-1-lee@jaeyeong.cc \
    --to=lee@jaeyeong.cc \
    --cc=bernard.metzler@linux.dev \
    --cc=jgg@ziepe.ca \
    --cc=leon@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    /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

all inboxes | Powered by JetHome®