diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2008-02-06 04:40:09 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-06 13:41:20 -0500 |
commit | f762e9054ff84aa90f037a49747ac61b36609d81 (patch) | |
tree | 7f39358385964c8fb101096b23c451ae82f6e58a | |
parent | 01584fa6456dafbaf5a94ad7fb2aa3e3ecd7a7ba (diff) |
ext3: add block bitmap validation
When a new block bitmap is read from disk in read_block_bitmap() there are a
few bits that should ALWAYS be set. In particular, the blocks given
corresponding to block bitmap, inode bitmap and inode tables. Validate the
block bitmap against these blocks.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Cc: <linux-ext4@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/ext3/balloc.c | 78 |
1 files changed, 70 insertions, 8 deletions
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index a8ba7e831278..a26e683780be 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c | |||
@@ -80,13 +80,57 @@ struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb, | |||
80 | return desc + offset; | 80 | return desc + offset; |
81 | } | 81 | } |
82 | 82 | ||
83 | static int ext3_valid_block_bitmap(struct super_block *sb, | ||
84 | struct ext3_group_desc *desc, | ||
85 | unsigned int block_group, | ||
86 | struct buffer_head *bh) | ||
87 | { | ||
88 | ext3_grpblk_t offset; | ||
89 | ext3_grpblk_t next_zero_bit; | ||
90 | ext3_fsblk_t bitmap_blk; | ||
91 | ext3_fsblk_t group_first_block; | ||
92 | |||
93 | group_first_block = ext3_group_first_block_no(sb, block_group); | ||
94 | |||
95 | /* check whether block bitmap block number is set */ | ||
96 | bitmap_blk = le32_to_cpu(desc->bg_block_bitmap); | ||
97 | offset = bitmap_blk - group_first_block; | ||
98 | if (!ext3_test_bit(offset, bh->b_data)) | ||
99 | /* bad block bitmap */ | ||
100 | goto err_out; | ||
101 | |||
102 | /* check whether the inode bitmap block number is set */ | ||
103 | bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap); | ||
104 | offset = bitmap_blk - group_first_block; | ||
105 | if (!ext3_test_bit(offset, bh->b_data)) | ||
106 | /* bad block bitmap */ | ||
107 | goto err_out; | ||
108 | |||
109 | /* check whether the inode table block number is set */ | ||
110 | bitmap_blk = le32_to_cpu(desc->bg_inode_table); | ||
111 | offset = bitmap_blk - group_first_block; | ||
112 | next_zero_bit = ext3_find_next_zero_bit(bh->b_data, | ||
113 | offset + EXT3_SB(sb)->s_itb_per_group, | ||
114 | offset); | ||
115 | if (next_zero_bit >= offset + EXT3_SB(sb)->s_itb_per_group) | ||
116 | /* good bitmap for inode tables */ | ||
117 | return 1; | ||
118 | |||
119 | err_out: | ||
120 | ext3_error(sb, __FUNCTION__, | ||
121 | "Invalid block bitmap - " | ||
122 | "block_group = %d, block = %lu", | ||
123 | block_group, bitmap_blk); | ||
124 | return 0; | ||
125 | } | ||
126 | |||
83 | /** | 127 | /** |
84 | * read_block_bitmap() | 128 | * read_block_bitmap() |
85 | * @sb: super block | 129 | * @sb: super block |
86 | * @block_group: given block group | 130 | * @block_group: given block group |
87 | * | 131 | * |
88 | * Read the bitmap for a given block_group, reading into the specified | 132 | * Read the bitmap for a given block_group,and validate the |
89 | * slot in the superblock's bitmap cache. | 133 | * bits for block/inode/inode tables are set in the bitmaps |
90 | * | 134 | * |
91 | * Return buffer_head on success or NULL in case of failure. | 135 | * Return buffer_head on success or NULL in case of failure. |
92 | */ | 136 | */ |
@@ -95,17 +139,35 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group) | |||
95 | { | 139 | { |
96 | struct ext3_group_desc * desc; | 140 | struct ext3_group_desc * desc; |
97 | struct buffer_head * bh = NULL; | 141 | struct buffer_head * bh = NULL; |
142 | ext3_fsblk_t bitmap_blk; | ||
98 | 143 | ||
99 | desc = ext3_get_group_desc (sb, block_group, NULL); | 144 | desc = ext3_get_group_desc(sb, block_group, NULL); |
100 | if (!desc) | 145 | if (!desc) |
101 | goto error_out; | 146 | return NULL; |
102 | bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap)); | 147 | bitmap_blk = le32_to_cpu(desc->bg_block_bitmap); |
103 | if (!bh) | 148 | bh = sb_getblk(sb, bitmap_blk); |
104 | ext3_error (sb, "read_block_bitmap", | 149 | if (unlikely(!bh)) { |
150 | ext3_error(sb, __FUNCTION__, | ||
105 | "Cannot read block bitmap - " | 151 | "Cannot read block bitmap - " |
106 | "block_group = %d, block_bitmap = %u", | 152 | "block_group = %d, block_bitmap = %u", |
107 | block_group, le32_to_cpu(desc->bg_block_bitmap)); | 153 | block_group, le32_to_cpu(desc->bg_block_bitmap)); |
108 | error_out: | 154 | return NULL; |
155 | } | ||
156 | if (likely(bh_uptodate_or_lock(bh))) | ||
157 | return bh; | ||
158 | |||
159 | if (bh_submit_read(bh) < 0) { | ||
160 | brelse(bh); | ||
161 | ext3_error(sb, __FUNCTION__, | ||
162 | "Cannot read block bitmap - " | ||
163 | "block_group = %d, block_bitmap = %u", | ||
164 | block_group, le32_to_cpu(desc->bg_block_bitmap)); | ||
165 | return NULL; | ||
166 | } | ||
167 | if (!ext3_valid_block_bitmap(sb, desc, block_group, bh)) { | ||
168 | brelse(bh); | ||
169 | return NULL; | ||
170 | } | ||
109 | return bh; | 171 | return bh; |
110 | } | 172 | } |
111 | /* | 173 | /* |