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
Subject: Re: [PATCH net-next v6 00/12] net/rds: make connection lifetime reference-counted
Date: Tue, 22 Sep 2026 09:47:43 -0700 [thread overview]
Message-ID: <d61a18374d74c7fca6448692b86e7351bd2ad080.camel@kernel.org> (raw)
In-Reply-To: <20260922164318.447049-1-achender@kernel.org>
On Tue, 2026-09-22 at 09:43 -0700, Allison Henderson wrote:
> Hi all,
>
Resend of v6 sent by mistake, please ignore the resend.
Apologies for the spam!
Thanks!
Allison
> This is v6 of the connection-lifetime set (v1 at [1], v2 at [2],
> v3 at [3], v4 at [6], v5 at [7]), following
> "net/rds: own the fastpath locks across connection teardown", which is
> in net-next. It is targeted at net-next: although the series fixes
> real use-after-frees (one syzbot report and one report from Chengfeng
> Ye below), it does so by reworking connection lifetime rather than
> patching the individual crash sites, and that rework is too invasive
> for net.
>
> rds_conn_destroy() frees the connection, its paths and its workqueues
> on the spot, relying on the documented assumption that "no one else is
> referencing the connection". That assumption stopped being true a
> long time ago: connections are destroyed on netns teardown and on a
> protocol-version mismatch as well as on rmmod, while pointers to them
> still live in socket rs_conn caches, congestion-map conn lists, CM
> callbacks and workers, and - for as long as an application leaves data
> unread - in every rds_incoming sitting on a receive queue. No single
> Fixes: commit covers the rot, so the series carries Reported-by tags
> where there are concrete reports instead.
>
> Patch 1 fixes rds_ib_conn_free() re-enabling interrupts under
> a caller's irqsave lock.
>
> Patch 2 makes the passive-connection exits of __rds_conn_create()
> undo conn_alloc() the same way the lost-race exit does, through one
> helper (a refactor: the passive twin only exists for IB, so nothing
> leaked there). Both are first in the series because the
> reference-counted teardown calls conn_free() from more places.
>
> Patch 3 guards the five work-arming sites that never tested
> rds_destroy_pending(): two IB completion paths, the IB recv refill,
> the TCP accept kick and the multipath reconnect in sendmsg.
>
> Patch 4 gives the connection its own destroy-in-progress marker.
> With f97d8c7bab78 in net-next there is no single-connection destroy
> left for the old predicate to miss, but the later patches need the
> precise answer: the IB unload re-sweep hands a connection to
> rds_conn_destroy() more than once, and the passive-twin creation
> must refuse a parent whose destroy has begun.
> Based on UEK commits:
> e2f5005adf63 net/rds: Add krefs to struct rds_connection
> https://github.com/oracle/linux-uek/commit/e2f5005adf63
>
> 6c53ef92f46e net/rds: Merge uses of conn->c_destroy_in_prog & RDS_DESTROY_PENDING
> https://github.com/oracle/linux-uek/commit/6c53ef92f46e
>
> Patch 5 splits rds_conn_destroy() into a synchronous quiesce and a
> kref-governed free.
> Based on UEK commits:
> 2c8569e4c880 ("net/rds: Add krefs to struct rds_connection").
> https://github.com/oracle/linux-uek/commit/2c8569e4c880
>
> Patch 6 makes each transport's exit path wait for its connections to
> actually be freed before the module goes away. The wait is
> unbounded and warns every ten seconds: a connection reference can be
> held for an application-controlled time (unread data), so a timeout
> would only move the use-after-free from freed memory to unloaded
> module text. rmmod blocking while data is queued and unread is the
> historical RDS contract. For IB the wait re-sweeps the nodev list,
> since device connections migrate to it asynchronously.
> Based on UEK commits:
> ece4b4e39afa ("net/rds: wait_event_timeout until zero connections during rmmod")
> https://github.com/oracle/linux-uek/commit/ece4b4e39afa
>
> 905ec90e6166 ("net/rds: Each RDS transport should keep its own connection count")
> https://github.com/oracle/linux-uek/commit/905ec90e6166
>
> Patch 7 unlinks each transport node before its destroy, so a
> free deferred past the teardown loop cannot write into the loop's
> stack-local list head. IB marks a gathered node as claimed by the
> sweep, since its connect and shutdown paths move the node too.
>
> Patch 8 hands out real references everywhere a connection pointer
> previously escaped bare, RCU-annotates parent->c_passive, refuses to
> revive a passive connection whose destroy has begun, and serializes
> the SIOCRDSSETTOS check with the rs_conn cache.
> Based on UEK commits:
> 2c8569e4c880 ("net/rds: Add krefs to struct rds_connection")
> https://github.com/oracle/linux-uek/commit/2c8569e4c880
>
> 0e9e3a72b7f7 ("net/rds: rds_sendmsg must use rs_conn only when not being destroyed").
> https://github.com/oracle/linux-uek/commit/0e9e3a72b7f7
>
> Patch 9 has the quiesce purge cp_send_queue under cp_lock, as every
> adder to that queue holds it. No sender can be in flight at any of
> today's destroy triggers (netns teardown, module unload), so this is
> hygiene rather than a race fix, and the v5 refusals in the senders
> that guarded against that impossible state are gone.
>
> Patch 10 pins the connection across the RDMA-CM event handler
> and rejects a connect request for a connection whose destroy has
> already quiesced it.
>
> Patch 11 drops the now-unused global rds_conn_count.
> Based on UEK commits:
> 905ec90e6166 ("net/rds: Each RDS transport should keep its own connection count").
> https://github.com/oracle/linux-uek/commit/905ec90e6166
>
> Patch 12 makes struct rds_incoming hold a reference on i_conn, the
> fix for the KASAN use-after-free Chengfeng Ye reported [4].
> Based on UEK commits:
> 99b9a3715419 ("net/rds: fix crash by expanding kref coverage to rds_incoming.i_conn").
> https://github.com/oracle/linux-uek/commit/99b9a3715419
>
> Patches 5, 8, 6 and 12 are ports of the connection kref work Sharath
> Srinivasan did for Oracle UEK, adapted to the upstream code.
>
> The series has been validated with the RDS selftests over loopback-TCP
> and RXE-RDMA, plus churn tests that delete network namespaces and
> unload the modules under live rds-stress traffic.
>
> Changes since v5 [7]:
> - Rebased; the version-mismatch destroy is now an rds_conn_drop() in
> net-next (f97d8c7bab78), so patch 4's Fixes: tag is gone and its
> changelog describes what still needs the per-connection flag, and
> the CM-callback deadlock reports against earlier versions no longer
> apply.
> - Patch 2: described as the refactor it is (the passive twin is
> IB-only, single path); Fixes: tag dropped.
> - Patch 9: reduced to the cp_lock purge; the send-side refusals and
> the negative *queued signalling are dropped, since no sender can be
> in flight at a destroy trigger.
> - Patch 6: wait comment describes the initial-sweep-plus-resweep
> contract; changelog notes the guarantee is complete only once incs
> hold references.
> - Patch 8: c_destroy_in_prog read through rds_destroy_pending() in
> __rds_conn_create(); the c_passive puts documented as possibly the
> last; READ_ONCE() on the unlocked rs_tos sample; rs_conn comment
> notes the rds_release() exception.
> - Patch 10: stale forward-reference comment fixed.
>
> Changes since v4 [6]:
> - Patch 7: the IB sweep marks each gathered node with a new
> i_ib_node_detached flag instead of relying on list emptiness. A
> node parked on the sweep's stack list is not empty, so a concurrent
> rds_ib_add_conn() would have unlinked it from under the sweep's
> lockless walk; rds_ib_add_conn(), rds_ib_remove_conn() and
> rds_ib_conn_free() now leave a claimed node alone.
>
> Changes since v3 [3]:
> - Rebased; the version-mismatch destroy that patch 10 also had to
> cope with is now an rds_conn_drop() in net (f97d8c7bab78), and
> patch 10's changelog says what remains for it to cover.
> - The uninitialised transport pointer in the CM event handler that
> the second v2 review pass raised turned out to be the bug Aohan
> Mei already posted a fix for (v2 at [5], stalled after review); it
> is carried forward separately for net rather than added here.
> - Patch 7: the teardown walks take a reference on each gathered
> connection, so a connection destroyed earlier and freed by a
> pending holder cannot vanish under the iterator, and the two IB
> list movers tolerate a node the sweep already unlinked instead of
> BUG_ON()ing; the nodev sweep gathers entry by entry, so the
> resweep from the unload wait no longer relies on list_splice_init().
> - Patch 8: SIOCRDSSETTOS check-then-act closed - the install in
> rds_sendmsg() re-checks the socket's ToS under rs_lock; rs_conn
> documented as a referenced, rs_lock-serialised cache; contract
> comment restored to rds_conn_lookup().
> - Patch 9: rds_send_probe() gets the same rds_destroy_pending()
> test under cp_lock as rds_send_queue_rm() (a probe queued after the
> purge pinned the connection for good).
> - v3 patch 10 (rds_tcp_accept_one() destroy check) dropped: the check
> was not serialised against the destroy, and the race it aimed at is
> not reachable - every TCP destroy path stops the listener, flushing
> the accept work, first. A comment now records that ordering.
> - Changelog and comment corrections from the second v2 review pass
> (self-requeue exemption in patch 3, c_refcount comment in patch 5,
> the uninterruptible wait and the transport-text wake in patch 6,
> "lock-free" wording in patch 11, cross-netns comment in patch 12).
>
> Changes since v2 [2]:
> - New patches 1 and 2: pre-existing rds_ib_conn_free() interrupt
> state clobber and passive-path transport data leak, surfaced by
> review of the teardown changes.
> - Patch 6: rds_ib_destroy_nodev_conns() uses list_splice_init(), so
> the resweep from the unload wait cannot splice a stale list head.
> - Patch 8: SIOCRDSGETTOS reads rs_tos under rs_lock like SETTOS.
> - New patch 9: rds_send_queue_rm() refuses a connection whose destroy
> has begun, under cp_lock, and the quiesce purges cp_send_queue
> under cp_lock (list corruption against an in-flight sender, and a
> message that would pin the connection forever).
> - New patch 10: rds_tcp_accept_one() does not install a socket on a
> connection whose destroy has begun (socket left pointing at a freed
> path).
>
> Changes since v1 [1]:
> - New patch 1: guard the five work-arming sites that never tested
> rds_destroy_pending(); patch 2's changelog and comments narrowed
> to what it actually newly covers.
> - Patch 4 moved ahead of the reference holders, so no bisect point
> has references without the unload wait; wait made unbounded with a
> periodic warning instead of a 10 s timeout; IB exit re-sweeps the
> nodev list for connections that detach from their device late.
> - New patch 5: transport nodes unlinked before destroy (stack list
> head use-after-free from a deferred conn_free).
> - Patch 6: c_passive RCU-annotated; a destroyed passive child is
> refused by __rds_conn_create() and clears the parent's pointer
> itself; SIOCRDSSETTOS uses rs_lock; lookup comment reworded;
> explicit not-for-stable note.
> - New patch 7: reference across the CM event handler, and a
> destroy-pending re-check in rds_ib_cm_handle_connect().
> - Patch 9: changelog states what a lingering inc keeps alive and
> that it blocks module unload.
> - Changelog corrections throughout (netns teardown paths named as the
> non-rmmod destroyers, stale rds_conn_path_destroy() reference).
>
> [1] https://lore.kernel.org/netdev/20260904070248.160384-1-achender@kernel.org/
> [2] https://lore.kernel.org/netdev/20260912035027.27447-1-achender@kernel.org/
> [3] https://lore.kernel.org/netdev/20260914033719.138057-1-achender@kernel.org/
> [4] https://lore.kernel.org/netdev/20260720184955.3008978-1-nicoyip.dev@gmail.com/
> [5] https://lore.kernel.org/netdev/20260825021223.3483044-1-ljp1205831794@gmail.com/
> [6] https://lore.kernel.org/netdev/20260917073958.174056-1-achender@kernel.org/
> [7] https://lore.kernel.org/netdev/20260919061149.250658-1-achender@kernel.org/
>
> Allison
>
>
> Allison Henderson (8):
> net/rds: ib: don't enable interrupts in rds_ib_conn_free()
> net/rds: free every path's transport data on the passive create paths
> net/rds: guard every work-requeueing site with rds_destroy_pending()
> net/rds: make rds_destroy_pending() report a connection's own destroy
> net/rds: unlink transport nodes before a possibly deferred connection
> free
> net/rds: take cp_lock to purge cp_send_queue in the quiesce
> net/rds: pin the connection across RDMA-CM event handling
> net/rds: drop rds_conn_count in favor of t_conn_count
>
> Sharath Srinivasan (4):
> net/rds: split connection destroy into quiesce and kref-governed free
> net/rds: wait for connections to be freed on transport unload
> net/rds: hold connection references in lookup, sockets and c_passive
> net/rds: hold a connection reference from struct rds_incoming
>
> net/rds/af_rds.c | 24 ++-
> net/rds/connection.c | 330 +++++++++++++++++++++++++++++++++------
> net/rds/ib.c | 22 ++-
> net/rds/ib.h | 4 +
> net/rds/ib_cm.c | 29 +++-
> net/rds/ib_rdma.c | 67 ++++++--
> net/rds/ib_recv.c | 6 +-
> net/rds/ib_send.c | 18 ++-
> net/rds/loop.c | 61 ++++++--
> net/rds/message.c | 16 +-
> net/rds/rdma_transport.c | 16 +-
> net/rds/rds.h | 46 +++++-
> net/rds/recv.c | 26 ++-
> net/rds/send.c | 68 +++++++-
> net/rds/tcp.c | 53 ++++++-
> net/rds/tcp_listen.c | 21 ++-
> 16 files changed, 690 insertions(+), 117 deletions(-)
>
next prev parent reply other threads:[~2026-09-22 16:47 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-22 16:43 [PATCH net-next v6 00/12] net/rds: make connection lifetime reference-counted Allison Henderson
2026-09-22 16:43 ` [PATCH net-next v6 01/12] net/rds: ib: don't enable interrupts in rds_ib_conn_free() Allison Henderson
2026-09-22 16:43 ` [PATCH net-next v6 02/12] net/rds: undo conn_alloc() the same way on every __rds_conn_create() exit Allison Henderson
2026-09-22 16:43 ` [PATCH net-next v6 03/12] net/rds: guard every work-requeueing site with rds_destroy_pending() Allison Henderson
2026-09-22 16:43 ` [PATCH net-next v6 04/12] net/rds: make rds_destroy_pending() report a connection's own destroy Allison Henderson
2026-09-22 16:47 ` Allison Henderson [this message]
-- strict thread matches above, loose matches on Subject: below --
2026-09-22 8:53 [PATCH net-next v6 00/12] net/rds: make connection lifetime reference-counted 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=d61a18374d74c7fca6448692b86e7351bd2ad080.camel@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