CVE-2026-74348: ocfs2/dlm: require a ref for locking_state debugfs open
In the Linux kernel, the following vulnerability has been resolved:
ocfs2/dlm: require a ref for lockingstate debugfs open
debuglockresopen() copies inode->iprivate into struct debuglockres and debuglockresrelease() later drops that pointer with dlmput(). That only works if open successfully pins the struct dlmctxt.
Today open calls dlmgrab(dlm) but ignores its return value. Once the last domain unregister has removed the context from dlmdomains, dlmgrab() returns NULL, yet open still stores the raw pointer and returns success. The later release path is outside the debugfs removal barrier, so it can call dlmput() after dlmfreectxtmem() has freed the context. KASAN reports this as a slab-use-after-free in dlmput() called from debuglockresrelease().
Fail the open when dlmgrab() cannot acquire the reference and unwind the seqfile private state before returning. That keeps lockingstate from handing out a file descriptor whose release path does not own the dlmctxt.
The buggy scenario involves two paths, with each column showing the order within that path:
lockingstate debugfs open: last domain unregister: 1. debuglockresopen() reads 1. dlmunregisterdomain() calls inode->iprivate. dlmcompletedlmshutdown(). 2. debuglockresopen() calls 2. shutdown removes the dlmctxt from dlmgrab(dlm) and gets NULL. dlmdomains. 3. open still stores the raw dlm 3. final teardown reaches pointer in dl->dlctxt and dlmfreectxtmem() and frees it. returns success. 4. debuglockresrelease() later calls dlmput(dl->dlctxt).
Validation reproduced this kernel report: KASAN slab-use-after-free in dlmput+0x82/0x200 RIP: 0033:0x7f4d349bc9e0 The buggy address belongs to the object at ffff888103a3c000 which belongs to the cache kmalloc-2k of size 2048 The buggy address is located 816 bytes inside of freed 2048-byte region [ffff888103a3c000, ffff888103a3c800) Write of size 4 Call trace: dumpstacklvl+0x66/0xa0 (?:?) printreport+0xd0/0x630 (?:?) dlmput+0x82/0x200 (?:?) srsoaliasreturnthunk+0x5/0xfbef5 (?:?) virtaddrvalid+0x188/0x2f0 (?:?) kasanreport+0xe4/0x120 (?:?) kasancheckrange+0x105/0x1b0 (?:?) debuglockresrelease+0x53/0x80 (fs/ocfs2/dlm/dlmdebug.c:587) dlmput+0x9/0x200 (?:?) debuglockresrelease+0x5c/0x80 (fs/ocfs2/dlm/dlmdebug.c:587) fullproxyrelease+0x67/0x90 (?:?) fput+0x1df/0x4b0 (?:?) dorawspinlock+0x10f/0x1b0 (?:?) fputclosesync+0xd2/0x170 (?:?) x64sysclose+0x55/0x90 (?:?) dosyscall64+0x10c/0x640 (arch/x86/entry/syscall64.c:87) irqentryexit+0xac/0x6e0 (?:?) entrySYSCALL64afterhwframe+0x77/0x7f (?:?) Freed by task stack: kasansavestack+0x33/0x60 (?:?) kasansavetrack+0x14/0x30 (?:?) kasansavefreeinfo+0x3b/0x60 (?:?) kasanslabfree+0x5f/0x80 (?:?) kfree+0x30f/0x580 (?:?) dlmput+0x1ce/0x200 (?:?) dlmunregisterdomain+0xf6/0xb30 (?:?) o2cbclusterdisconnect+0x6b/0x90 (?:?) ocfs2clusterdisconnect+0x41/0x70 (?:?) ocfs2dlmshutdown+0x1c4/0x220 (?:?) ocfs2dismountvolume+0x38a/0x550 (?:?) genericshutdownsuper+0xc3/0x220 (?:?) killblocksuper+0x29/0x60 (?:?) deactivatelockedsuper+0x66/0xe0 (?:?) cleanupmnt+0x13d/0x210 (?:?) taskworkrun+0xfa/0x170 (?:?) exittousermodeloop+0xd6/0x430 (?:?) dosyscall64+0x3cb/0x640 (arch/x86/entry/syscall64.c:87) entrySYSCALL64afterhwframe+0x77/0x7f (?:?)