diff options
| author | Zqiang <qiang.zhang@linux.dev> | 2026-09-01 13:47:14 -0400 |
|---|---|---|
| committer | David Teigland <teigland@redhat.com> | 2026-09-02 11:52:20 -0500 |
| commit | ed9b6a1296f10e4881d93dfe6d76013fbbaeee87 (patch) | |
| tree | ed534a328dc32fd575204dbdb13575ab1a6d6123 | |
| parent | b4e6ae7ba711758c38d5eb7d5a7a0712273bdf6f (diff) | |
dlm: wait for outstanding SRCU callbacks to complete in exit paths
The dlm_lowcomms_exit() and dlm_midcomms_exit() iterate over the
srcu protected connection and node hash tables and hand each
element to call_srcu() for deferred freeing (connection_release()
and midcomms_node_release()). call_srcu() is asynchronous: the
callbacks are invoked only after an SRCU grace period, which may
happen after the exit function has already returned.
These exit functions are reached from exit_dlm() on module unload.
Once they return, module teardown continues and the module text
may be unloaded while call_srcu() callbacks are still pending. When
such a callback finally runs, it executes freed module code and
touches the static SRCU domains that are being torn down, resulting
in a use-after-free.
Add an srcu_barrier() after the call_srcu() loop in each exit function
to wait for all outstanding callbacks of the respective SRCU domain to
complete before returning. In dlm_midcomms_exit() the barrier is issued
before dlm_lowcomms_exit() so that node callbacks are drained prior to
tearing down the lower layer.
Signed-off-by: Zqiang <qiang.zhang@linux.dev>
Acked-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
| -rw-r--r-- | fs/dlm/lowcomms.c | 1 | ||||
| -rw-r--r-- | fs/dlm/midcomms.c | 1 |
2 files changed, 2 insertions, 0 deletions
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 2aff1c7c17de..ea8353c4638d 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -1984,4 +1984,5 @@ void dlm_lowcomms_exit(void) } } srcu_read_unlock(&connections_srcu, idx); + srcu_barrier(&connections_srcu); } diff --git a/fs/dlm/midcomms.c b/fs/dlm/midcomms.c index 8964164600d2..045431524494 100644 --- a/fs/dlm/midcomms.c +++ b/fs/dlm/midcomms.c @@ -1178,6 +1178,7 @@ void dlm_midcomms_exit(void) } } srcu_read_unlock(&nodes_srcu, idx); + srcu_barrier(&nodes_srcu); dlm_lowcomms_exit(); } |
