Skip to contentSkip to conversation

ext2/ext3/ext4: Add block bitmap validation

PATCH In review Aneesh Kumar K.V 2 participants 2 messages Jul 9, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ext2/ext3/ext4: 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 by ext4_blk_bitmap, ext4_inode_bitmap and ext4_inode_table. Validate the block bitmap against these blocks.

---
 fs/ext2/balloc.c |   51 +++++++++++++++++++++++++++++++++++++----------
 fs/ext3/balloc.c |   48 ++++++++++++++++++++++++++++++++++++---------
 fs/ext4/balloc.c |   57 ++++++++++++++++++++++++++++++++++++++++-------------
 3 files changed, 121 insertions(+), 35 deletions(-)
fs/ext2/balloc.c +40 -11
index baf71dd..8127682 100644
@@ -69,6 +69,14 @@ struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
 	return desc + offset;
 }
 
+static inline int
+block_in_use(unsigned long block, struct super_block *sb, unsigned char *map)
+{
+	return ext2_test_bit ((block -
+		le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block)) %
+			 EXT2_BLOCKS_PER_GROUP(sb), map);
+}
+
 /*
  * Read the bitmap for a given block_group, reading into the specified 
  * slot in the superblock's bitmap cache.
@@ -80,18 +88,46 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
 {
 	struct ext2_group_desc * desc;
 	struct buffer_head * bh = NULL;
-	
+	unsigned int bitmap_blk;
+
 	desc = ext2_get_group_desc (sb, block_group, NULL);
 	if (!desc)
-		goto error_out;
-	bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap));
+		return NULL;
+	bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
+	bh = sb_bread(sb, bitmap_blk);
 	if (!bh)
 		ext2_error (sb, "read_block_bitmap",
 			    "Cannot read block bitmap - "
 			    "block_group = %d, block_bitmap = %u",
 			    block_group, le32_to_cpu(desc->bg_block_bitmap));
-error_out:
+
+	/* check whether block bitmap block number is set */
+	if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
+		/* bad block bitmap */
+		goto error_out;
+	}
+	/* check whether the inode bitmap block number is set */
+	bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap);
+	if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
+		/* bad block bitmap */
+		goto error_out;
+	}
+	/* check whether the inode table block number is set */
+	bitmap_blk = le32_to_cpu(desc->bg_inode_table);
+	if (!block_in_use(bitmap_blk, sb, bh->b_data)) {
+		/* bad block bitmap */
+		goto error_out;
+	}
+
 	return bh;
+
+error_out:
+	brelse(bh);
+	ext2_error(sb, "read_block_bitmap",
+			"Invalid block bitmap - "
+			"block_group = %d, block = %u",
+			block_group, bitmap_blk);
+	return NULL;
 }
 
 /*
@@ -583,13 +619,6 @@ unsigned long ext2_count_free_blocks (struct super_block * sb)
 #endif
 }
 
-static inline int
-block_in_use(unsigned long block, struct super_block *sb, unsigned char *map)
-{
-	return ext2_test_bit ((block -
-		le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block)) %
-			 EXT2_BLOCKS_PER_GROUP(sb), map);
-}
 
 static inline int test_root(int a, int b)
 {
fs/ext3/balloc.c +38 -10

75 lines not on this page · raw message

fs/ext4/balloc.c +43 -14

83 lines not on this page · raw message

Signature · 1 line
1.5.3.rc0.63.gc956-dirty
#1 lore raw
Quoted 4 lines · Aneesh Kumar K.V

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 by ext4_blk_bitmap, ext4_inode_bitmap and ext4_inode_table. Validate the block bitmap against these blocks.

Ah, our emails passed each other... Mine has the added change that it checks all of the itable bits, but otherwise it seems we made the same cleanups.

Cheers, Andreas
--
Andreas Dilger
Principal Software Engineer
Cluster File Systems, Inc.