Re: [PATCH] dlm: validate userspace lock resource name length
Alexander Aring <[email protected]> Thu, 16 Jul 2026 14:23:59 -0400
| Newsgroups | dev.linux.lists.gfs2,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAK-6q+hf8X9g+hiPC5A3n4rr1C=vWjakB4tU-sRFQHEL9finMg@mail.gmail.com> |
Hi, On Mon, Jun 8, 2026 at 8:16=E2=80=AFPM Samuel Moelius <[email protected]> wrote: > > 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 <[email protected]> Acked-by: Alexander Aring <[email protected]> > --- > 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 =3D file->private_data; > + size_t name_payload =3D 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 =3D count - sizeof(struct dlm_write_reque= st32); > + name_payload =3D namelen; > > k32buf =3D (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 =3D count - sizeof(*kbuf); > } > +#else > + if (count > sizeof(*kbuf)) > + name_payload =3D 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 =3D=3D DLM_USER_LOCK && > + !(kbuf->i.lock.flags & DLM_LKF_CONVERT)) { > + if (kbuf->i.lock.namelen > name_payload || > + kbuf->i.lock.namelen > DLM_RESNAME_MAXLEN) { there is later a check in "set_lock_args" to do a "if (!(flags & DLM_LKF_CONVERT) && (namelen > DLM_RESNAME_MAXLEN))" check. However there is a trace call in between that can access this array out of bounds area if namelen is above DLM_RESNAME_MAXLEN. I will add a cleanup patch to my list to check for "sane" parameters as soon as they are known... - Alex