]>
Commit | Line | Data |
---|---|---|
37554d48 SL |
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() | |
5 | ||
6 | [ Upstream commit 05573d6ccf702df549a7bdeabef31e4753df1a90 ] | |
7 | ||
8 | As Jungyeon reported in bugzilla: | |
9 | ||
10 | https://bugzilla.kernel.org/show_bug.cgi?id=203239 | |
11 | ||
12 | - Overview | |
13 | When mounting the attached crafted image and running program, following errors are reported. | |
14 | Additionally, it hangs on sync after running program. | |
15 | ||
16 | The image is intentionally fuzzed from a normal f2fs image for testing. | |
17 | Compile options for F2FS are as follows. | |
18 | CONFIG_F2FS_FS=y | |
19 | CONFIG_F2FS_STAT_FS=y | |
20 | CONFIG_F2FS_FS_XATTR=y | |
21 | CONFIG_F2FS_FS_POSIX_ACL=y | |
22 | CONFIG_F2FS_CHECK_FS=y | |
23 | ||
24 | - Reproduces | |
25 | cc poc_15.c | |
26 | ./run.sh f2fs | |
27 | sync | |
28 | ||
29 | - Kernel messages | |
30 | ------------[ cut here ]------------ | |
31 | kernel BUG at fs/f2fs/segment.c:3162! | |
32 | RIP: 0010:f2fs_inplace_write_data+0x12d/0x160 | |
33 | Call Trace: | |
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 | |
42 | do_fsync+0x33/0x60 | |
43 | __x64_sys_fsync+0xb/0x10 | |
44 | do_syscall_64+0x43/0xf0 | |
45 | entry_SYSCALL_64_after_hwframe+0x44/0xa9 | |
46 | ||
47 | The reason is f2fs_inplace_write_data() will trigger kernel panic due | |
48 | to data block locates in node type segment. | |
49 | ||
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. | |
52 | ||
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> | |
56 | --- | |
57 | fs/f2fs/segment.c | 9 +++++++-- | |
58 | 1 file changed, 7 insertions(+), 2 deletions(-) | |
59 | ||
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) | |
65 | { | |
66 | int err; | |
67 | struct f2fs_sb_info *sbi = fio->sbi; | |
68 | + unsigned int segno; | |
69 | ||
70 | fio->new_blkaddr = fio->old_blkaddr; | |
71 | /* i/o temperature is needed for passing down write hints */ | |
72 | __get_segment_type(fio); | |
73 | ||
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); | |
77 | + | |
78 | + if (!IS_DATASEG(get_seg_entry(sbi, segno)->type)) { | |
79 | + set_sbi_flag(sbi, SBI_NEED_FSCK); | |
80 | + return -EFAULT; | |
81 | + } | |
82 | ||
83 | stat_inc_inplace_blocks(fio->sbi); | |
84 | ||
85 | -- | |
86 | 2.20.1 | |
87 |