* [PATCH] fs/ntfs3: use d_instantiate_new() in ntfs_create_inode() and murder syzbot's "WARNING in do_new_mount" saga
@ 2026-09-09 9:03 Christian Brauner
2026-09-09 9:18 ` sashiko-bot
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Christian Brauner @ 2026-09-09 9:03 UTC (permalink / raw)
To: Konstantin Komarov, Sebastian Andrzej Siewior, Clark Williams,
linux-fsdevel
Cc: Steven Rostedt, jack, syzkaller-bugs, viro, ntfs3, linux-kernel,
linux-rt-devel, stable, syzbot+2a13ad6914e6fcec716c,
Christian Brauner (Amutable)
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.
Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block")
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>
---
fs/ntfs3/inode.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
index 56b4f6469a28..4ac26c80bd34 100644
--- a/fs/ntfs3/inode.c
+++ b/fs/ntfs3/inode.c
@@ -1866,10 +1866,10 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
goto out6;
/*
- * Call 'd_instantiate' after inode->i_op is set
+ * Call 'd_instantiate_new' after inode->i_op is set
* but before finish_open.
*/
- d_instantiate(dentry, inode);
+ d_instantiate_new(dentry, inode);
/* Set original time. inode times (i_ctime) may be changed in ntfs_init_acl. */
inode_set_atime_to_ts(inode, ni->i_crtime);
@@ -1917,9 +1917,6 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
if (!fnd)
ni_unlock(dir_ni);
- if (!err)
- unlock_new_inode(inode);
-
return err;
}
---
base-commit: 893e11787f78e43b534e252249ac3fff4d1333f8
change-id: 20260909-work-ntfs3-d_instantiate_new-814ad31dea82
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] fs/ntfs3: use d_instantiate_new() in ntfs_create_inode() and murder syzbot's "WARNING in do_new_mount" saga
2026-09-09 9:03 [PATCH] fs/ntfs3: use d_instantiate_new() in ntfs_create_inode() and murder syzbot's "WARNING in do_new_mount" saga Christian Brauner
@ 2026-09-09 9:18 ` sashiko-bot
2026-09-09 11:11 ` Jan Kara
2026-09-10 7:22 ` Christian Brauner
2 siblings, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-09-09 9:18 UTC (permalink / raw)
To: Christian Brauner; +Cc: linux-rt-devel, linux-kernel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] If `ntfs_init_acl()` fails, the error path skips the necessary cleanup for `ATTR_EA`, permanently leaking disk clusters allocated for non-resident extended attributes.
--
commit 44a39faac2ebabd21da92b47785ce2d1e97401b0
Author: Christian Brauner <brauner@kernel.org>
fs/ntfs3: use d_instantiate_new() in ntfs_create_inode() and murder syzbot's "WARNING in do_new_mount" saga
This commit fixes a bug where d_instantiate() was called on an I_NEW inode
before unlock_new_inode(). This caused lockdep lock owner corruption when
paths concurrently locked the directory. The fix switches to using
d_instantiate_new() and drops the trailing unlock_new_inode().
Closes: https://lore.kernel.org/6a9beced.a5e650b3.26d8a.000b.GAE@google.com
> diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
> index 56b4f6469a280..4ac26c80bd34f 100644
> --- a/fs/ntfs3/inode.c
> +++ b/fs/ntfs3/inode.c
[ ... ]
> @@ -1917,9 +1917,6 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
> if (!fnd)
> ni_unlock(dir_ni);
>
> - if (!err)
> - unlock_new_inode(inode);
> -
> return err;
> }
[Severity: High]
This isn't a bug introduced by this patch, but does ntfs_create_inode()
permanently leak disk clusters if ntfs_init_acl() fails?
If ntfs_init_acl() returns an error, the error path jumps to out5:
fs/ntfs3/inode.c:ntfs_create_inode() {
...
#ifdef CONFIG_NTFS3_FS_POSIX_ACL
if (!S_ISLNK(mode) && (sb->s_flags & SB_POSIXACL)) {
err = ntfs_init_acl(idmap, inode, dir);
if (err)
goto out5;
} else
#endif
...
}
Jumping to out5 bypasses the out6 label, which contains the essential
cleanup logic for ATTR_EA:
out6:
attr = ni_find_attr(ni, NULL, NULL, ATTR_EA, NULL, 0, NULL, NULL);
if (attr && attr->non_res) {
/* Delete ATTR_EA, if non-resident. */
struct runs_tree run;
run_init(&run);
attr_set_size(ni, ATTR_EA, NULL, 0, &run, 0, NULL, false);
run_close(&run);
}
out5:
if (!S_ISDIR(mode))
...
If ntfs_init_acl() creates the first ACL (which allocates non-resident
clusters for ATTR_EA via ntfs_set_acl_ex -> ntfs_set_ea -> attr_set_size)
but fails on the second ACL (e.g. ENOMEM), the non-resident ATTR_EA is left
attached to the inode.
The error path then proceeds to out4, clearing RECORD_FLAG_IN_USE on the MFT
record. Later, when the inode is evicted and ni_clear() is called, it checks
is_rec_inuse(). Because the flag was cleared, ni_clear() skips calling
ni_delete_all(), which is the only other function capable of freeing
non-resident attribute clusters.
Could an unprivileged user repeatedly trigger this failure (e.g. by exhausting
memory) to systematically exhaust disk space?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260909-work-ntfs3-d_instantiate_new-v1-1-2db697162ce8@kernel.org?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] fs/ntfs3: use d_instantiate_new() in ntfs_create_inode() and murder syzbot's "WARNING in do_new_mount" saga
2026-09-09 9:03 [PATCH] fs/ntfs3: use d_instantiate_new() in ntfs_create_inode() and murder syzbot's "WARNING in do_new_mount" saga Christian Brauner
2026-09-09 9:18 ` sashiko-bot
@ 2026-09-09 11:11 ` Jan Kara
2026-09-10 7:22 ` Christian Brauner
2 siblings, 0 replies; 4+ messages in thread
From: Jan Kara @ 2026-09-09 11:11 UTC (permalink / raw)
To: Christian Brauner
Cc: Konstantin Komarov, Sebastian Andrzej Siewior, Clark Williams,
linux-fsdevel, Steven Rostedt, jack, syzkaller-bugs, viro, ntfs3,
linux-kernel, linux-rt-devel, stable,
syzbot+2a13ad6914e6fcec716c
On Wed 09-09-26 11:03:18, Christian Brauner wrote:
> 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.
>
> Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block")
> 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>
Looks good. Feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/ntfs3/inode.c | 7 ++-----
> 1 file changed, 2 insertions(+), 5 deletions(-)
>
> diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
> index 56b4f6469a28..4ac26c80bd34 100644
> --- a/fs/ntfs3/inode.c
> +++ b/fs/ntfs3/inode.c
> @@ -1866,10 +1866,10 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
> goto out6;
>
> /*
> - * Call 'd_instantiate' after inode->i_op is set
> + * Call 'd_instantiate_new' after inode->i_op is set
> * but before finish_open.
> */
> - d_instantiate(dentry, inode);
> + d_instantiate_new(dentry, inode);
>
> /* Set original time. inode times (i_ctime) may be changed in ntfs_init_acl. */
> inode_set_atime_to_ts(inode, ni->i_crtime);
> @@ -1917,9 +1917,6 @@ int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
> if (!fnd)
> ni_unlock(dir_ni);
>
> - if (!err)
> - unlock_new_inode(inode);
> -
> return err;
> }
>
>
> ---
> base-commit: 893e11787f78e43b534e252249ac3fff4d1333f8
> change-id: 20260909-work-ntfs3-d_instantiate_new-814ad31dea82
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] fs/ntfs3: use d_instantiate_new() in ntfs_create_inode() and murder syzbot's "WARNING in do_new_mount" saga
2026-09-09 9:03 [PATCH] fs/ntfs3: use d_instantiate_new() in ntfs_create_inode() and murder syzbot's "WARNING in do_new_mount" saga Christian Brauner
2026-09-09 9:18 ` sashiko-bot
2026-09-09 11:11 ` Jan Kara
@ 2026-09-10 7:22 ` Christian Brauner
2 siblings, 0 replies; 4+ messages in thread
From: Christian Brauner @ 2026-09-10 7:22 UTC (permalink / raw)
To: Konstantin Komarov, Sebastian Andrzej Siewior, Clark Williams,
linux-fsdevel, Christian Brauner
Cc: Steven Rostedt, jack, syzkaller-bugs, viro, ntfs3, linux-kernel,
linux-rt-devel, stable, syzbot+2a13ad6914e6fcec716c
On Wed, 09 Sep 2026 11:03:18 +0200, Christian Brauner wrote:
> fs/ntfs3: use d_instantiate_new() in ntfs_create_inode() and murder syzbot's "WARNING in do_new_mount" saga
Applied to the vfs.fixes branch of the vfs/vfs.git tree.
Patches in the vfs.fixes branch should appear in linux-next soon.
Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.
It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.
Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.
tree: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs.fixes
[1/1] fs/ntfs3: use d_instantiate_new() in ntfs_create_inode() and murder syzbot's "WARNING in do_new_mount" saga
https://git.kernel.org/vfs/vfs/c/1abd643f3783
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-09-10 7:22 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-09 9:03 [PATCH] fs/ntfs3: use d_instantiate_new() in ntfs_create_inode() and murder syzbot's "WARNING in do_new_mount" saga Christian Brauner
2026-09-09 9:18 ` sashiko-bot
2026-09-09 11:11 ` Jan Kara
2026-09-10 7:22 ` Christian Brauner
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®