Re: [PATCH 1/2] dlm: gate dlm_plock device on CAP_SYS_ADMIN
Alexander Aring <[email protected]> Thu, 16 Jul 2026 14:11:42 -0400
| Newsgroups | dev.linux.lists.gfs2,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAK-6q+jkA3_sYQZhRRHNBCrX4MsjsLJMRODr-d6t6n3T3tFTOg@mail.gmail.com> |
Hi, On Thu, Jul 16, 2026 at 3:27=E2=80=AFAM Haofeng Li <[email protected]> w= rote: > > fs/dlm/plock.c registers /dev/dlm_plock via a miscdevice whose > file_operations has no .open callback and whose .mode field is unset. > The kernel therefore performs no capability check on open, and any > process that can open the node becomes an unprivileged plock daemon > with full read+write access to the pending-plock queue. > > Attack chain (when the device node is reachable by an unprivileged > opener =E2=80=94 see mitigation note below): > > 1. attacker open("/dev/dlm_plock") succeeds with no cap check > 2. dev_read() drains pending plock requests straight to user > space, leaking dlm_plock_info fields: fsid, number (resource > id / inode), start, end, owner, pid, ex, wait > 3. dev_write() matches an attacker-supplied dlm_plock_info > against a pending op on recv_list (matched on fsid+number+ > owner+pid+start+end+ex+wait) and memcpy()'s it into the > in-kernel op, including a forged .rv =3D=3D 0 > 4. when a matched op exists, the forged result is then applied: > for async ops (op->data !=3D NULL), dlm_plock_callback() runs > posix_lock_file(); for sync ops, the requester wakes and > proceeds as if the cluster had granted the lock. Either way > the requester ends up holding a POSIX lock without a real DLM > grant, or sees attacker-chosen rv that breaks lock correctness. > With no pending op on recv_list, dev_write() still returns > sizeof(info) but does nothing beyond a pr_debug ("dlm dev_write > no op ...") =E2=80=94 so a syntactically accepted write does not by > itself prove an applied grant. > > Mitigation: on a stock kernel, devtmpfs creates /dev/dlm_plock as > 0600 root:root, so steps 1-4 are only reachable where the node is > exposed to a less privileged principal =E2=80=94 e.g. udev MODE=3D0666, > container bind-mount of the node, or an fd passed via SCM_RIGHTS. > The in-kernel capability gap is real regardless of node mode. > > Reproduction (kernel 7.2.0-rc3, dlm loaded): > > # ./exploit_h2 # as root > [*] node /dev/dlm_plock mode=3D0600 uid=3D0 gid=3D0 > [!!!] AUTH BYPASS: opened with no capability check (fd=3D3) > [!!!] FORGE ACCEPTED: kernel accepted forged plock result (rv=3D0); > pending ops are grant-forgeable > [VULNERABLE] open + read-leak + grant-forge demonstrated > > The "FORGE ACCEPTED" line means dev_write() returned sizeof(info), > i.e. the write path is reachable and the version check passed; it > does not by itself mean a grant was applied. Demonstrating an > actual forged grant requires a concurrent plock op on recv_list to > match against. > > $ setpriv --reuid 65534 --regid 65534 ./exploit_h2 > [OK ] open denied: Permission denied # devtmpfs 0600, > not a kernel cap check > > Fix: add a .open callback that requires CAP_SYS_ADMIN, and set > .mode =3D 0600 on the miscdevice so the explicit expectation matches > the devtmpfs default and survives future defaults. > > Signed-off-by: Haofeng Li <[email protected]> Acked-by: Alexander Aring <[email protected]> Thanks. - Alex