[PATCH] dlm: validate userspace lock resource name length

From: Samuel Moelius

Date: Mon Jun 08 2026 - 20:17:55 EST


The DLM userspace device accepts a flexible resource name after
`struct dlm_write_request`. `device_write()` bounded the total write
size, but did not verify that `i.lock.namelen` was covered by the bytes
actually supplied by the write.

A short `DLM_USER_LOCK` request can therefore claim a full
`DLM_RESNAME_MAXLEN` resource name while providing no name bytes. The
request path later hashes and copies the claimed name length, reading
past the `memdup_user_nul()` allocation.

Reject non-conversion lock requests whose claimed resource name length
exceeds the flexible name payload supplied with the write. Valid lock
requests with complete names are unchanged. Track the payload length
before compat conversion so 32-bit requests keep using their own request
header size.

Assisted-by: Codex:gpt-5.5-cyber-preview
Signed-off-by: Samuel Moelius <sam.moelius@xxxxxxxxxxxxxxx>
---
fs/dlm/user.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)

diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index a8ed4c8fdc5b..205364329ce3 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -511,6 +511,7 @@ static ssize_t device_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct dlm_user_proc *proc = file->private_data;
+ size_t name_payload = 0;
struct dlm_write_request *kbuf;
int error;

@@ -544,6 +545,7 @@ static ssize_t device_write(struct file *file, const char __user *buf,

if (count > sizeof(struct dlm_write_request32))
namelen = count - sizeof(struct dlm_write_request32);
+ name_payload = namelen;

k32buf = (struct dlm_write_request32 *)kbuf;

@@ -560,7 +562,13 @@ static ssize_t device_write(struct file *file, const char __user *buf,

compat_input(kbuf, k32buf, namelen);
kfree(k32buf);
+ } else {
+ if (count > sizeof(*kbuf))
+ name_payload = count - sizeof(*kbuf);
}
+#else
+ if (count > sizeof(*kbuf))
+ name_payload = count - sizeof(*kbuf);
#endif

/* do we really need this? can a write happen after a close? */
@@ -570,6 +578,15 @@ static ssize_t device_write(struct file *file, const char __user *buf,
goto out_free;
}

+ if (kbuf->cmd == DLM_USER_LOCK &&
+ !(kbuf->i.lock.flags & DLM_LKF_CONVERT)) {
+ if (kbuf->i.lock.namelen > name_payload ||
+ kbuf->i.lock.namelen > DLM_RESNAME_MAXLEN) {
+ error = -EINVAL;
+ goto out_free;
+ }
+ }
+
error = -EINVAL;

switch (kbuf->cmd)
--
2.43.0