Skip to content

Commit d99208b

Browse files
ea1davisaalexandrovich
authored andcommitted
fs/ntfs3: cancle set bad inode after removing name fails
The reproducer uses a file0 on a ntfs3 file system with a corrupted i_link. When renaming, the file0's inode is marked as a bad inode because the file name cannot be deleted. The underlying bug is that make_bad_inode() is called on a live inode. In some cases it's "icache lookup finds a normal inode, d_splice_alias() is called to attach it to dentry, while another thread decides to call make_bad_inode() on it - that would evict it from icache, but we'd already found it there earlier". In some it's outright "we have an inode attached to dentry - that's how we got it in the first place; let's call make_bad_inode() on it just for shits and giggles". Fixes: 78ab59f ("fs/ntfs3: Rework file operations") Reported-by: syzbot+1aa90f0eb1fc3e77d969@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=1aa90f0eb1fc3e77d969 Signed-off-by: Edward Adam Davis <eadavis@qq.com> Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
1 parent e841ecb commit d99208b

3 files changed

Lines changed: 7 additions & 13 deletions

File tree

fs/ntfs3/frecord.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3003,8 +3003,7 @@ int ni_add_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
30033003
* ni_rename - Remove one name and insert new name.
30043004
*/
30053005
int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni,
3006-
struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de,
3007-
bool *is_bad)
3006+
struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de)
30083007
{
30093008
int err;
30103009
struct NTFS_DE *de2 = NULL;
@@ -3027,8 +3026,8 @@ int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni,
30273026
err = ni_add_name(new_dir_ni, ni, new_de);
30283027
if (!err) {
30293028
err = ni_remove_name(dir_ni, ni, de, &de2, &undo);
3030-
if (err && ni_remove_name(new_dir_ni, ni, new_de, &de2, &undo))
3031-
*is_bad = true;
3029+
WARN_ON(err && ni_remove_name(new_dir_ni, ni, new_de, &de2,
3030+
&undo));
30323031
}
30333032

30343033
/*

fs/ntfs3/namei.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ static int ntfs_rename(struct mnt_idmap *idmap, struct inode *dir,
244244
struct ntfs_inode *ni = ntfs_i(inode);
245245
struct inode *new_inode = d_inode(new_dentry);
246246
struct NTFS_DE *de, *new_de;
247-
bool is_same, is_bad;
247+
bool is_same;
248248
/*
249249
* de - memory of PATH_MAX bytes:
250250
* [0-1024) - original name (dentry->d_name)
@@ -313,12 +313,8 @@ static int ntfs_rename(struct mnt_idmap *idmap, struct inode *dir,
313313
if (dir_ni != new_dir_ni)
314314
ni_lock_dir2(new_dir_ni);
315315

316-
is_bad = false;
317-
err = ni_rename(dir_ni, new_dir_ni, ni, de, new_de, &is_bad);
318-
if (is_bad) {
319-
/* Restore after failed rename failed too. */
320-
_ntfs_bad_inode(inode);
321-
} else if (!err) {
316+
err = ni_rename(dir_ni, new_dir_ni, ni, de, new_de);
317+
if (!err) {
322318
simple_rename_timestamp(dir, dentry, new_dir, new_dentry);
323319
mark_inode_dirty(inode);
324320
mark_inode_dirty(dir);

fs/ntfs3/ntfs_fs.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,8 +577,7 @@ int ni_add_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,
577577
struct NTFS_DE *de);
578578

579579
int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni,
580-
struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de,
581-
bool *is_bad);
580+
struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de);
582581

583582
bool ni_is_dirty(struct inode *inode);
584583

0 commit comments

Comments
 (0)