Make ext2fs_check_desc() more stringent to force use of backup superbocks

E2fsck could to do more damage to a filesystem by trying to relocate
inode tables due to corrupted block group descriptors, and the
relocation could seriously damage the filesystem.

This patch enhances ext2fs_check_desk() so it detects more
self-inconsistent block group descriptors, including the cases where
e2sck might be tempted to relocate the inode table, and reports the
block group descriptors as invalid; this will cause e2fsck to attempt
to use the backup superblocks, which hopefully have not been trashed.

Addresses-Sourceforge-Bug: #1840291

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
bitmap-optimize
Theodore Ts'o 2008-07-10 16:35:05 -04:00
parent 7d56e33d1f
commit 009c02baf9
3 changed files with 61 additions and 26 deletions

View File

@ -63,7 +63,9 @@ int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
if (fs->super->s_reserved_gdt_blocks && fs->block_map == bmap)
fs->group_desc[group].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
for (j=0; j < old_desc_blocks; j++)
ext2fs_mark_block_bitmap(bmap, old_desc_blk + j);
if (old_desc_blk + j < fs->super->s_blocks_count)
ext2fs_mark_block_bitmap(bmap,
old_desc_blk + j);
}
if (new_desc_blk)
ext2fs_mark_block_bitmap(bmap, new_desc_blk);

View File

@ -31,41 +31,73 @@
*/
errcode_t ext2fs_check_desc(ext2_filsys fs)
{
ext2fs_block_bitmap bmap;
errcode_t retval;
dgrp_t i;
blk_t first_block = fs->super->s_first_data_block;
blk_t last_block = fs->super->s_blocks_count-1;
blk_t blk, b;
int j;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
retval = ext2fs_allocate_block_bitmap(fs, "check_desc map", &bmap);
if (retval)
return retval;
for (i = 0; i < fs->group_desc_count; i++)
ext2fs_reserve_super_and_bgd(fs, i, bmap);
for (i = 0; i < fs->group_desc_count; i++) {
if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
first_block = ext2fs_group_first_block(fs, i);
last_block = ext2fs_group_last_block(fs, i);
if (i == (fs->group_desc_count - 1))
last_block = fs->super->s_blocks_count-1;
}
/*
* Check to make sure block bitmap for group is
* located within the group.
* Check to make sure the block bitmap for group is sane
*/
if (fs->group_desc[i].bg_block_bitmap < first_block ||
fs->group_desc[i].bg_block_bitmap > last_block)
return EXT2_ET_GDESC_BAD_BLOCK_MAP;
blk = fs->group_desc[i].bg_block_bitmap;
if (blk < first_block || blk > last_block ||
ext2fs_test_block_bitmap(bmap, blk)) {
retval = EXT2_ET_GDESC_BAD_BLOCK_MAP;
goto errout;
}
ext2fs_mark_block_bitmap(bmap, blk);
/*
* Check to make sure inode bitmap for group is
* located within the group
* Check to make sure the inode bitmap for group is sane
*/
if (fs->group_desc[i].bg_inode_bitmap < first_block ||
fs->group_desc[i].bg_inode_bitmap > last_block)
return EXT2_ET_GDESC_BAD_INODE_MAP;
blk = fs->group_desc[i].bg_inode_bitmap;
if (blk < first_block || blk > last_block ||
ext2fs_test_block_bitmap(bmap, blk)) {
retval = EXT2_ET_GDESC_BAD_INODE_MAP;
goto errout;
}
ext2fs_mark_block_bitmap(bmap, blk);
/*
* Check to make sure inode table for group is located
* within the group
* Check to make sure the inode table for group is sane
*/
if (fs->group_desc[i].bg_inode_table < first_block ||
((fs->group_desc[i].bg_inode_table +
fs->inode_blocks_per_group - 1) > last_block))
return EXT2_ET_GDESC_BAD_INODE_TABLE;
blk = fs->group_desc[i].bg_inode_table;
if (blk < first_block ||
((blk + fs->inode_blocks_per_group - 1) > last_block)) {
retval = EXT2_ET_GDESC_BAD_INODE_TABLE;
goto errout;
}
for (j = 0, b = blk; j < fs->inode_blocks_per_group;
j++, b++) {
if (ext2fs_test_block_bitmap(bmap, b)) {
retval = EXT2_ET_GDESC_BAD_INODE_TABLE;
goto errout;
}
ext2fs_mark_block_bitmap(bmap, b);
}
}
return 0;
errout:
ext2fs_free_block_bitmap(bmap);
return retval;
}

View File

@ -111,15 +111,16 @@ Exit status is 0
debugfs -R ''set_super_value reserved_gdt_blocks 15679'' -w ./test.img
Exit status is 0
Corruption found in superblock. (reserved_gdt_blocks = 15679).
../e2fsck/e2fsck: Group descriptors look bad... trying backup blocks...
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
The superblock could not be read or does not describe a correct ext2
filesystem. If the device is valid and it really contains an ext2
filesystem (and not swap or ufs or something else), then the superblock
is corrupt, and you might try running e2fsck with an alternate superblock:
e2fsck -b 1025 <device>
Exit status is 8
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/4096 files (0.0% non-contiguous), 2107/16384 blocks
Exit status is 1
-----------------------------------------------
debugfs -R ''set_super_value reserved_gdt_blocks 32'' -w ./test.img