]>
Commit | Line | Data |
---|---|---|
bb104d9e SL |
1 | From a623478dc7f1e90a67118dbcc58e9aedae48d68f Mon Sep 17 00:00:00 2001 |
2 | From: Chao Yu <yuchao0@huawei.com> | |
3 | Date: Mon, 15 Apr 2019 15:30:51 +0800 | |
4 | Subject: f2fs: fix to do sanity check on valid block count of segment | |
5 | ||
6 | [ Upstream commit e95bcdb2fefa129f37bd9035af1d234ca92ee4ef ] | |
7 | ||
8 | As Jungyeon reported in bugzilla: | |
9 | ||
10 | https://bugzilla.kernel.org/show_bug.cgi?id=203233 | |
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_13.c | |
26 | mkdir test | |
27 | mount -t f2fs tmp.img test | |
28 | cp a.out test | |
29 | cd test | |
30 | sudo ./a.out | |
31 | sync | |
32 | ||
33 | - Kernel messages | |
34 | F2FS-fs (sdb): Bitmap was wrongly set, blk:4608 | |
35 | kernel BUG at fs/f2fs/segment.c:2102! | |
36 | RIP: 0010:update_sit_entry+0x394/0x410 | |
37 | Call Trace: | |
38 | f2fs_allocate_data_block+0x16f/0x660 | |
39 | do_write_page+0x62/0x170 | |
40 | f2fs_do_write_node_page+0x33/0xa0 | |
41 | __write_node_page+0x270/0x4e0 | |
42 | f2fs_sync_node_pages+0x5df/0x670 | |
43 | f2fs_write_checkpoint+0x372/0x1400 | |
44 | f2fs_sync_fs+0xa3/0x130 | |
45 | f2fs_do_sync_file+0x1a6/0x810 | |
46 | do_fsync+0x33/0x60 | |
47 | __x64_sys_fsync+0xb/0x10 | |
48 | do_syscall_64+0x43/0xf0 | |
49 | entry_SYSCALL_64_after_hwframe+0x44/0xa9 | |
50 | ||
51 | sit.vblocks and sum valid block count in sit.valid_map may be | |
52 | inconsistent, segment w/ zero vblocks will be treated as free | |
53 | segment, while allocating in free segment, we may allocate a | |
54 | free block, if its bitmap is valid previously, it can cause | |
55 | kernel crash due to bitmap verification failure. | |
56 | ||
57 | Anyway, to avoid further serious metadata inconsistence and | |
58 | corruption, it is necessary and worth to detect SIT | |
59 | inconsistence. So let's enable check_block_count() to verify | |
60 | vblocks and valid_map all the time rather than do it only | |
61 | CONFIG_F2FS_CHECK_FS is enabled. | |
62 | ||
63 | Signed-off-by: Chao Yu <yuchao0@huawei.com> | |
64 | Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> | |
65 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
66 | --- | |
67 | fs/f2fs/segment.h | 3 +-- | |
68 | 1 file changed, 1 insertion(+), 2 deletions(-) | |
69 | ||
70 | diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h | |
71 | index 893723978f5e..faca7fdb54b0 100644 | |
72 | --- a/fs/f2fs/segment.h | |
73 | +++ b/fs/f2fs/segment.h | |
74 | @@ -613,7 +613,6 @@ static inline void verify_block_addr(struct f2fs_io_info *fio, block_t blk_addr) | |
75 | static inline int check_block_count(struct f2fs_sb_info *sbi, | |
76 | int segno, struct f2fs_sit_entry *raw_sit) | |
77 | { | |
78 | -#ifdef CONFIG_F2FS_CHECK_FS | |
79 | bool is_valid = test_bit_le(0, raw_sit->valid_map) ? true : false; | |
80 | int valid_blocks = 0; | |
81 | int cur_pos = 0, next_pos; | |
82 | @@ -640,7 +639,7 @@ static inline int check_block_count(struct f2fs_sb_info *sbi, | |
83 | set_sbi_flag(sbi, SBI_NEED_FSCK); | |
84 | return -EINVAL; | |
85 | } | |
86 | -#endif | |
87 | + | |
88 | /* check segment usage, and check boundary of a given segment number */ | |
89 | if (unlikely(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg | |
90 | || segno > TOTAL_SEGS(sbi) - 1)) { | |
91 | -- | |
92 | 2.20.1 | |
93 |