Commit fcc2d8cc authored by Chao Yu's avatar Chao Yu Committed by Jaegeuk Kim
Browse files

f2fs: fix to detect corrupted meta ino



It is possible that ino of dirent or orphan inode is corrupted in a
fuzzed image, occasionally, if corrupted ino is equal to meta ino:
meta_ino, node_ino or compress_ino, caller of f2fs_iget() from below
call paths will get meta inode directly, it's not allowed, let's
add sanity check to detect such cases.

case #1
- recover_dentry
 - __f2fs_find_entry
 - f2fs_iget_retry

case #2
- recover_orphan_inode
 - f2fs_iget_retry

Signed-off-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent d80afefb
Loading
Loading
Loading
Loading
+16 −5
Original line number Diff line number Diff line
@@ -487,6 +487,12 @@ static int do_read_inode(struct inode *inode)
	return 0;
}

static bool is_meta_ino(struct f2fs_sb_info *sbi, unsigned int ino)
{
	return ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi) ||
		ino == F2FS_COMPRESS_INO(sbi);
}

struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
{
	struct f2fs_sb_info *sbi = F2FS_SB(sb);
@@ -498,16 +504,21 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
		return ERR_PTR(-ENOMEM);

	if (!(inode->i_state & I_NEW)) {
		if (is_meta_ino(sbi, ino)) {
			f2fs_err(sbi, "inaccessible inode: %lu, run fsck to repair", ino);
			set_sbi_flag(sbi, SBI_NEED_FSCK);
			ret = -EFSCORRUPTED;
			trace_f2fs_iget_exit(inode, ret);
			iput(inode);
			return ERR_PTR(ret);
		}

		trace_f2fs_iget(inode);
		return inode;
	}
	if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi))
		goto make_now;

#ifdef CONFIG_F2FS_FS_COMPRESSION
	if (ino == F2FS_COMPRESS_INO(sbi))
	if (is_meta_ino(sbi, ino))
		goto make_now;
#endif

	ret = do_read_inode(inode);
	if (ret)