diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2008-02-06 04:40:08 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-06 13:41:20 -0500 |
commit | 01584fa6456dafbaf5a94ad7fb2aa3e3ecd7a7ba (patch) | |
tree | 8454d18e301e4a408236b22d91bf506fa90630fb /fs/ext2 | |
parent | 445a1d3e24b806bff01e422f0ddadf68e0eb5d0f (diff) |
ext2: 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>
Diffstat (limited to 'fs/ext2')
-rw-r--r-- | fs/ext2/balloc.c | 81 |
1 files changed, 72 insertions, 9 deletions
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index 794008b6ce29..a51bdf82450f 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c | |||
@@ -69,9 +69,53 @@ struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb, | |||
69 | return desc + offset; | 69 | return desc + offset; |
70 | } | 70 | } |
71 | 71 | ||
72 | static int ext2_valid_block_bitmap(struct super_block *sb, | ||
73 | struct ext2_group_desc *desc, | ||
74 | unsigned int block_group, | ||
75 | struct buffer_head *bh) | ||
76 | { | ||
77 | ext2_grpblk_t offset; | ||
78 | ext2_grpblk_t next_zero_bit; | ||
79 | ext2_fsblk_t bitmap_blk; | ||
80 | ext2_fsblk_t group_first_block; | ||
81 | |||
82 | group_first_block = ext2_group_first_block_no(sb, block_group); | ||
83 | |||
84 | /* check whether block bitmap block number is set */ | ||
85 | bitmap_blk = le32_to_cpu(desc->bg_block_bitmap); | ||
86 | offset = bitmap_blk - group_first_block; | ||
87 | if (!ext2_test_bit(offset, bh->b_data)) | ||
88 | /* bad block bitmap */ | ||
89 | goto err_out; | ||
90 | |||
91 | /* check whether the inode bitmap block number is set */ | ||
92 | bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap); | ||
93 | offset = bitmap_blk - group_first_block; | ||
94 | if (!ext2_test_bit(offset, bh->b_data)) | ||
95 | /* bad block bitmap */ | ||
96 | goto err_out; | ||
97 | |||
98 | /* check whether the inode table block number is set */ | ||
99 | bitmap_blk = le32_to_cpu(desc->bg_inode_table); | ||
100 | offset = bitmap_blk - group_first_block; | ||
101 | next_zero_bit = ext2_find_next_zero_bit(bh->b_data, | ||
102 | offset + EXT2_SB(sb)->s_itb_per_group, | ||
103 | offset); | ||
104 | if (next_zero_bit >= offset + EXT2_SB(sb)->s_itb_per_group) | ||
105 | /* good bitmap for inode tables */ | ||
106 | return 1; | ||
107 | |||
108 | err_out: | ||
109 | ext2_error(sb, __FUNCTION__, | ||
110 | "Invalid block bitmap - " | ||
111 | "block_group = %d, block = %lu", | ||
112 | block_group, bitmap_blk); | ||
113 | return 0; | ||
114 | } | ||
115 | |||
72 | /* | 116 | /* |
73 | * Read the bitmap for a given block_group, reading into the specified | 117 | * Read the bitmap for a given block_group,and validate the |
74 | * slot in the superblock's bitmap cache. | 118 | * bits for block/inode/inode tables are set in the bitmaps |
75 | * | 119 | * |
76 | * Return buffer_head on success or NULL in case of failure. | 120 | * Return buffer_head on success or NULL in case of failure. |
77 | */ | 121 | */ |
@@ -80,17 +124,36 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group) | |||
80 | { | 124 | { |
81 | struct ext2_group_desc * desc; | 125 | struct ext2_group_desc * desc; |
82 | struct buffer_head * bh = NULL; | 126 | struct buffer_head * bh = NULL; |
83 | 127 | ext2_fsblk_t bitmap_blk; | |
84 | desc = ext2_get_group_desc (sb, block_group, NULL); | 128 | |
129 | desc = ext2_get_group_desc(sb, block_group, NULL); | ||
85 | if (!desc) | 130 | if (!desc) |
86 | goto error_out; | 131 | return NULL; |
87 | bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap)); | 132 | bitmap_blk = le32_to_cpu(desc->bg_block_bitmap); |
88 | if (!bh) | 133 | bh = sb_getblk(sb, bitmap_blk); |
89 | ext2_error (sb, "read_block_bitmap", | 134 | if (unlikely(!bh)) { |
135 | ext2_error(sb, __FUNCTION__, | ||
90 | "Cannot read block bitmap - " | 136 | "Cannot read block bitmap - " |
91 | "block_group = %d, block_bitmap = %u", | 137 | "block_group = %d, block_bitmap = %u", |
92 | block_group, le32_to_cpu(desc->bg_block_bitmap)); | 138 | block_group, le32_to_cpu(desc->bg_block_bitmap)); |
93 | error_out: | 139 | return NULL; |
140 | } | ||
141 | if (likely(bh_uptodate_or_lock(bh))) | ||
142 | return bh; | ||
143 | |||
144 | if (bh_submit_read(bh) < 0) { | ||
145 | brelse(bh); | ||
146 | ext2_error(sb, __FUNCTION__, | ||
147 | "Cannot read block bitmap - " | ||
148 | "block_group = %d, block_bitmap = %u", | ||
149 | block_group, le32_to_cpu(desc->bg_block_bitmap)); | ||
150 | return NULL; | ||
151 | } | ||
152 | if (!ext2_valid_block_bitmap(sb, desc, block_group, bh)) { | ||
153 | brelse(bh); | ||
154 | return NULL; | ||
155 | } | ||
156 | |||
94 | return bh; | 157 | return bh; |
95 | } | 158 | } |
96 | 159 | ||