mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] fs/ntfs3: use ni_lock_dir() in ntfs_readdir()
@ 2026-10-13 19:39 syzbot
  0 siblings, 0 replies; only message in thread
From: syzbot @ 2026-10-13 19:39 UTC (permalink / raw)
  To: syzkaller-bugs, Aleksandr Nogikh, Konstantin Komarov, ntfs3,
	ZhengYuan Huang
  Cc: linux-kernel, syzbot

From: Aleksandr Nogikh <nogikh@google.com>

A circular locking dependency warning is detected by lockdep between
&ni->ni_lock and mapping.invalidate_lock when getdents64() writes into a
memory-mapped buffer while an operation such as fallocate() runs
concurrently on a regular file:

 WARNING: possible circular locking dependency detected
 task is trying to acquire lock:
 ffff88819b6dbb20 (mapping.invalidate_lock#3){++++}-{4:4}, at:
 filemap_fault+0x6e0/0x13c0 mm/filemap.c:3585
 but task is already holding lock:
 ffff88819b6997e8 (&ni->ni_lock/5){+.+.}-{4:4}, at:
 ntfs_readdir+0x717/0xf70 fs/ntfs3/dir.c:541
 which lock already depends on the new lock.

 the existing dependency chain (in reverse order) is:

  -> #1 (&ni->ni_lock/5){+.+.}-{4:4}:
        ni_lock fs/ntfs3/ntfs_fs.h:1247 [inline]
        ntfs_fallocate+0x56a/0x1080 fs/ntfs3/file.c:535
        vfs_fallocate+0x663/0x7f0 fs/open.c:338
        ioctl_preallocate fs/ioctl.c:289 [inline]
        file_ioctl+0x5db/0x7e0 fs/ioctl.c:332
        do_vfs_ioctl+0xc2a/0x1550 fs/ioctl.c:576

  -> #0 (mapping.invalidate_lock#3){++++}-{4:4}:
        filemap_invalidate_lock_shared include/linux/fs.h:1089 [inline]
        filemap_fault+0x6e0/0x13c0 mm/filemap.c:3585
        __do_fault+0x138/0x2a0 mm/memory.c:5565
        handle_pte_fault mm/memory.c:6558 [inline]
        __handle_mm_fault mm/memory.c:6707 [inline]
        handle_mm_fault+0x100a/0x28a0 mm/memory.c:6876
        do_user_addr_fault+0x746/0x1340 arch/x86/mm/fault.c:1394
        exc_page_fault+0x6a/0xc0 arch/x86/mm/fault.c:1536
        filldir64+0x2bc/0x620 fs/readdir.c:-1
        dir_emit include/linux/fs.h:3610 [inline]
        ntfs_dir_emit fs/ntfs3/dir.c:388 [inline]
        ntfs_read_hdr+0x8a7/0xc10 fs/ntfs3/dir.c:429
        ntfs_readdir+0x9ab/0xf70 fs/ntfs3/dir.c:589
        iterate_dir+0x3ea/0x8a0 fs/readdir.c:114
        __do_sys_getdents64 fs/readdir.c:404 [inline]

The warning occurs because ntfs_fallocate() on a regular file acquires
mapping.invalidate_lock and then calls ni_lock(), which locks the regular
file inode's ni_lock with the default subclass NTFS_INODE_MUTEX_NORMAL
(subclass 5). Meanwhile, ntfs_readdir() on a directory inode also uses
ni_lock() with subclass 5, and while holding the lock across directory
traversal, calls dir_emit() to fill directory entries into the user buffer.
If that buffer is backed by a memory-mapped file, writing to it triggers a
page fault (filemap_fault()), which acquires the mapped file's
mapping.invalidate_lock. Because lockdep sees mapping.invalidate_lock ->
ni_lock (subclass 5) in fallocate and ni_lock (subclass 5) ->
mapping.invalidate_lock in readdir, it flags a circular locking dependency.

This is a false positive because the two operations involve distinct
inodes: readdir holds the mutex of the directory inode, while the page
fault acquires the invalidate_lock of the regular file whose pages back the
user buffer, so an actual deadlock cannot occur.

In ntfs3, directory inodes are intended to be locked with ni_lock_dir(),
which uses the lockdep subclass NTFS_INODE_MUTEX_PARENT (subclass 6). This
subclass hierarchy is already used by other directory operations like
ntfs_lookup(), ntfs_create_inode(), ntfs_link(), ntfs_unlink(), and
ntfs_rename(). Replace ni_lock() with ni_lock_dir() in ntfs_readdir() when
loading subrecords and when traversing directory metadata. This changes the
directory lock subclass to NTFS_INODE_MUTEX_PARENT (6), establishing the
hierarchy ni_lock_dir (subclass 6) -> mapping.invalidate_lock -> ni_lock
(subclass 5) and eliminating the false lockdep warning.

Fixes: d62cf685d12e ("fs/ntfs3: hold ni_lock across readdir metadata walk")
Assisted-by: Gemini:gemini-3.8-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by: syzbot+7736960b837908f3a81d@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=7736960b837908f3a81d
Link: https://syzkaller.appspot.com/ai_job?id=fae916f3-c2b4-47da-86b5-063a011b5c01
Signed-off-by: Aleksandr Nogikh <nogikh@google.com>

---
diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c
index eb9152e9f..8bf62d2fb 100644
--- a/fs/ntfs3/dir.c
+++ b/fs/ntfs3/dir.c
@@ -522,7 +522,7 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx)
 		 * Load all subrecords to avoid 'write' access to 'ni' during
 		 * directory reading.
 		 */
-		ni_lock(ni);
+		ni_lock_dir(ni);
 		if (!ni->mi_loaded && ni->attr_list.size) {
 			err = ni_load_all_mi(ni);
 			if (!err)
@@ -538,7 +538,7 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx)
 	 * once is not enough if concurrent writeback can still compact ATTR_LIST
 	 * entries and free the record that ntfs_read_hdr() is currently walking.
 	 */
-	ni_lock(ni);
+	ni_lock_dir(ni);
 
 	root = indx_get_root(&ni->dir, ni, NULL, NULL);
 	if (!root) {


base-commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907
-- 
See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
The person who has signed off on the patch is responsible for
addressing comments.
syzbot engineers can be reached at syzkaller@googlegroups.com.

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-10-13 19:40 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-13 19:39 [PATCH] fs/ntfs3: use ni_lock_dir() in ntfs_readdir() syzbot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®