mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 02:24:24 +02:00
f2fs: Add sanity checks before unlinking and loading inodes
Add check for inode->i_nlink == 1 for directories during unlink, as their value is decremented twice, which can trigger a warning in drop_nlink. In such case mark the filesystem as corrupted and return from the function call with the relevant failure return value. Additionally add the check for i_nlink == 1 in sanity_check_inode in order to detect on-disk corruption early. Reported-by: syzbot+c07d47c7bc68f47b9083@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=c07d47c7bc68f47b9083 Tested-by: syzbot+c07d47c7bc68f47b9083@syzkaller.appspotmail.com Signed-off-by: Nikola Z. Ivanov <zlatistiv@gmail.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
9b3c8336c6
commit
f37981edcd
|
|
@ -294,6 +294,12 @@ static bool sanity_check_inode(struct inode *inode, struct folio *node_folio)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (S_ISDIR(inode->i_mode) && unlikely(inode->i_nlink == 1)) {
|
||||
f2fs_warn(sbi, "%s: directory inode (ino=%lx) has a single i_nlink",
|
||||
__func__, inode->i_ino);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (f2fs_has_extra_attr(inode)) {
|
||||
if (!f2fs_sb_has_extra_attr(sbi)) {
|
||||
f2fs_warn(sbi, "%s: inode (ino=%lx) is with extra_attr, but extra_attr feature is off",
|
||||
|
|
|
|||
|
|
@ -570,12 +570,13 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
|
|||
}
|
||||
|
||||
if (unlikely(inode->i_nlink == 0)) {
|
||||
f2fs_warn(F2FS_I_SB(inode), "%s: inode (ino=%lx) has zero i_nlink",
|
||||
f2fs_warn(sbi, "%s: inode (ino=%lx) has zero i_nlink",
|
||||
__func__, inode->i_ino);
|
||||
err = -EFSCORRUPTED;
|
||||
set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
|
||||
f2fs_folio_put(folio, false);
|
||||
goto out;
|
||||
goto corrupted;
|
||||
} else if (S_ISDIR(inode->i_mode) && unlikely(inode->i_nlink == 1)) {
|
||||
f2fs_warn(sbi, "%s: directory inode (ino=%lx) has a single i_nlink",
|
||||
__func__, inode->i_ino);
|
||||
goto corrupted;
|
||||
}
|
||||
|
||||
f2fs_balance_fs(sbi, true);
|
||||
|
|
@ -601,6 +602,12 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
|
|||
|
||||
if (IS_DIRSYNC(dir))
|
||||
f2fs_sync_fs(sbi->sb, 1);
|
||||
|
||||
goto out;
|
||||
corrupted:
|
||||
err = -EFSCORRUPTED;
|
||||
set_sbi_flag(sbi, SBI_NEED_FSCK);
|
||||
f2fs_folio_put(folio, false);
|
||||
out:
|
||||
trace_f2fs_unlink_exit(inode, err);
|
||||
return err;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user