* [PATCH 0/2] ocfs2/dlm: bound peer-controlled lengths in the o2dlm receive path
@ 2026-06-29 5:01 Bryam Vargas via B4 Relay
2026-06-29 5:01 ` [PATCH 1/2] ocfs2: bound namelen in dlm_migrate_request_handler Bryam Vargas via B4 Relay
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Bryam Vargas via B4 Relay @ 2026-06-29 5:01 UTC (permalink / raw)
To: Joseph Qi, Mark Fasheh, Joel Becker
Cc: linux-kernel, ocfs2-devel, Andrew Morton, Kurt Hackel
The o2dlm receive handlers trust u8 length and count fields from the wire
without bounding them, so a node in a DLM domain can corrupt or panic any
other node with a malformed message. Three defects:
- dlm_migrate_request_handler() passes migrate->namelen unchecked to
dlm_init_mle(), which memcpy()s it into the 32-byte mname[] of an
o2dlm_mle slab object: a heap out-of-bounds write of up to ~215
attacker-controlled bytes.
- dlm_mig_lockres_handler() passes mres->lockname_len unchecked to
dlm_init_lockres(), which memcpy()s it into the 32-byte o2dlm_lockname
slab object: a heap out-of-bounds write of up to ~223 bytes.
- the same handler trusts mres->num_locks without checking that the
message is large enough to hold that many entries, so
dlm_process_recovery_data() walks mres->ml[] past the kmalloc(data_len)
copy and trips a BUG_ON (an out-of-bounds read ending in a panic).
The other o2dlm receive handlers already reject an oversized name; the
migration and recovery handlers have omitted it since the DLM was added (see
the Fixes tags). Patch 1 bounds namelen; patch 2 validates lockname_len,
num_locks, and the payload size. Conforming recovery and migration traffic is
unaffected.
o2net authenticates peers only by the DLM domain key, so any node that has
joined the domain -- including a compromised or malicious member -- can send
these messages. There is no local trigger; the attacker must already be a
member of the cluster.
Each sink was confirmed under KASAN with an out-of-tree module mirroring it
exactly -- a kmem_cache/kmalloc of the real destination size, then the same
unclamped memcpy/loop: slab-out-of-bounds Write for the two writes, Read for
the recovery walk, and a panic. A userspace AddressSanitizer build faults
identically under -m32 and -m64. Scrubbed logs are available on request.
I reported this privately to security@kernel.org and the ocfs2 maintainers on
2026-06-20; with no response after the standard embargo period I am posting
the fix publicly. I have no embargo requirement.
Bryam Vargas (2):
ocfs2: bound namelen in dlm_migrate_request_handler
ocfs2: validate lengths in dlm_mig_lockres_handler
fs/ocfs2/dlm/dlmmaster.c | 6 ++++++
fs/ocfs2/dlm/dlmrecovery.c | 9 +++++++++
2 files changed, 15 insertions(+)
---
Bryam Vargas (2):
ocfs2: bound namelen in dlm_migrate_request_handler
ocfs2: validate lengths in dlm_mig_lockres_handler
fs/ocfs2/dlm/dlmmaster.c | 6 ++++++
fs/ocfs2/dlm/dlmrecovery.c | 9 +++++++++
2 files changed, 15 insertions(+)
---
base-commit: 4549871118cf616eecdd2d939f78e3b9e1dddc48
change-id: 20260629-b4-disp-94fb6521-0afa227d464c
Best regards,
--
Bryam Vargas <hexlabsecurity@proton.me>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/2] ocfs2: bound namelen in dlm_migrate_request_handler
2026-06-29 5:01 [PATCH 0/2] ocfs2/dlm: bound peer-controlled lengths in the o2dlm receive path Bryam Vargas via B4 Relay
@ 2026-06-29 5:01 ` Bryam Vargas via B4 Relay
2026-07-02 11:03 ` Joseph Qi
2026-06-29 5:01 ` [PATCH 2/2] ocfs2: validate lengths in dlm_mig_lockres_handler Bryam Vargas via B4 Relay
2026-07-02 5:56 ` [PATCH 0/2] ocfs2/dlm: bound peer-controlled lengths in the o2dlm receive path Joseph Qi
2 siblings, 1 reply; 7+ messages in thread
From: Bryam Vargas via B4 Relay @ 2026-06-29 5:01 UTC (permalink / raw)
To: Joseph Qi, Mark Fasheh, Joel Becker
Cc: linux-kernel, ocfs2-devel, Andrew Morton, Kurt Hackel
From: Bryam Vargas <hexlabsecurity@proton.me>
A node receiving a DLM_MIGRATE_REQUEST message trusts the peer-supplied
name length (migrate->namelen) without bounding it. dlm_init_mle() then
copies that many bytes into the fixed DLM_LOCKID_NAME_MAX-byte mname[]
array of an o2dlm_mle slab object, so a malformed message from a cluster
peer overflows the slab object by up to ~215 bytes: a heap out-of-bounds
write of attacker-controlled data, reachable by any node in the domain.
Reject an oversized name, the way dlm_master_request_handler() and the
other o2dlm receive handlers already do; the migration handler omits the
check entirely. Conforming messages are unaffected.
Fixes: 6714d8e86bf4 ("[PATCH] OCFS2: The Second Oracle Cluster Filesystem")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
---
fs/ocfs2/dlm/dlmmaster.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 93eff38fdadd..bd7623cc6e77 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -3100,6 +3100,12 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data,
name = migrate->name;
namelen = migrate->namelen;
+ if (namelen > DLM_LOCKID_NAME_MAX) {
+ mlog(ML_ERROR, "%s: invalid name length %u in migrate request\n",
+ dlm->name, namelen);
+ ret = -EINVAL;
+ goto leave;
+ }
hash = dlm_lockid_hash(name, namelen);
/* preallocate.. if this fails, abort */
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/2] ocfs2: validate lengths in dlm_mig_lockres_handler
2026-06-29 5:01 [PATCH 0/2] ocfs2/dlm: bound peer-controlled lengths in the o2dlm receive path Bryam Vargas via B4 Relay
2026-06-29 5:01 ` [PATCH 1/2] ocfs2: bound namelen in dlm_migrate_request_handler Bryam Vargas via B4 Relay
@ 2026-06-29 5:01 ` Bryam Vargas via B4 Relay
2026-07-02 11:05 ` Joseph Qi
2026-07-02 5:56 ` [PATCH 0/2] ocfs2/dlm: bound peer-controlled lengths in the o2dlm receive path Joseph Qi
2 siblings, 1 reply; 7+ messages in thread
From: Bryam Vargas via B4 Relay @ 2026-06-29 5:01 UTC (permalink / raw)
To: Joseph Qi, Mark Fasheh, Joel Becker
Cc: linux-kernel, ocfs2-devel, Andrew Morton, Kurt Hackel
From: Bryam Vargas <hexlabsecurity@proton.me>
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.
Fixes: 6714d8e86bf4 ("[PATCH] OCFS2: The Second Oracle Cluster Filesystem")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
---
fs/ocfs2/dlm/dlmrecovery.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 128872bd945d..14d4c7c3eebd 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -1357,6 +1357,15 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
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",
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/2] ocfs2/dlm: bound peer-controlled lengths in the o2dlm receive path
2026-06-29 5:01 [PATCH 0/2] ocfs2/dlm: bound peer-controlled lengths in the o2dlm receive path Bryam Vargas via B4 Relay
2026-06-29 5:01 ` [PATCH 1/2] ocfs2: bound namelen in dlm_migrate_request_handler Bryam Vargas via B4 Relay
2026-06-29 5:01 ` [PATCH 2/2] ocfs2: validate lengths in dlm_mig_lockres_handler Bryam Vargas via B4 Relay
@ 2026-07-02 5:56 ` Joseph Qi
2026-07-02 9:27 ` Bryam Vargas
2 siblings, 1 reply; 7+ messages in thread
From: Joseph Qi @ 2026-07-02 5:56 UTC (permalink / raw)
To: hexlabsecurity, Mark Fasheh, Joel Becker
Cc: linux-kernel, ocfs2-devel, Andrew Morton, Kurt Hackel
Ocfs2 is always deployed in trusted network, so how to trigger this
issue in real environment?
In a properly administered ocfs2 cluster with trusted nodes and no
compromised machines, this looks essentially unreachable.
IMO, the patches are reasonable as a belt hardening against future bugs
or operational accidents, but not overstate the risk by framing it as a
security vulnerability.
Thanks,
Joseph
On 6/29/26 1:01 PM, Bryam Vargas via B4 Relay wrote:
> The o2dlm receive handlers trust u8 length and count fields from the wire
> without bounding them, so a node in a DLM domain can corrupt or panic any
> other node with a malformed message. Three defects:
>
> - dlm_migrate_request_handler() passes migrate->namelen unchecked to
> dlm_init_mle(), which memcpy()s it into the 32-byte mname[] of an
> o2dlm_mle slab object: a heap out-of-bounds write of up to ~215
> attacker-controlled bytes.
>
> - dlm_mig_lockres_handler() passes mres->lockname_len unchecked to
> dlm_init_lockres(), which memcpy()s it into the 32-byte o2dlm_lockname
> slab object: a heap out-of-bounds write of up to ~223 bytes.
>
> - the same handler trusts mres->num_locks without checking that the
> message is large enough to hold that many entries, so
> dlm_process_recovery_data() walks mres->ml[] past the kmalloc(data_len)
> copy and trips a BUG_ON (an out-of-bounds read ending in a panic).
>
> The other o2dlm receive handlers already reject an oversized name; the
> migration and recovery handlers have omitted it since the DLM was added (see
> the Fixes tags). Patch 1 bounds namelen; patch 2 validates lockname_len,
> num_locks, and the payload size. Conforming recovery and migration traffic is
> unaffected.
>
> o2net authenticates peers only by the DLM domain key, so any node that has
> joined the domain -- including a compromised or malicious member -- can send
> these messages. There is no local trigger; the attacker must already be a
> member of the cluster.
>
> Each sink was confirmed under KASAN with an out-of-tree module mirroring it
> exactly -- a kmem_cache/kmalloc of the real destination size, then the same
> unclamped memcpy/loop: slab-out-of-bounds Write for the two writes, Read for
> the recovery walk, and a panic. A userspace AddressSanitizer build faults
> identically under -m32 and -m64. Scrubbed logs are available on request.
>
> I reported this privately to security@kernel.org and the ocfs2 maintainers on
> 2026-06-20; with no response after the standard embargo period I am posting
> the fix publicly. I have no embargo requirement.
>
> Bryam Vargas (2):
> ocfs2: bound namelen in dlm_migrate_request_handler
> ocfs2: validate lengths in dlm_mig_lockres_handler
>
> fs/ocfs2/dlm/dlmmaster.c | 6 ++++++
> fs/ocfs2/dlm/dlmrecovery.c | 9 +++++++++
> 2 files changed, 15 insertions(+)
>
> ---
> Bryam Vargas (2):
> ocfs2: bound namelen in dlm_migrate_request_handler
> ocfs2: validate lengths in dlm_mig_lockres_handler
>
> fs/ocfs2/dlm/dlmmaster.c | 6 ++++++
> fs/ocfs2/dlm/dlmrecovery.c | 9 +++++++++
> 2 files changed, 15 insertions(+)
> ---
> base-commit: 4549871118cf616eecdd2d939f78e3b9e1dddc48
> change-id: 20260629-b4-disp-94fb6521-0afa227d464c
>
> Best regards,
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 0/2] ocfs2/dlm: bound peer-controlled lengths in the o2dlm receive path
2026-07-02 5:56 ` [PATCH 0/2] ocfs2/dlm: bound peer-controlled lengths in the o2dlm receive path Joseph Qi
@ 2026-07-02 9:27 ` Bryam Vargas
0 siblings, 0 replies; 7+ messages in thread
From: Bryam Vargas @ 2026-07-02 9:27 UTC (permalink / raw)
To: Joseph Qi, Mark Fasheh, Joel Becker
Cc: ocfs2-devel, linux-kernel, Andrew Morton, Kurt Hackel
On Thu, 2 Jul 2026 13:56:00 +0800, Joseph Qi wrote:
> Ocfs2 is always deployed in trusted network, so how to trigger this
> issue in real environment?
Agreed on the precondition: there's no local trigger, and a random host off the
cluster can't reach this. The sender has to be a node the cluster's o2net layer
accepts, so it isn't remote-unauthenticated.
The real-environment trigger isn't a malicious admin. It's a single compromised
member: code execution on one node via any unrelated flaw, or a node wrongly
admitted to the interconnect. o2net admits senders by node configuration, not by
any secret -- so "trusted network" is the whole boundary. From that one foothold
you can corrupt the kernel heap of, or panic, every other node in the domain.
Node B's kernel integrity shouldn't depend on node A never being compromised.
> IMO, the patches are reasonable as a belt hardening against future bugs
> or operational accidents, but not overstate the risk by framing it as a
> security vulnerability.
The DLM already treats these wire fields as untrusted, so this isn't a belt
against a hypothetical. The lock-operation handlers reject an oversized name the
moment they read it:
dlm_master_request_handler fs/ocfs2/dlm/dlmmaster.c:1426
dlm_create_lock_handler fs/ocfs2/dlm/dlmlock.c:469
dlm_convert_lock_handler fs/ocfs2/dlm/dlmconvert.c:450
dlm_unlock_lock_handler fs/ocfs2/dlm/dlmunlock.c:416
same namelen > DLM_LOCKID_NAME_MAX test in all four. dlm_migrate_request_handler
and dlm_mig_lockres_handler take the identical u8 field into the identical
32-byte buffer and skip it. The patches just make them consistent with the rest
of the receive path. Here the sender's u8 length (up to 255) reaches the 32-byte
slab buffer with no bound, and the sender controls the copied bytes too. That's
a heap OOB write.
The framing is your call as maintainer, and the fix is identical either way. If
ocfs2's position is that a joined member is inside the trust boundary, I won't
argue the CVE -- but these two are attacker-length-and-content-controlled heap
OOB writes, which is why I didn't post them as robustness-only. Either way I'd
like the bound to land.
Thanks for the review,
Bryam
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] ocfs2: bound namelen in dlm_migrate_request_handler
2026-06-29 5:01 ` [PATCH 1/2] ocfs2: bound namelen in dlm_migrate_request_handler Bryam Vargas via B4 Relay
@ 2026-07-02 11:03 ` Joseph Qi
0 siblings, 0 replies; 7+ messages in thread
From: Joseph Qi @ 2026-07-02 11:03 UTC (permalink / raw)
To: hexlabsecurity, Andrew Morton
Cc: linux-kernel, ocfs2-devel, Kurt Hackel, Mark Fasheh, Joel Becker
On 6/29/26 1:01 PM, Bryam Vargas via B4 Relay wrote:
> From: Bryam Vargas <hexlabsecurity@proton.me>
>
> A node receiving a DLM_MIGRATE_REQUEST message trusts the peer-supplied
> name length (migrate->namelen) without bounding it. dlm_init_mle() then
> copies that many bytes into the fixed DLM_LOCKID_NAME_MAX-byte mname[]
> array of an o2dlm_mle slab object, so a malformed message from a cluster
> peer overflows the slab object by up to ~215 bytes: a heap out-of-bounds
> write of attacker-controlled data, reachable by any node in the domain.
>
> Reject an oversized name, the way dlm_master_request_handler() and the
> other o2dlm receive handlers already do; the migration handler omits the
> check entirely. Conforming messages are unaffected.
>
> Fixes: 6714d8e86bf4 ("[PATCH] OCFS2: The Second Oracle Cluster Filesystem")
> Cc: stable@vger.kernel.org
> Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Looks fine.
Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
> ---
> fs/ocfs2/dlm/dlmmaster.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
> index 93eff38fdadd..bd7623cc6e77 100644
> --- a/fs/ocfs2/dlm/dlmmaster.c
> +++ b/fs/ocfs2/dlm/dlmmaster.c
> @@ -3100,6 +3100,12 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data,
>
> name = migrate->name;
> namelen = migrate->namelen;
> + if (namelen > DLM_LOCKID_NAME_MAX) {
> + mlog(ML_ERROR, "%s: invalid name length %u in migrate request\n",
> + dlm->name, namelen);
> + ret = -EINVAL;
> + goto leave;
> + }
> hash = dlm_lockid_hash(name, namelen);
>
> /* preallocate.. if this fails, abort */
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] ocfs2: validate lengths in dlm_mig_lockres_handler
2026-06-29 5:01 ` [PATCH 2/2] ocfs2: validate lengths in dlm_mig_lockres_handler Bryam Vargas via B4 Relay
@ 2026-07-02 11:05 ` Joseph Qi
0 siblings, 0 replies; 7+ messages in thread
From: Joseph Qi @ 2026-07-02 11:05 UTC (permalink / raw)
To: hexlabsecurity, Andrew Morton
Cc: linux-kernel, ocfs2-devel, Kurt Hackel, Mark Fasheh, Joel Becker
On 6/29/26 1:01 PM, Bryam Vargas via B4 Relay wrote:
> From: Bryam Vargas <hexlabsecurity@proton.me>
>
> 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.
>
> Fixes: 6714d8e86bf4 ("[PATCH] OCFS2: The Second Oracle Cluster Filesystem")
> Cc: stable@vger.kernel.org
> Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Looks fine.
Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
> ---
> fs/ocfs2/dlm/dlmrecovery.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
> index 128872bd945d..14d4c7c3eebd 100644
> --- a/fs/ocfs2/dlm/dlmrecovery.c
> +++ b/fs/ocfs2/dlm/dlmrecovery.c
> @@ -1357,6 +1357,15 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
> 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",
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-07-02 11:05 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-29 5:01 [PATCH 0/2] ocfs2/dlm: bound peer-controlled lengths in the o2dlm receive path Bryam Vargas via B4 Relay
2026-06-29 5:01 ` [PATCH 1/2] ocfs2: bound namelen in dlm_migrate_request_handler Bryam Vargas via B4 Relay
2026-07-02 11:03 ` Joseph Qi
2026-06-29 5:01 ` [PATCH 2/2] ocfs2: validate lengths in dlm_mig_lockres_handler Bryam Vargas via B4 Relay
2026-07-02 11:05 ` Joseph Qi
2026-07-02 5:56 ` [PATCH 0/2] ocfs2/dlm: bound peer-controlled lengths in the o2dlm receive path Joseph Qi
2026-07-02 9:27 ` Bryam Vargas
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome