[PATCH 2/3] fix bitmap byte size calculations
Josh Hunt <[email protected]> Thu, 30 Jul 2026 20:37:00 -0700
| Newsgroups | org.kernel.vger.linux-ext4 |
|---|---|
| Message-ID | <[email protected]> |
From: Kit Knox <[email protected]> The bitmap byte size calculations use integer division (count / 8) without rounding up. When clusters_per_group or inodes_per_group is not a multiple of 8, this allocates too few bytes. The bitmap backends copy (num + 7) / 8 bytes via ext2fs_get_block_bitmap_range2(), causing a buffer overrun of 1-7 bytes. Example: With s_clusters_per_group = blocksize*8 + 1, the buffer is undersized by 1 byte, causing heap corruption when the bitmap is copied. Signed-off-by: Kit Knox <[email protected]> --- e2fsck/pass5.c | 10 ++++++---- lib/ext2fs/rw_bitmaps.c | 13 ++++++------- misc/dumpe2fs.c | 4 ++-- resize/resize2fs.c | 3 ++- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c index c1d45a5f..aad2e76a 100644 --- a/e2fsck/pass5.c +++ b/e2fsck/pass5.c @@ -324,10 +324,12 @@ static void check_block_bitmaps(e2fsck_t ctx) int redo_flag = 0; char *actual_buf, *bitmap_buf; - actual_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize, - "actual bitmap buffer"); - bitmap_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize, - "bitmap block buffer"); + actual_buf = (char *) e2fsck_allocate_memory(ctx, + ext2fs_div_ceil(fs->super->s_clusters_per_group, 8), + "actual bitmap buffer"); + bitmap_buf = (char *) e2fsck_allocate_memory(ctx, + ext2fs_div_ceil(fs->super->s_clusters_per_group, 8), + "bitmap block buffer"); clear_problem_context(&pctx); free_array = (unsigned int *) e2fsck_allocate_memory(ctx, diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c index 1da75e4a..211d9ec4 100644 --- a/lib/ext2fs/rw_bitmaps.c +++ b/lib/ext2fs/rw_bitmaps.c @@ -72,15 +72,14 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) inode_nbytes = block_nbytes = 0; if (do_block) { - block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; + block_nbytes = ext2fs_div_ceil(EXT2_CLUSTERS_PER_GROUP(fs->super), 8); retval = io_channel_alloc_buf(fs->io, 0, &block_buf); if (retval) goto errout; memset(block_buf, 0xff, fs->blocksize); } if (do_inode) { - inode_nbytes = (size_t) - ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8); + inode_nbytes = ext2fs_div_ceil(EXT2_INODES_PER_GROUP(fs->super), 8); retval = io_channel_alloc_buf(fs->io, 0, &inode_buf); if (retval) goto errout; @@ -230,8 +229,8 @@ static int bitmap_tail_verify(unsigned char *bitmap, int first, int last) static errcode_t read_bitmaps_range_prepare(ext2_filsys fs, int flags) { errcode_t retval; - int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; - int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; + int block_nbytes = ext2fs_div_ceil(EXT2_CLUSTERS_PER_GROUP(fs->super), 8); + int inode_nbytes = ext2fs_div_ceil(EXT2_INODES_PER_GROUP(fs->super), 8); char *buf; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); @@ -289,8 +288,8 @@ static errcode_t read_bitmaps_range_start(ext2_filsys fs, int flags, dgrp_t i; char *block_bitmap = 0, *inode_bitmap = 0; errcode_t retval = 0; - int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; - int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; + int block_nbytes = ext2fs_div_ceil(EXT2_CLUSTERS_PER_GROUP(fs->super), 8); + int inode_nbytes = ext2fs_div_ceil(EXT2_INODES_PER_GROUP(fs->super), 8); int csum_flag; unsigned int cnt; blk64_t blk; diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c index b56d15d9..2c45d6bb 100644 --- a/misc/dumpe2fs.c +++ b/misc/dumpe2fs.c @@ -168,8 +168,8 @@ static void list_desc(ext2_filsys fs, int grp_only) if (ext2fs_has_feature_bigalloc(fs->super)) units = _("clusters"); - block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; - inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; + block_nbytes = ext2fs_div_ceil(EXT2_CLUSTERS_PER_GROUP(fs->super), 8); + inode_nbytes = ext2fs_div_ceil(EXT2_INODES_PER_GROUP(fs->super), 8); if (fs->block_map) block_bitmap = malloc(block_nbytes); diff --git a/resize/resize2fs.c b/resize/resize2fs.c index dfefca1d..ad092244 100644 --- a/resize/resize2fs.c +++ b/resize/resize2fs.c @@ -2088,6 +2088,7 @@ static int fix_ea_ibody_entries(ext2_extent imap, ea_magic = (__u32 *)((char *)inode + EXT2_GOOD_OLD_INODE_SIZE + inode->i_extra_isize); + if (*ea_magic != EXT2_EXT_ATTR_MAGIC) return 0; @@ -2950,7 +2951,7 @@ static errcode_t resize2fs_calculate_summary_stats(ext2_filsys fs) /* * First calculate the block statistics */ - bitmap_buf = malloc(fs->blocksize); + bitmap_buf = malloc(ext2fs_div_ceil(fs->super->s_clusters_per_group, 8)); if (!bitmap_buf) return ENOMEM; for (group = 0; group < fs->group_desc_count; group++) { -- 2.34.1