Re: [PATCH v2] f2fs: fix to disallow getting inner inode via f2fs_iget()

From: Chao Yu
Date: Tue Sep 13 2022 - 02:44:39 EST


On 2022/9/13 13:54, Jaegeuk Kim wrote:
On 09/13, Chao Yu wrote:
On 2022/9/12 23:39, Jaegeuk Kim wrote:
On 09/08, Chao Yu wrote:
On 2022/9/8 10:19, Jaegeuk Kim wrote:
On 09/08, Chao Yu wrote:
On 2022/9/8 10:02, Jaegeuk Kim wrote:
On 08/31, Chao Yu wrote:
From: Chao Yu <chao.yu@xxxxxxxx>

Introduce f2fs_iget_inner() for f2fs_fill_super() to get inner inode:
meta inode, node inode or compressed inode, and add f2fs_check_nid_range()
in f2fs_iget() to avoid getting inner inode from external interfaces.

So, we don't want to check the range of inner inode numbers? What'd be the
way to check it's okay?

For node_ino, meta_ino, root_ino, we have checked them in sanity_check_raw_super()
as below:

/* check reserved ino info */
if (le32_to_cpu(raw_super->node_ino) != 1 ||
le32_to_cpu(raw_super->meta_ino) != 2 ||
le32_to_cpu(raw_super->root_ino) != 3) {
f2fs_info(sbi, "Invalid Fs Meta Ino: node(%u) meta(%u) root(%u)",
le32_to_cpu(raw_super->node_ino),
le32_to_cpu(raw_super->meta_ino),
le32_to_cpu(raw_super->root_ino));
return -EFSCORRUPTED;
}

compressed_ino should always be NM_I(sbi)->max_nid, it can be checked in
f2fs_init_compress_inode()?

Hmm, I'm not sure whether we really need this patch, since it'd look better
to handle all the iget with single f2fs_iget?

Well, the main concern is previously f2fs_iget() won't check validation for inner
inode due to it will skip do_read_inode() - f2fs_check_nid_range(), so that in a
fuzzed image, caller may pass inner ino into f2fs_iget(), result in incorrect use
of inner inode. So I add f2fs_check_nid_range() in prior to f2fs_iget_inner() in
f2fs_iget() as below to detect and avoid this case.

FWIW, sanity_check_raw_super() checked the inode numbers.

However, previously, f2fs_iget() will return inner inode to caller directly, if caller
passes meta_ino, node_ino or compress_ino to f2fs_iget()?

Do you want to do sanity check on corrupted dentry? If so, how about checking

Yes, including:

- corrupted ino in dentry
- corrupted ino of orphan inode

As I replied in this thread:

https://lore.kernel.org/lkml/b1c74dc1-8d01-9041-9469-036273c5618d@xxxxxxxxxx/

it in f2fs_iget instead?

if (is_meta_ino(ino)) {
if (!(inode->i_state & I_NEW)
return -EFSCORRUPTED;
goto make_now;
}

Fine to me, let me revise in v3.

Thanks,



Thanks,



+struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
+{
+ int ret;
+
+ ret = f2fs_check_nid_range(F2FS_SB(sb), ino);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return f2fs_iget_inner(sb, ino);