1 From 93ab4f1ac925435b36cd9c3f653efca61e517da0 Mon Sep 17 00:00:00 2001
2 From: Chao Yu <yuchao0@huawei.com>
3 Date: Mon, 15 Apr 2019 15:30:52 +0800
4 Subject: f2fs: fix to avoid panic in f2fs_inplace_write_data()
6 [ Upstream commit 05573d6ccf702df549a7bdeabef31e4753df1a90 ]
8 As Jungyeon reported in bugzilla:
10 https://bugzilla.kernel.org/show_bug.cgi?id=203239
13 When mounting the attached crafted image and running program, following errors are reported.
14 Additionally, it hangs on sync after running program.
16 The image is intentionally fuzzed from a normal f2fs image for testing.
17 Compile options for F2FS are as follows.
20 CONFIG_F2FS_FS_XATTR=y
21 CONFIG_F2FS_FS_POSIX_ACL=y
22 CONFIG_F2FS_CHECK_FS=y
30 ------------[ cut here ]------------
31 kernel BUG at fs/f2fs/segment.c:3162!
32 RIP: 0010:f2fs_inplace_write_data+0x12d/0x160
34 f2fs_do_write_data_page+0x3c1/0x820
35 __write_data_page+0x156/0x720
36 f2fs_write_cache_pages+0x20d/0x460
37 f2fs_write_data_pages+0x1b4/0x300
38 do_writepages+0x15/0x60
39 __filemap_fdatawrite_range+0x7c/0xb0
40 file_write_and_wait_range+0x2c/0x80
41 f2fs_do_sync_file+0x102/0x810
43 __x64_sys_fsync+0xb/0x10
44 do_syscall_64+0x43/0xf0
45 entry_SYSCALL_64_after_hwframe+0x44/0xa9
47 The reason is f2fs_inplace_write_data() will trigger kernel panic due
48 to data block locates in node type segment.
50 To avoid panic, let's just return error code and set SBI_NEED_FSCK to
51 give a hint to fsck for latter repairing.
53 Signed-off-by: Chao Yu <yuchao0@huawei.com>
54 Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
55 Signed-off-by: Sasha Levin <sashal@kernel.org>
57 fs/f2fs/segment.c | 9 +++++++--
58 1 file changed, 7 insertions(+), 2 deletions(-)
60 diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
61 index 03fa2c4d3d79..8fc3edb6760c 100644
62 --- a/fs/f2fs/segment.c
63 +++ b/fs/f2fs/segment.c
64 @@ -3069,13 +3069,18 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
67 struct f2fs_sb_info *sbi = fio->sbi;
70 fio->new_blkaddr = fio->old_blkaddr;
71 /* i/o temperature is needed for passing down write hints */
72 __get_segment_type(fio);
74 - f2fs_bug_on(sbi, !IS_DATASEG(get_seg_entry(sbi,
75 - GET_SEGNO(sbi, fio->new_blkaddr))->type));
76 + segno = GET_SEGNO(sbi, fio->new_blkaddr);
78 + if (!IS_DATASEG(get_seg_entry(sbi, segno)->type)) {
79 + set_sbi_flag(sbi, SBI_NEED_FSCK);
83 stat_inc_inplace_blocks(fio->sbi);