Skip to content

Commit 677a82b

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: fix to do sanity check for inline inode
Yanming reported a kernel bug in Bugzilla kernel [1], which can be reproduced. The bug message is: The kernel message is shown below: kernel BUG at fs/inode.c:611! Call Trace: evict+0x282/0x4e0 __dentry_kill+0x2b2/0x4d0 dput+0x2dd/0x720 do_renameat2+0x596/0x970 __x64_sys_rename+0x78/0x90 do_syscall_64+0x3b/0x90 [1] https://bugzilla.kernel.org/show_bug.cgi?id=215895 The bug is due to fuzzed inode has both inline_data and encrypted flags. During f2fs_evict_inode(), as the inode was deleted by rename(), it will cause inline data conversion due to conflicting flags. The page cache will be polluted and the panic will be triggered in clear_inode(). Try fixing the bug by doing more sanity checks for inline data inode in sanity_check_inode(). Cc: [email protected] Reported-by: Ming Yan <[email protected]> Signed-off-by: Chao Yu <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent 958ed92 commit 677a82b

File tree

3 files changed

+26
-7
lines changed

3 files changed

+26
-7
lines changed

fs/f2fs/f2fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4019,6 +4019,7 @@ extern struct kmem_cache *f2fs_inode_entry_slab;
40194019
* inline.c
40204020
*/
40214021
bool f2fs_may_inline_data(struct inode *inode);
4022+
bool f2fs_sanity_check_inline_data(struct inode *inode);
40224023
bool f2fs_may_inline_dentry(struct inode *inode);
40234024
void f2fs_do_read_inline_data(struct page *page, struct page *ipage);
40244025
void f2fs_truncate_inline_inode(struct inode *inode,

fs/f2fs/inline.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,40 @@
1414
#include "node.h"
1515
#include <trace/events/f2fs.h>
1616

17-
bool f2fs_may_inline_data(struct inode *inode)
17+
static bool support_inline_data(struct inode *inode)
1818
{
1919
if (f2fs_is_atomic_file(inode))
2020
return false;
21-
2221
if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode))
2322
return false;
24-
2523
if (i_size_read(inode) > MAX_INLINE_DATA(inode))
2624
return false;
25+
return true;
26+
}
2727

28-
if (f2fs_post_read_required(inode))
28+
bool f2fs_may_inline_data(struct inode *inode)
29+
{
30+
if (!support_inline_data(inode))
2931
return false;
3032

31-
return true;
33+
return !f2fs_post_read_required(inode);
34+
}
35+
36+
bool f2fs_sanity_check_inline_data(struct inode *inode)
37+
{
38+
if (!f2fs_has_inline_data(inode))
39+
return false;
40+
41+
if (!support_inline_data(inode))
42+
return true;
43+
44+
/*
45+
* used by sanity_check_inode(), when disk layout fields has not
46+
* been synchronized to inmem fields.
47+
*/
48+
return (S_ISREG(inode->i_mode) &&
49+
(file_is_encrypt(inode) || file_is_verity(inode) ||
50+
(F2FS_I(inode)->i_flags & F2FS_COMPR_FL)));
3251
}
3352

3453
bool f2fs_may_inline_dentry(struct inode *inode)

fs/f2fs/inode.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,7 @@ static bool sanity_check_inode(struct inode *inode, struct page *node_page)
276276
}
277277
}
278278

279-
if (f2fs_has_inline_data(inode) &&
280-
(!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode))) {
279+
if (f2fs_sanity_check_inline_data(inode)) {
281280
set_sbi_flag(sbi, SBI_NEED_FSCK);
282281
f2fs_warn(sbi, "%s: inode (ino=%lx, mode=%u) should not have inline_data, run fsck to fix",
283282
__func__, inode->i_ino, inode->i_mode);

0 commit comments

Comments
 (0)