linux/fs/ntfs3
Christian Brauner 1abd643f37
fs/ntfs3: use d_instantiate_new() in ntfs_create_inode() and murder syzbot's "WARNING in do_new_mount" saga
ntfs_create_inode() creates a new inode via ntfs_new_inode(). It hashes
it with insert_inode_locked() and so it's marked as I_NEW until
unlock_new_inode().

ntfs 3 calls d_instantiate() in between though... Since the dentry was
already hashed by the lookup before the create any path walk finds it
without touching the parent's i_rwsem and so can lock the inode.

If the inode is a directory unlock_new_inode() calls
lockdep_annotate_inode_mutex_key() and marks i_rwsem with the
i_mutex_dir_key class.

That resets the count and the owner of a lock somebody else may already
hold by now...

syzbot has been spamming us with the same godforsaken bug

  "WARNING in do_new_mount"

since 2023. I can't take it anymore so I went looking. Afaict, syzbot's
executor chdirs into a freshly mounted ntfs3 image, creates a
directory and then mounts some pseudofs on it. Everytime the mkdir()
takes longer than syzbot waits mount() runs concurrently:

  mkdir("./sys")                        mount(NULL, "./sys", "sysfs")
  ntfs_create_inode()
    d_instantiate()
                                        user_path_at() finds the dentry
                                        do_lock_mount()
                                          inode_lock(inode)
                                          namespace_lock()
    unlock_new_inode()
      lockdep_annotate_inode_mutex_key()
        init_rwsem(&inode->i_rwsem)
                                        unlock_mount()
                                          inode_unlock(inode)

The mount side then releases a lock that according to the rwsem nobody
holds:

  DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) && ...):
  count = 0x0, magic = 0xffff888043a854e8, owner = 0x0,
  curr 0xffff888000244880, list empty
  WARNING: CPU: 0 PID: 5346 at kernel/locking/rwsem.c:1368 __up_write
  Call Trace:
   inode_unlock include/linux/fs.h:877 [inline]
   unlock_mount fs/namespace.c:2892 [inline]
   do_new_mount_fc fs/namespace.c:3828 [inline]
   do_new_mount+0x777/0xa40 fs/namespace.c:3887

On PREEMPT_RT the same thing shows up as

  DEBUG_LOCKS_WARN_ON(rt_mutex_owner(lock) != current)
  WARNING: kernel/locking/rtmutex_common.h:193 at rt_mutex_slowunlock

The up_write() underflows the reset count. A following inode_lock() on
that directory then never returns. A path walk into the new directory
racing with the mkdir() corrupts the lock the same way via
inode_lock_shared() in lookup_slow().

Switch to d_instantiate_new() and drop the trailing unlock_new_inode().
All error paths bail out before that point with I_NEW still set and
keep using discard_new_inode().

May we never see this fscking bug report again.

Link: https://patch.msgid.link/20260909-work-ntfs3-d_instantiate_new-v1-1-2db697162ce8@kernel.org
Fixes: 82cae269cf ("fs/ntfs3: Add initialization of super block")
Reviewed-by: Jan Kara <jack@suse.cz>
Cc: stable@vger.kernel.org # v5.15+
Reported-by: syzbot+2a13ad6914e6fcec716c@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/6a9beced.a5e650b3.26d8a.000b.GAE@google.com
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-09-10 09:22:06 +02:00
..
lib treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
attrib.c fs/ntfs3: Add basic support for alternative data streams 2026-07-30 10:50:00 +02:00
attrlist.c fs/ntfs3: Add basic support for alternative data streams 2026-07-30 10:50:00 +02:00
bitfunc.c fs/ntfs3: Add ntfs_bitmap_weight_le function and refactoring 2022-11-14 19:50:42 +03:00
bitmap.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
debug.h
dir.c fs/ntfs3: Add basic support for alternative data streams 2026-07-30 10:50:00 +02:00
file.c fs/ntfs3: Add basic support for alternative data streams 2026-07-30 10:50:00 +02:00
frecord.c fs/ntfs3: Add basic support for alternative data streams 2026-07-30 10:50:00 +02:00
fslog.c fs/ntfs3: fix out-of-bounds read in read_log_rec_buf() 2026-08-18 10:35:38 +02:00
fsntfs.c fs/ntfs3: Add basic support for alternative data streams 2026-07-30 10:50:00 +02:00
index.c fs/ntfs3: Fix memory leak in indx_find_sort() 2026-07-30 10:49:41 +02:00
inode.c fs/ntfs3: use d_instantiate_new() in ntfs_create_inode() and murder syzbot's "WARNING in do_new_mount" saga 2026-09-10 09:22:06 +02:00
Kconfig ntfs: add Kconfig and Makefile 2026-02-19 21:51:00 +09:00
lznt.c fs/ntfs3: cosmetic fixes and improvements 2026-07-14 18:41:16 +02:00
Makefile fs/ntfs3: add a subset of W=1 warnings for stricter checks 2026-03-04 10:28:25 +01:00
namei.c Changes for 7.3-rc1 2026-08-20 12:27:02 -07:00
ntfs_fs.h fs/ntfs3: Add basic support for alternative data streams 2026-07-30 10:50:00 +02:00
ntfs.h fs/ntfs3: Add basic support for alternative data streams 2026-07-30 10:50:00 +02:00
record.c fs/ntfs3: reject out-of-range evcn in mi_enum_attr() 2026-08-14 08:50:16 +02:00
run.c fs/ntfs3: cosmetic fixes and improvements 2026-07-14 18:41:16 +02:00
super.c fs/ntfs3: fix integer overflow in MFT cluster validation 2026-08-14 08:49:59 +02:00
upcase.c fs/ntfs3: Add option "nocase" 2022-09-30 17:39:47 +03:00
xattr.c fs/ntfs3: validate ef->size covers the record's name and value 2026-08-18 10:35:39 +02:00