From: Allison Henderson <achender@kernel.org>
To: netdev@vger.kernel.org, linux-rdma@vger.kernel.org,
pabeni@redhat.com, edumazet@google.com, kuba@kernel.org,
horms@kernel.org
Cc: achender@kernel.org
Subject: [PATCH net v3 1/2] net/rds: keep the connected peer's scope id apart from the bound one
Date: Sat, 3 Oct 2026 09:35:25 -0700 [thread overview]
Message-ID: <20261003163526.250805-2-achender@kernel.org> (raw)
In-Reply-To: <20261003163526.250805-1-achender@kernel.org>
rds_connect() has nowhere to keep the scope of a link-local peer, so
it stores it in rs_bound_scope_id, the scope of the socket's own
bound address, for rds_bind() to check a later link-local bind
against. That field is then also what a send without a destination
uses as the request's scope, and what a later bind() overwrites:
rds_add_bound() stores the bound address's scope unconditionally,
which for a non-link-local address is 0.
So after connect(fe80::x%ifA) followed by bind(global), a send() with
no destination asks for fe80::x with scope 0. rds_conn_lookup() keys
on the interface, so that finds or creates a connection with c_dev_if
0, which the TCP transport then tries to connect through
sin6_scope_id 0 and tcp_v6_connect() rejects for a link-local peer:
the connected socket's data is queued on a connection that can never
come up. In the other order, bind(global) then connect(fe80::x%ifB),
the connect leaves a global-bound socket with rs_bound_scope_id ifB,
so sends to other link-local peers are refused as off-link and sends
to global peers inherit a meaningless interface.
Give the connected peer its own rs_conn_scope_id. rds_connect()
records it there and leaves the bound scope alone, rds_bind()'s
connected-socket check compares against it, and the destination-less
send takes its scope from it.
Fixes: 1e2b44e78eea ("rds: Enable RDS IPv6 support")
Assisted-by: Claude-Code:claude-fable-5
Signed-off-by: Allison Henderson <achender@kernel.org>
---
net/rds/af_rds.c | 12 ++++++++----
net/rds/bind.c | 4 ++--
net/rds/rds.h | 2 ++
net/rds/send.c | 2 +-
4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c
index d5defe9172e3..ba726782addf 100644
--- a/net/rds/af_rds.c
+++ b/net/rds/af_rds.c
@@ -572,6 +572,7 @@ static int rds_connect(struct socket *sock, struct sockaddr_unsized *uaddr,
}
ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &rs->rs_conn_addr);
rs->rs_conn_port = sin->sin_port;
+ rs->rs_conn_scope_id = 0;
break;
#if IS_ENABLED(CONFIG_IPV6)
@@ -616,11 +617,14 @@ static int rds_connect(struct socket *sock, struct sockaddr_unsized *uaddr,
ret = -EINVAL;
break;
}
- /* Remember the connected address scope ID. It will
- * be checked against the binding local address when
- * the socket is bound.
+ /* Remember the connected address scope ID. It is
+ * checked against the binding local address when
+ * the socket is bound, and gives a send without a
+ * destination its scope.
*/
- rs->rs_bound_scope_id = sin6->sin6_scope_id;
+ rs->rs_conn_scope_id = sin6->sin6_scope_id;
+ } else {
+ rs->rs_conn_scope_id = 0;
}
rs->rs_conn_addr = sin6->sin6_addr;
rs->rs_conn_port = sin6->sin6_port;
diff --git a/net/rds/bind.c b/net/rds/bind.c
index f800d920d969..3ac59cd512a2 100644
--- a/net/rds/bind.c
+++ b/net/rds/bind.c
@@ -233,8 +233,8 @@ int rds_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int addr_len)
* non-link local address (scope_id is 0).
*/
if (!ipv6_addr_any(&rs->rs_conn_addr) && scope_id &&
- rs->rs_bound_scope_id &&
- scope_id != rs->rs_bound_scope_id) {
+ rs->rs_conn_scope_id &&
+ scope_id != rs->rs_conn_scope_id) {
ret = -EINVAL;
goto out;
}
diff --git a/net/rds/rds.h b/net/rds/rds.h
index 2db49573dacd..9b1ffc49c0a6 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -646,6 +646,8 @@ struct rds_sock {
struct in6_addr rs_conn_addr;
#define rs_conn_addr_v4 rs_conn_addr.s6_addr32[3]
__be16 rs_conn_port;
+ /* scope of rs_conn_addr when it is link-local, 0 otherwise */
+ __u32 rs_conn_scope_id;
struct rds_transport *rs_transport;
/*
diff --git a/net/rds/send.c b/net/rds/send.c
index 1afa981e5c06..9380b67675bd 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -1256,7 +1256,7 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
lock_sock(sk);
daddr = rs->rs_conn_addr;
dport = rs->rs_conn_port;
- scope_id = rs->rs_bound_scope_id;
+ scope_id = rs->rs_conn_scope_id;
release_sock(sk);
}
--
2.25.1
next prev parent reply other threads:[~2026-10-03 16:35 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-03 16:35 [PATCH net v3 0/2] net/rds: scope-aware sendmsg connection cache Allison Henderson
2026-10-03 16:35 ` Allison Henderson [this message]
2026-10-04 16:35 ` [PATCH net v3 1/2] net/rds: keep the connected peer's scope id apart from the bound one sashiko-bot
2026-10-04 16:41 ` netdev-bot+sashiko
2026-10-03 16:35 ` [PATCH net v3 2/2] net/rds: include the scope id in the sendmsg connection cache check Allison Henderson
2026-10-04 16:35 ` sashiko-bot
2026-10-04 16:41 ` netdev-bot+sashiko
2026-10-03 16:39 ` [PATCH net v3 0/2] net/rds: scope-aware sendmsg connection cache netdev-bot+sinfo
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=20261003163526.250805-2-achender@kernel.org \
--to=achender@kernel.org \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.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.