From: Cen Zhang <zzzccc427@gmail.com>
To: mark@fasheh.com, jlbec@evilplan.org, joseph.qi@linux.alibaba.com
Cc: heming.zhao@suse.com, ocfs2-devel@lists.linux.dev,
linux-kernel@vger.kernel.org, stable@vger.kernel.org,
baijiaju1990@gmail.com, jjzuming@gmail.com, zzzccc427@gmail.com
Subject: [PATCH] ocfs2/dlm: serialize migration MLE cleanup on failure
Date: Tue, 27 Oct 2026 10:53:50 +0800 [thread overview]
Message-ID: <pm-ocfs2-objects-candidate-0038-v5-5e414ac0c701d2ccd4b3@gmail.com> (raw)
A migration MLE has a base reference for the mastering answer and an
in-use reference held by dlm_migrate_lockres(). The finishing assertion
consumes the base reference, but migration failure drops it again
without checking whether the assertion already consumed it.
The target queues its migration worker before it acknowledges the
ALL_DONE packet, so its finishing assertion can arrive while the sender
still waits for the status, or after dlm_send_one_lockres() has
returned a connection error for that very packet:
Old-master sender Finishing assertion
----------------- -------------------
publish MLE; take in-use reference
send ALL_DONE; wait for status
take lookup reference
unlink MLE
put lookup and base references
send returns a connection error
put base reference again; free MLE
put in-use reference; access freed MLE
dlm_assert_master_handler() holds dlm->spinlock from the MLE lookup to
the final puts, and it takes dlm->master_lock around the unlink and the
puts. Decide under the same locks: if the MLE is already unhashed, the
assertion consumed the base reference, so drop only the sender's in-use
reference. Otherwise unlink it before consuming the base reference so a
later assertion no longer finds it.
Use the same cleanup helper for the pre-send failure, the send failure
and the target-death failure paths. The sender's in-use reference keeps
the MLE alive until its final put outside the nested locks. Successful
migration retains its existing in-use-only put.
KASAN report, only the relevant frames are kept:
BUG: KASAN: slab-use-after-free in dlm_put_mle_inuse+0xce/0xe0
Read of size 8 at addr ffff8881190e3c20 by task umount/593
Call Trace:
<TASK>
dlm_put_mle_inuse+0xce/0xe0
dlm_migrate_lockres+0x16af/0x20d0
dlm_empty_lockres+0x60a/0xbd0
dlm_unregister_domain+0x53b/0x11d0
o2cb_cluster_disconnect+0xa5/0x110
ocfs2_cluster_disconnect+0x73/0xc0
ocfs2_dlm_shutdown+0x311/0x440
ocfs2_dismount_volume+0x696/0x940
generic_shutdown_super+0x15f/0x490
kill_block_super+0x40/0xa0
deactivate_locked_super+0xae/0x120
deactivate_super+0xa2/0xc0
cleanup_mnt+0x217/0x450
task_work_run+0x144/0x230
</TASK>
Allocated by task 593:
kmem_cache_alloc_noprof+0x20b/0x5c0
dlm_migrate_lockres+0x20e/0x20d0
dlm_empty_lockres+0x60a/0xbd0
dlm_unregister_domain+0x53b/0x11d0
o2cb_cluster_disconnect+0xa5/0x110
ocfs2_cluster_disconnect+0x73/0xc0
ocfs2_dlm_shutdown+0x311/0x440
ocfs2_dismount_volume+0x696/0x940
Freed by task 593:
kmem_cache_free+0x242/0x580
__dlm_put_mle+0x4b2/0x660
dlm_migrate_lockres+0x1690/0x20d0
dlm_empty_lockres+0x60a/0xbd0
dlm_unregister_domain+0x53b/0x11d0
o2cb_cluster_disconnect+0xa5/0x110
ocfs2_cluster_disconnect+0x73/0xc0
ocfs2_dlm_shutdown+0x311/0x440
The buggy address belongs to the object at ffff8881190e3c00
which belongs to the cache o2dlm_mle of size 480
The buggy address is located 32 bytes inside of
freed 480-byte region [ffff8881190e3c00, ffff8881190e3de0)
Fixes: 6714d8e86bf4 ("[PATCH] OCFS2: The Second Oracle Cluster Filesystem")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
fs/ocfs2/dlm/dlmmaster.c | 33 ++++++++++++++++++++++++---------
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 612969867ff9..57119b195cc1 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -2525,6 +2525,27 @@ static int dlm_is_lockres_migratable(struct dlm_ctxt *dlm,
*/
+/*
+ * The finishing assert may already have unlinked the MLE and dropped its
+ * base reference. Decide under the locks the assert handler holds, and only
+ * drop the base reference here while the MLE is still hashed.
+ */
+static void dlm_put_migration_mle(struct dlm_ctxt *dlm,
+ struct dlm_master_list_entry *mle)
+{
+ spin_lock(&dlm->spinlock);
+ spin_lock(&dlm->master_lock);
+ __dlm_mle_detach_hb_events(dlm, mle);
+ if (!hlist_unhashed(&mle->master_hash_node)) {
+ __dlm_unlink_mle(dlm, mle);
+ __dlm_put_mle(mle);
+ }
+ spin_unlock(&dlm->master_lock);
+ spin_unlock(&dlm->spinlock);
+
+ dlm_put_mle_inuse(mle);
+}
+
static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
struct dlm_lock_resource *res, u8 target)
{
@@ -2609,9 +2630,7 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
if (ret < 0) {
if (mle_added) {
- dlm_mle_detach_hb_events(dlm, mle);
- dlm_put_mle(mle);
- dlm_put_mle_inuse(mle);
+ dlm_put_migration_mle(dlm, mle);
} else if (mle) {
kmem_cache_free(dlm_mle_cache, mle);
mle = NULL;
@@ -2640,9 +2659,7 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
mlog(0, "migration to node %u failed with %d\n",
target, ret);
/* migration failed, detach and clean up mle */
- dlm_mle_detach_hb_events(dlm, mle);
- dlm_put_mle(mle);
- dlm_put_mle_inuse(mle);
+ dlm_put_migration_mle(dlm, mle);
spin_lock(&res->spinlock);
res->state &= ~DLM_LOCK_RES_MIGRATING;
wake = 1;
@@ -2686,9 +2703,7 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
res->lockname.name, target);
ret = -EINVAL;
/* migration failed, detach and clean up mle */
- dlm_mle_detach_hb_events(dlm, mle);
- dlm_put_mle(mle);
- dlm_put_mle_inuse(mle);
+ dlm_put_migration_mle(dlm, mle);
spin_lock(&res->spinlock);
res->state &= ~DLM_LOCK_RES_MIGRATING;
wake = 1;
reply other threads:[~2026-10-27 2:53 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=pm-ocfs2-objects-candidate-0038-v5-5e414ac0c701d2ccd4b3@gmail.com \
--to=zzzccc427@gmail.com \
--cc=baijiaju1990@gmail.com \
--cc=heming.zhao@suse.com \
--cc=jjzuming@gmail.com \
--cc=jlbec@evilplan.org \
--cc=joseph.qi@linux.alibaba.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mark@fasheh.com \
--cc=ocfs2-devel@lists.linux.dev \
--cc=stable@vger.kernel.org \
/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
all inboxes | Powered by JetHome®