5.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <redacted>
commit b54e03d9b3697d25f4a0063cf717d459c5e3ad94 upstream.
A node receiving a DLM_MIG_LOCKRES message trusts several fields of the
peer-supplied dlm_migratable_lockres without validation. num_locks and
lockname_len are bounded only on the sending side, and the message is
never checked to actually carry num_locks migratable_lock entries. As a
result dlm_process_recovery_data() walks mres->ml[0..num_locks) past the
kmalloc(data_len) copy of the message (an out-of-bounds read that ends in
a BUG_ON panic), and dlm_init_lockres() copies lockname_len bytes into the
fixed 32-byte o2dlm_lockname slab object (a heap out-of-bounds write).
Both are reachable by any node in the domain.
Validate these fields right after dlm_grab(), before anything uses them --
including the not-joined error path, which already prints mres->lockname
with the unbounded lockname_len as a %.*s precision. Reject the message
unless lockname_len <= DLM_LOCKID_NAME_MAX, num_locks <=
DLM_MAX_MIGRATABLE_LOCKS (the bound the sender already asserts), and the
payload is large enough to hold the claimed locks. Conforming recovery
and migration messages are unaffected.
Link: https://lore.kernel.org/20260629-b4-disp-94fb6521-v1-2-6953bcc0421f@proton.me (local)
Fixes: 6714d8e86bf4 ("[PATCH] OCFS2: The Second Oracle Cluster Filesystem")
Signed-off-by: Bryam Vargas <redacted>
Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Cc: Mark Fasheh <mark@fasheh.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Junxiao Bi <redacted>
Cc: Changwei Ge <redacted>
Cc: Jun Piao <redacted>
Cc: Heming Zhao <heming.zhao@suse.com>
Cc: <redacted>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ocfs2/dlm/dlmrecovery.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -1359,6 +1359,15 @@ int dlm_mig_lockres_handler(struct o2net
if (!dlm_grab(dlm))
return -EINVAL;
+ if (mres->lockname_len > DLM_LOCKID_NAME_MAX ||
+ mres->num_locks > DLM_MAX_MIGRATABLE_LOCKS ||
+ be16_to_cpu(msg->data_len) < struct_size(mres, ml, mres->num_locks)) {
+ mlog(ML_ERROR, "%s: invalid lockres migration message from %u\n",
+ dlm->name, mres->master);
+ dlm_put(dlm);
+ return -EINVAL;
+ }
+
if (!dlm_joined(dlm)) {
mlog(ML_ERROR, "Domain %s not joined! "
"lockres %.*s, master %u\n",