From e686e6cd460cc1767c1a6dcf19841d1d0df4bb7b Mon Sep 17 00:00:00 2001 From: ngkaho1234 Date: Wed, 28 Oct 2015 13:54:37 +0000 Subject: [PATCH] METADATA_CSUM: inode and block group descriptor checksum verification added --- lwext4/ext4_fs.c | 181 +++++++++++++++++++++++++++++------------------ 1 file changed, 111 insertions(+), 70 deletions(-) diff --git a/lwext4/ext4_fs.c b/lwext4/ext4_fs.c index 6afb96e..7b2d404 100644 --- a/lwext4/ext4_fs.c +++ b/lwext4/ext4_fs.c @@ -489,76 +489,6 @@ static ext4_fsblk_t ext4_fs_get_descriptor_block(struct ext4_sblock *s, return (has_super + ext4_fs_first_bg_block_no(s, bgid)); } -int ext4_fs_get_block_group_ref(struct ext4_fs *fs, uint32_t bgid, - struct ext4_block_group_ref *ref) -{ - /* Compute number of descriptors, that fits in one data block */ - uint32_t dsc_per_block = - ext4_sb_get_block_size(&fs->sb) / ext4_sb_get_desc_size(&fs->sb); - - /* Block group descriptor table starts at the next block after - * superblock */ - uint64_t block_id = - ext4_fs_get_descriptor_block(&fs->sb, bgid, dsc_per_block); - - uint32_t offset = - (bgid % dsc_per_block) * ext4_sb_get_desc_size(&fs->sb); - - int rc = ext4_block_get(fs->bdev, &ref->block, block_id); - if (rc != EOK) - return rc; - - ref->block_group = (void *)(ref->block.data + offset); - ref->fs = fs; - ref->index = bgid; - ref->dirty = false; - - if (ext4_bg_has_flag(ref->block_group, EXT4_BLOCK_GROUP_BLOCK_UNINIT)) { - rc = ext4_fs_init_block_bitmap(ref); - if (rc != EOK) { - ext4_block_set(fs->bdev, &ref->block); - return rc; - } - ext4_bg_clear_flag(ref->block_group, - EXT4_BLOCK_GROUP_BLOCK_UNINIT); - - ref->dirty = true; - } - - if (ext4_bg_has_flag(ref->block_group, EXT4_BLOCK_GROUP_INODE_UNINIT)) { - rc = ext4_fs_init_inode_bitmap(ref); - if (rc != EOK) { - ext4_block_set(ref->fs->bdev, &ref->block); - return rc; - } - - ext4_bg_clear_flag(ref->block_group, - EXT4_BLOCK_GROUP_INODE_UNINIT); - - if (!ext4_bg_has_flag(ref->block_group, - EXT4_BLOCK_GROUP_ITABLE_ZEROED)) { - rc = ext4_fs_init_inode_table(ref); - if (rc != EOK) { - ext4_block_set(fs->bdev, &ref->block); - return rc; - } - - ext4_bg_set_flag(ref->block_group, - EXT4_BLOCK_GROUP_ITABLE_ZEROED); - } - - ref->dirty = true; - } - - return EOK; -} - -/* - * BIG FAT NOTES: - * Currently we do not verify the checksum of block_group_desc - * and inode. - */ - /**@brief Compute checksum of block group descriptor. * @param sb Superblock * @param bgid Index of block group in the filesystem @@ -629,6 +559,96 @@ static uint16_t ext4_fs_bg_checksum(struct ext4_sblock *sb, uint32_t bgid, return crc; } +#if CONFIG_META_CSUM_ENABLE +static bool ext4_fs_verify_bg_csum(struct ext4_sblock *sb, + uint32_t bgid, + struct ext4_bgroup *bg) +{ + if (!ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) + return true; + + return ext4_fs_bg_checksum(sb, + bgid, + bg) == + to_le16(bg->checksum); +} +#else +#define ext4_fs_verify_bg_csum(...) true +#endif + +int ext4_fs_get_block_group_ref(struct ext4_fs *fs, uint32_t bgid, + struct ext4_block_group_ref *ref) +{ + /* Compute number of descriptors, that fits in one data block */ + uint32_t dsc_per_block = + ext4_sb_get_block_size(&fs->sb) / ext4_sb_get_desc_size(&fs->sb); + + /* Block group descriptor table starts at the next block after + * superblock */ + uint64_t block_id = + ext4_fs_get_descriptor_block(&fs->sb, bgid, dsc_per_block); + + uint32_t offset = + (bgid % dsc_per_block) * ext4_sb_get_desc_size(&fs->sb); + + int rc = ext4_block_get(fs->bdev, &ref->block, block_id); + if (rc != EOK) + return rc; + + ref->block_group = (void *)(ref->block.data + offset); + ref->fs = fs; + ref->index = bgid; + ref->dirty = false; + + if (!ext4_fs_verify_bg_csum(&fs->sb, + bgid, + ref->block_group)) { + ext4_dbg(DEBUG_FS, + DBG_WARN "Block group descriptor checksum failed." + "Block group index: %" PRIu32"\n", + bgid); + } + + if (ext4_bg_has_flag(ref->block_group, EXT4_BLOCK_GROUP_BLOCK_UNINIT)) { + rc = ext4_fs_init_block_bitmap(ref); + if (rc != EOK) { + ext4_block_set(fs->bdev, &ref->block); + return rc; + } + ext4_bg_clear_flag(ref->block_group, + EXT4_BLOCK_GROUP_BLOCK_UNINIT); + + ref->dirty = true; + } + + if (ext4_bg_has_flag(ref->block_group, EXT4_BLOCK_GROUP_INODE_UNINIT)) { + rc = ext4_fs_init_inode_bitmap(ref); + if (rc != EOK) { + ext4_block_set(ref->fs->bdev, &ref->block); + return rc; + } + + ext4_bg_clear_flag(ref->block_group, + EXT4_BLOCK_GROUP_INODE_UNINIT); + + if (!ext4_bg_has_flag(ref->block_group, + EXT4_BLOCK_GROUP_ITABLE_ZEROED)) { + rc = ext4_fs_init_inode_table(ref); + if (rc != EOK) { + ext4_block_set(fs->bdev, &ref->block); + return rc; + } + + ext4_bg_set_flag(ref->block_group, + EXT4_BLOCK_GROUP_ITABLE_ZEROED); + } + + ref->dirty = true; + } + + return EOK; +} + int ext4_fs_put_block_group_ref(struct ext4_block_group_ref *ref) { /* Check if reference modified */ @@ -697,6 +717,20 @@ static void ext4_fs_set_inode_checksum(struct ext4_inode_ref *inode_ref) ext4_fs_inode_checksum(inode_ref)); } +#if CONFIG_META_CSUM_ENABLE +static bool ext4_fs_verify_inode_csum(struct ext4_inode_ref *inode_ref) +{ + struct ext4_sblock *sb = &inode_ref->fs->sb; + if (!ext4_sb_feature_ro_com(sb, EXT4_FRO_COM_METADATA_CSUM)) + return true; + + return ext4_inode_get_checksum(sb, inode_ref->inode) == + ext4_fs_inode_checksum(inode_ref); +} +#else +#define ext4_fs_verify_inode_csum(...) true +#endif + int ext4_fs_get_inode_ref(struct ext4_fs *fs, uint32_t index, struct ext4_inode_ref *ref) { @@ -752,6 +786,13 @@ int ext4_fs_get_inode_ref(struct ext4_fs *fs, uint32_t index, ref->fs = fs; ref->dirty = false; + if (!ext4_fs_verify_inode_csum(ref)) { + ext4_dbg(DEBUG_FS, + DBG_WARN "Inode checksum failed." + "Inode: %" PRIu32"\n", + ref->index); + } + return EOK; }