summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSharath Srinivasan <sharath.srinivasan@oracle.com>2026-07-29 21:16:28 -0700
committerJakub Kicinski <kuba@kernel.org>2026-08-04 18:00:58 -0700
commiteb8a59a17f4a8b6f2afb4a8063e99dd96cc3fab0 (patch)
treeb6e67c0de15283fd1c05ecafaa46e28fbd37b1b7
parent9079adef042c1e7a6141dcdfd3041acd30607297 (diff)
downloadlinux-eb8a59a17f4a8b6f2afb4a8063e99dd96cc3fab0.tar.gz
linux-eb8a59a17f4a8b6f2afb4a8063e99dd96cc3fab0.zip
net/rds: fix rds_message leak in the rds_send_xmit() drop path
When rds_send_xmit() picks the next message off cp_send_queue it takes its own reference with rds_message_addref(). If the message then hits the never-retransmit check (RDS_MSG_FLUSH, or an RDMA op that was already retransmitted), it is moved to the local to_be_dropped list and that reference is dropped after the batch. However, if RDS_MSG_ON_CONN has already been cleared, the message is not added to to_be_dropped and the reference taken above is never dropped: cp_xmit_rm has not been set at this point, so the loop simply abandons rm and the rds_message (and everything it pins: pages, MRs, notifiers) leaks after an RDMA error. The only other places that clear RDS_MSG_ON_CONN are rds_send_path_drop_acked() and rds_send_drop_to(), and both can run while rds_send_xmit() has dropped cp_lock between moving the message to cp_retrans and re-taking the lock in the never-retransmit check: rds_send_path_drop_acked() can ack away a message that already sat on cp_retrans - the RDS_MSG_RETRANSMITTED case above - and rds_send_drop_to() runs on socket close. Both unlink the message under cp_lock and put their own reference, leaving the xmit-path reference stranded. Drop the reference directly in that case. This mirrors Oracle UEK commit "net/rds: fix rds_message memleak in rds_send_xmit". Signed-off-by: Gerd Rausch <gerd.rausch@oracle.com> Signed-off-by: Sharath Srinivasan <sharath.srinivasan@oracle.com> [achender: port to net-next; update commit message, checkpatch nits] Signed-off-by: Allison Henderson <achender@kernel.org> Link: https://patch.msgid.link/20260730041629.3512480-4-achender@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--net/rds/send.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/net/rds/send.c b/net/rds/send.c
index 6a567c97a999..309021e0cc9b 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -339,9 +339,21 @@ restart:
(rm->rdma.op_active &&
test_bit(RDS_MSG_RETRANSMITTED, &rm->m_flags))) {
spin_lock_irqsave(&cp->cp_lock, flags);
- if (test_and_clear_bit(RDS_MSG_ON_CONN, &rm->m_flags))
- list_move(&rm->m_conn_item, &to_be_dropped);
- spin_unlock_irqrestore(&cp->cp_lock, flags);
+ if (test_and_clear_bit(RDS_MSG_ON_CONN,
+ &rm->m_flags)) {
+ /* our ref is put after the batch */
+ list_move(&rm->m_conn_item,
+ &to_be_dropped);
+ spin_unlock_irqrestore(&cp->cp_lock,
+ flags);
+ } else {
+ /* already off the conn list; drop
+ * the ref taken above ourselves
+ */
+ spin_unlock_irqrestore(&cp->cp_lock,
+ flags);
+ rds_message_put(rm);
+ }
continue;
}