Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=abcb2947c91130426539f209f7a473a67a1f6663
Commit:     abcb2947c91130426539f209f7a473a67a1f6663
Parent:     389d1b083c767a360ec84b27a95da06244becec8
Author:     Aneesh Kumar K.V <[EMAIL PROTECTED]>
AuthorDate: Mon Jan 28 23:58:27 2008 -0500
Committer:  Theodore Ts'o <[EMAIL PROTECTED]>
CommitDate: Mon Jan 28 23:58:27 2008 -0500

    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 corresponding to block bitmap, inode bitmap and inode 
tables.
    Validate the block bitmap against these blocks.
    
    Signed-off-by: Aneesh Kumar K.V <[EMAIL PROTECTED]>
---
 fs/ext4/balloc.c |   99 ++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 81 insertions(+), 18 deletions(-)

diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index ff3428e..d460223 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -189,13 +189,65 @@ struct ext4_group_desc * ext4_get_group_desc(struct 
super_block * sb,
        return desc;
 }
 
+static int ext4_valid_block_bitmap(struct super_block *sb,
+                                       struct ext4_group_desc *desc,
+                                       unsigned int block_group,
+                                       struct buffer_head *bh)
+{
+       ext4_grpblk_t offset;
+       ext4_grpblk_t next_zero_bit;
+       ext4_fsblk_t bitmap_blk;
+       ext4_fsblk_t group_first_block;
+
+       if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+               /* with FLEX_BG, the inode/block bitmaps and itable
+                * blocks may not be in the group at all
+                * so the bitmap validation will be skipped for those groups
+                * or it has to also read the block group where the bitmaps
+                * are located to verify they are set.
+                */
+               return 1;
+       }
+       group_first_block = ext4_group_first_block_no(sb, block_group);
+
+       /* check whether block bitmap block number is set */
+       bitmap_blk = ext4_block_bitmap(sb, desc);
+       offset = bitmap_blk - group_first_block;
+       if (!ext4_test_bit(offset, bh->b_data))
+               /* bad block bitmap */
+               goto err_out;
+
+       /* check whether the inode bitmap block number is set */
+       bitmap_blk = ext4_inode_bitmap(sb, desc);
+       offset = bitmap_blk - group_first_block;
+       if (!ext4_test_bit(offset, bh->b_data))
+               /* bad block bitmap */
+               goto err_out;
+
+       /* check whether the inode table block number is set */
+       bitmap_blk = ext4_inode_table(sb, desc);
+       offset = bitmap_blk - group_first_block;
+       next_zero_bit = ext4_find_next_zero_bit(bh->b_data,
+                               offset + EXT4_SB(sb)->s_itb_per_group,
+                               offset);
+       if (next_zero_bit >= offset + EXT4_SB(sb)->s_itb_per_group)
+               /* good bitmap for inode tables */
+               return 1;
+
+err_out:
+       ext4_error(sb, __FUNCTION__,
+                       "Invalid block bitmap - "
+                       "block_group = %d, block = %llu",
+                       block_group, bitmap_blk);
+       return 0;
+}
 /**
  * read_block_bitmap()
  * @sb:                        super block
  * @block_group:       given block group
  *
- * Read the bitmap for a given block_group, reading into the specified
- * slot in the superblock's bitmap cache.
+ * Read the bitmap for a given block_group,and validate the
+ * bits for block/inode/inode tables are set in the bitmaps
  *
  * Return buffer_head on success or NULL in case of failure.
  */
@@ -210,25 +262,36 @@ read_block_bitmap(struct super_block *sb, ext4_group_t 
block_group)
        if (!desc)
                return NULL;
        bitmap_blk = ext4_block_bitmap(sb, desc);
+       bh = sb_getblk(sb, bitmap_blk);
+       if (unlikely(!bh)) {
+               ext4_error(sb, __FUNCTION__,
+                           "Cannot read block bitmap - "
+                           "block_group = %d, block_bitmap = %llu",
+                           (int)block_group, (unsigned long long)bitmap_blk);
+               return NULL;
+       }
+       if (bh_uptodate_or_lock(bh))
+               return bh;
+
        if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
-               bh = sb_getblk(sb, bitmap_blk);
-               if (!buffer_uptodate(bh)) {
-                       lock_buffer(bh);
-                       if (!buffer_uptodate(bh)) {
-                               ext4_init_block_bitmap(sb, bh, block_group,
-                                                      desc);
-                               set_buffer_uptodate(bh);
-                       }
-                       unlock_buffer(bh);
-               }
-       } else {
-               bh = sb_bread(sb, bitmap_blk);
+               ext4_init_block_bitmap(sb, bh, block_group, desc);
+               set_buffer_uptodate(bh);
+               unlock_buffer(bh);
+               return bh;
        }
-       if (!bh)
-               ext4_error (sb, __FUNCTION__,
+       if (bh_submit_read(bh) < 0) {
+               put_bh(bh);
+               ext4_error(sb, __FUNCTION__,
                            "Cannot read block bitmap - "
-                           "block_group = %lu, block_bitmap = %llu",
-                           block_group, bitmap_blk);
+                           "block_group = %d, block_bitmap = %llu",
+                           (int)block_group, (unsigned long long)bitmap_blk);
+               return NULL;
+       }
+       if (!ext4_valid_block_bitmap(sb, desc, block_group, bh)) {
+               put_bh(bh);
+               return NULL;
+       }
+
        return bh;
 }
 /*
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to