1 ext4: add block bitmap validation
3 From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
5 When a new block bitmap is read from disk in read_block_bitmap()
6 there are a few bits that should ALWAYS be set. In particular,
7 the blocks given corresponding to block bitmap, inode bitmap and inode tables.
8 Validate the block bitmap against these blocks.
10 Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
12 fs/ext4/balloc.c | 97 ++++++++++++++++++++++++++++++++++++++++++++---------
13 1 files changed, 80 insertions(+), 17 deletions(-)
15 diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
16 index ff3428e..3b9b07b 100644
17 --- a/fs/ext4/balloc.c
18 +++ b/fs/ext4/balloc.c
19 @@ -189,13 +189,65 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb,
23 +static int ext4_valid_block_bitmap(struct super_block *sb,
24 + struct ext4_group_desc *desc,
25 + unsigned int block_group,
26 + struct buffer_head *bh)
28 + ext4_grpblk_t offset;
29 + ext4_grpblk_t next_zero_bit;
30 + ext4_fsblk_t bitmap_blk;
31 + ext4_fsblk_t group_first_block;
33 + if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
34 + /* with FLEX_BG, the inode/block bitmaps and itable
35 + * blocks may not be in the group at all
36 + * so the bitmap validation will be skipped for those groups
37 + * or it has to also read the block group where the bitmaps
38 + * are located to verify they are set.
42 + group_first_block = ext4_group_first_block_no(sb, block_group);
44 + /* check whether block bitmap block number is set */
45 + bitmap_blk = ext4_block_bitmap(sb, desc);
46 + offset = bitmap_blk - group_first_block;
47 + if (!ext4_test_bit(offset, bh->b_data))
48 + /* bad block bitmap */
51 + /* check whether the inode bitmap block number is set */
52 + bitmap_blk = ext4_inode_bitmap(sb, desc);
53 + offset = bitmap_blk - group_first_block;
54 + if (!ext4_test_bit(offset, bh->b_data))
55 + /* bad block bitmap */
58 + /* check whether the inode table block number is set */
59 + bitmap_blk = ext4_inode_table(sb, desc);
60 + offset = bitmap_blk - group_first_block;
61 + next_zero_bit = ext4_find_next_zero_bit(bh->b_data,
62 + offset + EXT4_SB(sb)->s_itb_per_group,
64 + if (next_zero_bit >= offset + EXT4_SB(sb)->s_itb_per_group)
65 + /* good bitmap for inode tables */
69 + ext4_error(sb, __FUNCTION__,
70 + "Invalid block bitmap - "
71 + "block_group = %d, block = %llu",
72 + block_group, bitmap_blk);
78 * @block_group: given block group
80 - * Read the bitmap for a given block_group, reading into the specified
81 - * slot in the superblock's bitmap cache.
82 + * Read the bitmap for a given block_group,and validate the
83 + * bits for block/inode/inode tables are set in the bitmaps
85 * Return buffer_head on success or NULL in case of failure.
87 @@ -210,25 +262,36 @@ read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
90 bitmap_blk = ext4_block_bitmap(sb, desc);
91 + bh = sb_getblk(sb, bitmap_blk);
92 + if (unlikely(!bh)) {
93 + ext4_error(sb, __FUNCTION__,
94 + "Cannot read block bitmap - "
95 + "block_group = %d, block_bitmap = %llu",
96 + block_group, bitmap_blk);
99 + if (bh_uptodate_or_lock(bh))
102 if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
103 - bh = sb_getblk(sb, bitmap_blk);
104 - if (!buffer_uptodate(bh)) {
106 - if (!buffer_uptodate(bh)) {
107 - ext4_init_block_bitmap(sb, bh, block_group,
109 - set_buffer_uptodate(bh);
114 - bh = sb_bread(sb, bitmap_blk);
115 + ext4_init_block_bitmap(sb, bh, block_group, desc);
116 + set_buffer_uptodate(bh);
121 - ext4_error (sb, __FUNCTION__,
122 + if (bh_submit_read(bh) < 0) {
124 + ext4_error(sb, __FUNCTION__,
125 "Cannot read block bitmap - "
126 - "block_group = %lu, block_bitmap = %llu",
127 + "block_group = %d, block_bitmap = %llu",
128 block_group, bitmap_blk);
131 + if (!ext4_valid_block_bitmap(sb, desc, block_group, bh)) {
140 1.5.3.5.652.gf192c-dirty