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 2/3] net/rds: hold the socket while an rds_mr references it
Date: Fri, 10 Jul 2026 19:51:17 -0700 [thread overview]
Message-ID: <20260711025118.2449428-3-achender@kernel.org> (raw)
In-Reply-To: <20260711025118.2449428-1-achender@kernel.org>
From: Håkon Bugge <haakon.bugge@oracle.com>
Each rds_mr stores a bare back pointer to the socket that created it
(mr->r_sock) but takes no reference on it. When the mr is destroyed it
references the rs. Hence, provisions must be made to avoid the rs
being destroyed before all mrs referencing it have been destroyed.
The MR itself is refcounted, and in-flight messages legitimately hold
MR krefs that can outlive the socket: rds_release() drops the rb-tree
references via rds_rdma_drop_keys(), but a send completion arriving
afterwards drops the final message reference from the CQ handler and
ends up in
rds_message_purge()
__rds_put_mr_final()
rds_destroy_mr() -> takes rs->rs_rdma_lock
dereferencing a socket that may already have been freed.
Oracle UEK fixed the same use-after-free ("rds: Add proper refcnt when
an RDS MR references an RDS Socket") after seeing crashes of the form:
PF: supervisor write access in kernel mode
_raw_spin_lock_irqsave+0x4a/0x6a
__rds_put_mr_final+0x2c/0xe0 [rds]
rds_message_purge+0x13c/0x150 [rds]
rds_message_put+0x39/0x54 [rds]
rds_ib_send_cqe_handler+0x147/0x3dd [rds_rdma]
To fix this, take a socket reference when an MR is created and drop it
when the final MR kref goes away. The reference cycle is broken by
rds_release(), which always runs rds_rdma_drop_keys() on close. So the
socket reference held by an MR never prevents release, it only delays
sk_free() until the last MR user is done.
In the on-demand-paging path in rds_cmsg_rdma_args(), we take the reference
after the transport get_mr() call succeeds. This is because its error
path frees the MR with kfree() directly rather than through
__rds_put_mr_final(). So an early hold in this case would leak the socket
reference.
Fixes: eff5f53bef75 ("RDS: RDMA support")
Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
[achender: port to net-next (sock_hold/sock_put in place of the UEK
rds_sock_addref/rds_sock_put helpers); also balance the reference on
the rds_cmsg_rdma_args() ODP path; update commit message]
Assisted-by: Claude-Code:claude-fable-5
Signed-off-by: Allison Henderson <achender@kernel.org>
---
net/rds/rdma.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/net/rds/rdma.c b/net/rds/rdma.c
index 201cbe38fa893..fe221968f3fe7 100644
--- a/net/rds/rdma.c
+++ b/net/rds/rdma.c
@@ -117,6 +117,7 @@ void __rds_put_mr_final(struct kref *kref)
struct rds_mr *mr = container_of(kref, struct rds_mr, r_kref);
rds_destroy_mr(mr);
+ sock_put(rds_rs_to_sk(mr->r_sock));
kfree(mr);
}
@@ -243,7 +244,11 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
kref_init(&mr->r_kref);
RB_CLEAR_NODE(&mr->r_rb_node);
mr->r_trans = rs->rs_transport;
+ /* The MR can outlive its socket: a socket reference is held
+ * until the final kref is dropped in __rds_put_mr_final().
+ */
mr->r_sock = rs;
+ sock_hold(rds_rs_to_sk(rs));
if (args->flags & RDS_RDMA_USE_ONCE)
mr->r_use_once = 1;
@@ -755,6 +760,10 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
}
rdsdebug("Need odp; local_odp_mr %p trans_private %p\n",
local_odp_mr, local_odp_mr->r_trans_private);
+ /* From here on the MR is torn down through
+ * __rds_put_mr_final(), which drops this reference.
+ */
+ sock_hold(rds_rs_to_sk(rs));
op->op_odp_mr = local_odp_mr;
op->op_odp_addr = iov->addr;
}
--
2.25.1
next prev parent reply other threads:[~2026-07-11 2:51 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-11 2:51 [PATCH net 0/3] net/rds: Bug fix ports Allison Henderson
2026-07-11 2:51 ` [PATCH net 1/3] net/rds: don't use unpin_user_pages_dirty_lock() from atomic context Allison Henderson
2026-07-11 2:51 ` Allison Henderson [this message]
2026-07-11 2:51 ` [PATCH net 3/3] net/rds: fix rds_message leak in the rds_send_xmit() drop path Allison Henderson
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=20260711025118.2449428-3-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox