Thread (26 messages) flat view 26 messages, 2 authors, 1d ago
WARM1d

Revision v3 of 2 in this series.

Revisions (2)
  1. v3 current
  2. v4 [diff vs current]

[PATCH net-next v3 10/13] net/rds: tcp: don't attach an accepted socket to a connection being destroyed

From: Allison Henderson <achender@kernel.org>
Date: 2026-09-14 03:37:25
Also in: linux-rdma
Subsystem: networking [general], rds - reliable datagram sockets, the rest · Maintainers: "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Allison Henderson, Linus Torvalds

rds_tcp_accept_one() looks the connection up, claims a path with a
DOWN -> CONNECTING transition and installs the accepted socket on it.
A connection whose destroy has begun is quiesced - its paths are DOWN
and its old sockets released - but stays allocated while a reference
holder is still around, and rds_conn_create() hands out exactly such
a connection with a reference of its own.  The path claim then
succeeds, the socket is installed, the accept drops its reference,
and when the last holder goes away the path is freed with the
socket's sk_user_data still pointing at it: the next byte from the
peer runs the socket callbacks against freed memory, and nothing ever
releases the socket.

Refuse the accept for a connection whose destroy has begun, the same
way an unexpected path state is refused: drop the path claim and
reset the new socket.  The peer reconnects with backoff and, by then,
either finds a fresh connection or nothing listening.

Assisted-by: Claude-Code:claude-fable-5
Signed-off-by: Allison Henderson <achender@kernel.org>
---
 net/rds/tcp_listen.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c
index dcac10a91a67..e22ea9ca8c1c 100644
--- a/net/rds/tcp_listen.c
+++ b/net/rds/tcp_listen.c
@@ -278,7 +278,15 @@ int rds_tcp_accept_one(struct rds_tcp_net *rtn)
 	cp = rs_tcp->t_cpath;
 	conn_state = rds_conn_path_state(cp);
 	WARN_ON(conn_state == RDS_CONN_UP);
-	if (conn_state != RDS_CONN_CONNECTING && conn_state != RDS_CONN_ERROR) {
+	/* A connection whose destroy has begun has been quiesced and is
+	 * only waiting for its last reference: its paths sit in
+	 * RDS_CONN_DOWN, which rds_tcp_accept_one_path() happily claims.
+	 * Installing a socket on it would leave sk_user_data pointing
+	 * at a path that is about to be freed.
+	 */
+	if (rds_destroy_pending(conn) ||
+	    (conn_state != RDS_CONN_CONNECTING &&
+	     conn_state != RDS_CONN_ERROR)) {
 		rds_conn_path_drop(cp, 0);
 		goto rst_nsk;
 	}
-- 
2.25.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help