# HG changeset patch # User tytso@mit.edu # Date Tue Sep 12 14:55:22 2006 -0400 # Node ID 90cd01f7fcd6293846f0b3ca6ce2b007e3dd7d51 # parent: cb841a8195a7aa87e8d0c95686291e8fb53358df Fix loops over group descriptors to prevent 2**32-1 block number overflows For loops iterating over all group descriptors, consistently define first_block and last_block in a way that they are inclusive of the range, and do not overflow. Previously on the last block group we did a test of <= first + dec_blocks; this would actually wrap back to 0 for a total block count of 2^32-1 Also add handling of last block group which may be smaller. Signed-off-by: Eric Sandeen Index: e2fsprogs-1.39-my-patches-from-ted/e2fsck/ChangeLog =================================================================== --- e2fsprogs-1.39-my-patches-from-ted.orig/e2fsck/ChangeLog +++ e2fsprogs-1.39-my-patches-from-ted/e2fsck/ChangeLog @@ -1,3 +1,11 @@ +2006-08-30 Eric Sandeen + + * pass1b.c (check_if_fs_block): Change block group loop to use + a common pattern of first_block/last_block, etc. + + * super.c (check_super_block): Avoid overflows when iterating over + group descriptors on very large filesystems + 2006-08-30 Theodore Tso * pass5.c (check_inode_bitmaps, check_inode_end, check_block_end): Index: e2fsprogs-1.39-my-patches-from-ted/e2fsck/pass1b.c =================================================================== --- e2fsprogs-1.39-my-patches-from-ted.orig/e2fsck/pass1b.c +++ e2fsprogs-1.39-my-patches-from-ted/e2fsck/pass1b.c @@ -779,16 +779,16 @@ errout: static int check_if_fs_block(e2fsck_t ctx, blk_t test_block) { ext2_filsys fs = ctx->fs; - blk_t block; + blk_t first_block; dgrp_t i; - block = fs->super->s_first_data_block; + first_block = fs->super->s_first_data_block; for (i = 0; i < fs->group_desc_count; i++) { - /* Check superblocks/block group descriptros */ + /* Check superblocks/block group descriptors */ if (ext2fs_bg_has_super(fs, i)) { - if (test_block >= block && - (test_block <= block + fs->desc_blocks)) + if (test_block >= first_block && + (test_block <= first_block + fs->desc_blocks)) return 1; } @@ -804,7 +804,7 @@ static int check_if_fs_block(e2fsck_t ct (test_block == fs->group_desc[i].bg_inode_bitmap)) return 1; - block += fs->super->s_blocks_per_group; + first_block += fs->super->s_blocks_per_group; } return 0; } Index: e2fsprogs-1.39-my-patches-from-ted/e2fsck/super.c =================================================================== --- e2fsprogs-1.39-my-patches-from-ted.orig/e2fsck/super.c +++ e2fsprogs-1.39-my-patches-from-ted/e2fsck/super.c @@ -566,15 +566,17 @@ void check_super_block(e2fsck_t ctx) * Verify the group descriptors.... */ first_block = sb->s_first_data_block; - last_block = first_block + blocks_per_group; for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) { pctx.group = i; if (i == fs->group_desc_count - 1) - last_block = sb->s_blocks_count; + last_block = sb->s_blocks_count - 1; + else + last_block = first_block + blocks_per_group - 1; + if ((gd->bg_block_bitmap < first_block) || - (gd->bg_block_bitmap >= last_block)) { + (gd->bg_block_bitmap > last_block)) { pctx.blk = gd->bg_block_bitmap; if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx)) gd->bg_block_bitmap = 0; @@ -584,7 +586,7 @@ void check_super_block(e2fsck_t ctx) ctx->invalid_bitmaps++; } if ((gd->bg_inode_bitmap < first_block) || - (gd->bg_inode_bitmap >= last_block)) { + (gd->bg_inode_bitmap > last_block)) { pctx.blk = gd->bg_inode_bitmap; if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx)) gd->bg_inode_bitmap = 0; @@ -595,7 +597,7 @@ void check_super_block(e2fsck_t ctx) } if ((gd->bg_inode_table < first_block) || ((gd->bg_inode_table + - fs->inode_blocks_per_group - 1) >= last_block)) { + fs->inode_blocks_per_group - 1) > last_block)) { pctx.blk = gd->bg_inode_table; if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx)) gd->bg_inode_table = 0; @@ -607,7 +609,6 @@ void check_super_block(e2fsck_t ctx) free_blocks += gd->bg_free_blocks_count; free_inodes += gd->bg_free_inodes_count; first_block += sb->s_blocks_per_group; - last_block += sb->s_blocks_per_group; if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) || (gd->bg_free_inodes_count > sb->s_inodes_per_group) || Index: e2fsprogs-1.39-my-patches-from-ted/lib/ext2fs/ChangeLog =================================================================== --- e2fsprogs-1.39-my-patches-from-ted.orig/lib/ext2fs/ChangeLog +++ e2fsprogs-1.39-my-patches-from-ted/lib/ext2fs/ChangeLog @@ -1,3 +1,8 @@ +2006-08-30 Eric Sandeen + + * check_desc.c (ext2fs_check_desc): avoid overflows when iterating + over group descriptors on very large filesystems. + 2006-08-30 Theodore Tso * bitmaps.c (ext2fs_set_bitmap_padding): Fix potential overflow Index: e2fsprogs-1.39-my-patches-from-ted/lib/ext2fs/check_desc.c =================================================================== --- e2fsprogs-1.39-my-patches-from-ted.orig/lib/ext2fs/check_desc.c +++ e2fsprogs-1.39-my-patches-from-ted/lib/ext2fs/check_desc.c @@ -32,37 +32,41 @@ errcode_t ext2fs_check_desc(ext2_filsys fs) { dgrp_t i; - blk_t block = fs->super->s_first_data_block; - blk_t next; + blk_t first_block = fs->super->s_first_data_block; + blk_t last_block; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); for (i = 0; i < fs->group_desc_count; i++) { - next = block + fs->super->s_blocks_per_group; + if (i == fs->group_desc_count - 1) + last_block = fs->super->s_blocks_count - 1; + else + last_block = first_block + + fs->super->s_blocks_per_group - 1; /* * Check to make sure block bitmap for group is * located within the group. */ - if (fs->group_desc[i].bg_block_bitmap < block || - fs->group_desc[i].bg_block_bitmap >= next) + 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; /* * Check to make sure inode bitmap for group is * located within the group */ - if (fs->group_desc[i].bg_inode_bitmap < block || - fs->group_desc[i].bg_inode_bitmap >= next) + 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; /* * Check to make sure inode table for group is located * within the group */ - if (fs->group_desc[i].bg_inode_table < block || + if (fs->group_desc[i].bg_inode_table < first_block || ((fs->group_desc[i].bg_inode_table + - fs->inode_blocks_per_group) >= next)) + fs->inode_blocks_per_group) > last_block)) return EXT2_ET_GDESC_BAD_INODE_TABLE; - block = next; + first_block += fs->super->s_blocks_per_group; } return 0; } Index: e2fsprogs-1.39-my-patches-from-ted/misc/ChangeLog =================================================================== --- e2fsprogs-1.39-my-patches-from-ted.orig/misc/ChangeLog +++ e2fsprogs-1.39-my-patches-from-ted/misc/ChangeLog @@ -1,3 +1,12 @@ +2006-08-30 Eric Sandeen + + * dumpe2fs.c (list_desc, mark_table_blocks): Avoid overflows when + iterating over group descriptors on very large + filesystems. + + * e2image.c (mark_table_blocks): Change block group loop to use a + common pattern of first_block/last_block, etc. + 2006-08-30 Theodore Tso * tune2fs.c (main), mke2fs.c (PRS): Use e2p_percent to properly Index: e2fsprogs-1.39-my-patches-from-ted/misc/dumpe2fs.c =================================================================== --- e2fsprogs-1.39-my-patches-from-ted.orig/misc/dumpe2fs.c +++ e2fsprogs-1.39-my-patches-from-ted/misc/dumpe2fs.c @@ -130,7 +130,7 @@ static void list_desc (ext2_filsys fs) { unsigned long i; long diff; - blk_t group_blk, next_blk; + blk_t first_block, last_block; blk_t super_blk, old_desc_blk, new_desc_blk; char *block_bitmap=NULL, *inode_bitmap=NULL; int inode_blocks_per_group, old_desc_blocks, reserved_gdt; @@ -147,7 +147,7 @@ static void list_desc (ext2_filsys fs) EXT2_BLOCK_SIZE(fs->super); reserved_gdt = fs->super->s_reserved_gdt_blocks; fputc('\n', stdout); - group_blk = fs->super->s_first_data_block; + first_block = fs->super->s_first_data_block; if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) old_desc_blocks = fs->super->s_first_meta_bg; else @@ -155,11 +155,14 @@ static void list_desc (ext2_filsys fs) for (i = 0; i < fs->group_desc_count; i++) { ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk, &new_desc_blk, 0); - next_blk = group_blk + fs->super->s_blocks_per_group; - if (next_blk > fs->super->s_blocks_count) - next_blk = fs->super->s_blocks_count; + if (i == fs->group_desc_count - 1) + last_block = fs->super->s_blocks_count - 1; + else + last_block = first_block + + fs->super->s_blocks_per_group - 1; + printf (_("Group %lu: (Blocks "), i); - print_range(group_blk, next_blk - 1); + print_range(first_block, last_block); fputs(")", stdout); print_bg_opts(fs, i); has_super = ((i==0) || super_blk); @@ -188,19 +191,19 @@ static void list_desc (ext2_filsys fs) fputc('\n', stdout); fputs(_(" Block bitmap at "), stdout); print_number(fs->group_desc[i].bg_block_bitmap); - diff = fs->group_desc[i].bg_block_bitmap - group_blk; + diff = fs->group_desc[i].bg_block_bitmap - first_block; if (diff >= 0) printf(" (+%ld)", diff); fputs(_(", Inode bitmap at "), stdout); print_number(fs->group_desc[i].bg_inode_bitmap); - diff = fs->group_desc[i].bg_inode_bitmap - group_blk; + diff = fs->group_desc[i].bg_inode_bitmap - first_block; if (diff >= 0) printf(" (+%ld)", diff); fputs(_("\n Inode table at "), stdout); print_range(fs->group_desc[i].bg_inode_table, fs->group_desc[i].bg_inode_table + inode_blocks_per_group - 1); - diff = fs->group_desc[i].bg_inode_table - group_blk; + diff = fs->group_desc[i].bg_inode_table - first_block; if (diff > 0) printf(" (+%ld)", diff); printf (_("\n %d free blocks, %d free inodes, " @@ -223,7 +226,7 @@ static void list_desc (ext2_filsys fs) fputc('\n', stdout); inode_bitmap += fs->super->s_inodes_per_group / 8; } - group_blk = next_blk; + first_block += fs->super->s_blocks_per_group; } } Index: e2fsprogs-1.39-my-patches-from-ted/misc/e2image.c =================================================================== --- e2fsprogs-1.39-my-patches-from-ted.orig/misc/e2image.c +++ e2fsprogs-1.39-my-patches-from-ted/misc/e2image.c @@ -244,21 +244,21 @@ static int process_file_block(ext2_filsy static void mark_table_blocks(ext2_filsys fs) { - blk_t block, b; + blk_t first_block, b; unsigned int i,j; - block = fs->super->s_first_data_block; + first_block = fs->super->s_first_data_block; /* * Mark primary superblock */ - ext2fs_mark_block_bitmap(meta_block_map, block); + ext2fs_mark_block_bitmap(meta_block_map, first_block); /* * Mark the primary superblock descriptors */ for (j = 0; j < fs->desc_blocks; j++) { ext2fs_mark_block_bitmap(meta_block_map, - ext2fs_descriptor_block_loc(fs, block, j)); + ext2fs_descriptor_block_loc(fs, first_block, j)); } for (i = 0; i < fs->group_desc_count; i++) { @@ -287,7 +287,7 @@ static void mark_table_blocks(ext2_filsy ext2fs_mark_block_bitmap(meta_block_map, fs->group_desc[i].bg_inode_bitmap); } - block += fs->super->s_blocks_per_group; + first_block += fs->super->s_blocks_per_group; } }