summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext2ed/ChangeLog5
-rw-r--r--ext2ed/init.c11
-rw-r--r--lib/ext2fs/ChangeLog11
-rw-r--r--lib/ext2fs/ext2fs.h11
-rw-r--r--lib/ext2fs/initialize.c19
-rw-r--r--lib/ext2fs/openfs.c11
-rw-r--r--misc/ChangeLog9
-rw-r--r--misc/filefrag.c9
-rw-r--r--misc/mke2fs.c8
-rw-r--r--resize/ChangeLog6
-rw-r--r--resize/resize2fs.c12
11 files changed, 81 insertions, 31 deletions
diff --git a/ext2ed/ChangeLog b/ext2ed/ChangeLog
index fa59c241..27564906 100644
--- a/ext2ed/ChangeLog
+++ b/ext2ed/ChangeLog
@@ -1,3 +1,8 @@
+2006-08-30 Theodore Tso <tytso@mit.edu>
+
+ * init.c (div_ceil, set_file_system_info): Fix potential overflow
+ for really big filesystems.
+
2006-06-30 Theodore Ts'o <tytso@mit.edu>
* Release of E2fsprogs 1.38
diff --git a/ext2ed/init.c b/ext2ed/init.c
index f89d8934..7ab2e28c 100644
--- a/ext2ed/init.c
+++ b/ext2ed/init.c
@@ -370,6 +370,13 @@ void add_user_command (struct struct_commands *ptr,char *name,char *description,
ptr->callback [num]=callback;
}
+static unsigned int div_ceil(unsigned int a, unsigned int b)
+{
+ if (!a)
+ return 0;
+ return ((a - 1) / b) + 1;
+}
+
int set_file_system_info (void)
{
@@ -415,8 +422,8 @@ int set_file_system_info (void)
file_system_info.first_group_desc_offset=2*EXT2_MIN_BLOCK_SIZE;
else
file_system_info.first_group_desc_offset=file_system_info.block_size;
- file_system_info.groups_count=( sb->s_blocks_count-sb->s_first_data_block+sb->s_blocks_per_group-1) /
- sb->s_blocks_per_group;
+ file_system_info.groups_count = div_ceil(sb->s_blocks_count,
+ sb->s_blocks_per_group);
file_system_info.inodes_per_block=file_system_info.block_size/sizeof (struct ext2_inode);
file_system_info.blocks_per_group=sb->s_inodes_per_group/file_system_info.inodes_per_block;
diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog
index abd188f2..6a2c8bdf 100644
--- a/lib/ext2fs/ChangeLog
+++ b/lib/ext2fs/ChangeLog
@@ -1,3 +1,14 @@
+2006-08-30 Theodore Tso <tytso@mit.edu>
+
+ * ext2fs.h (ext2fs_div_ceil): Add new function which safely
+ calculates an integer division where the result is always
+ rounded up while avoiding overflow errors.
+
+ * initialize.c (calc_reserved_gdt_blocks, ext2fs_initialize):
+ * openfs.c (ext2fs_open2): Use ext2fs_div_ceil() instead of a
+ using an open-coded expression which was subject to
+ overflows.
+
2006-08-06 Andreas Dilger <adilger@clusterfs.com>
* bitops.h (ext2fs_cpu_to_le32, ext2fs_le64_to_cpu,
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index b3c2f656..8ca5723f 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -965,6 +965,7 @@ extern int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk);
extern int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino);
extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
struct ext2_inode *inode);
+extern unsigned int ext2fs_div_ceil(unsigned int a, unsigned int b);
/*
* The actual inlined functions definitions themselves...
@@ -1132,6 +1133,16 @@ _INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
return inode->i_blocks -
(inode->i_file_acl ? fs->blocksize >> 9 : 0);
}
+
+/*
+ * This is an efficient, overflow safe way of calculating ceil((1.0 * a) / b)
+ */
+_INLINE_ unsigned int ext2fs_div_ceil(unsigned int a, unsigned int b)
+{
+ if (!a)
+ return 0;
+ return ((a - 1) / b) + 1;
+}
#undef _INLINE_
#endif
diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
index 05ba8c8a..6b476d98 100644
--- a/lib/ext2fs/initialize.c
+++ b/lib/ext2fs/initialize.c
@@ -77,8 +77,8 @@ static unsigned int calc_reserved_gdt_blocks(ext2_filsys fs)
*/
if (sb->s_blocks_count < max_blocks / 1024)
max_blocks = sb->s_blocks_count * 1024;
- rsv_groups = (max_blocks - sb->s_first_data_block + bpg - 1) / bpg;
- rsv_gdb = (rsv_groups + gdpb - 1) / gdpb - fs->desc_blocks;
+ rsv_groups = ext2fs_div_ceil(max_blocks - sb->s_first_data_block, bpg);
+ rsv_gdb = ext2fs_div_ceil(rsv_groups, gdpb) - fs->desc_blocks;
if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb))
rsv_gdb = EXT2_ADDR_PER_BLOCK(sb);
#ifdef RES_GDT_DEBUG
@@ -205,17 +205,15 @@ errcode_t ext2fs_initialize(const char *name, int flags,
}
retry:
- fs->group_desc_count = (super->s_blocks_count -
- super->s_first_data_block +
- EXT2_BLOCKS_PER_GROUP(super) - 1)
- / EXT2_BLOCKS_PER_GROUP(super);
+ fs->group_desc_count = ext2fs_div_ceil(super->s_blocks_count -
+ super->s_first_data_block,
+ EXT2_BLOCKS_PER_GROUP(super));
if (fs->group_desc_count == 0) {
retval = EXT2_ET_TOOSMALL;
goto cleanup;
}
- fs->desc_blocks = (fs->group_desc_count +
- EXT2_DESC_PER_BLOCK(super) - 1)
- / EXT2_DESC_PER_BLOCK(super);
+ fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
+ EXT2_DESC_PER_BLOCK(super));
i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize;
set_field(s_inodes_count, super->s_blocks_count / i);
@@ -233,8 +231,7 @@ retry:
* should be. But make sure that we don't allocate more than
* one bitmap's worth of inodes each group.
*/
- ipg = (super->s_inodes_count + fs->group_desc_count - 1) /
- fs->group_desc_count;
+ ipg = ext2fs_div_ceil(super->s_inodes_count, fs->group_desc_count);
if (ipg > fs->blocksize * 8) {
if (super->s_blocks_per_group >= 256) {
/* Try again with slightly different parameters */
diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
index 00149c80..f09484fc 100644
--- a/lib/ext2fs/openfs.c
+++ b/lib/ext2fs/openfs.c
@@ -258,12 +258,11 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
retval = EXT2_ET_CORRUPT_SUPERBLOCK;
goto cleanup;
}
- fs->group_desc_count = (fs->super->s_blocks_count -
- fs->super->s_first_data_block +
- blocks_per_group - 1) / blocks_per_group;
- fs->desc_blocks = (fs->group_desc_count +
- EXT2_DESC_PER_BLOCK(fs->super) - 1)
- / EXT2_DESC_PER_BLOCK(fs->super);
+ fs->group_desc_count = ext2fs_div_ceil(fs->super->s_blocks_count -
+ fs->super->s_first_data_block,
+ blocks_per_group);
+ fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
+ EXT2_DESC_PER_BLOCK(fs->super));
retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize,
&fs->group_desc);
if (retval)
diff --git a/misc/ChangeLog b/misc/ChangeLog
index 86254330..0cecaa43 100644
--- a/misc/ChangeLog
+++ b/misc/ChangeLog
@@ -1,3 +1,12 @@
+2006-08-30 Theodore Tso <tytso@mit.edu>
+
+ * mke2fs.c (parse_extended_opts): Use ext2fs_div_ceil() instead of
+ a using an open-coded expression which was subject to
+ overflows.
+
+ * filefrag.c (div_ceil, frag_report): Fix potential overflow for
+ really big filesystems.
+
2006-08-06 Theodore Tso <tytso@mit.edu>
* findsuper.c (main): Improve findsuper program by printing the
diff --git a/misc/filefrag.c b/misc/filefrag.c
index 0719d4ce..df900602 100644
--- a/misc/filefrag.c
+++ b/misc/filefrag.c
@@ -47,6 +47,13 @@ int verbose = 0;
#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
#define EXT3_IOC_GETFLAGS _IOR('f', 1, long)
+static unsigned int div_ceil(unsigned int a, unsigned int b)
+{
+ if (!a)
+ return 0;
+ return ((a - 1) / b) + 1;
+}
+
static unsigned long get_bmap(int fd, unsigned long block)
{
int ret;
@@ -105,7 +112,7 @@ static void frag_report(const char *filename)
if (verbose) {
printf("Filesystem type is: %x\n", fsinfo.f_type);
}
- cylgroups = (fsinfo.f_blocks + fsinfo.f_bsize*8-1) / fsinfo.f_bsize*8;
+ cylgroups = div_ceil(fsinfo.f_blocks, fsinfo.f_bsize*8);
if (verbose) {
printf("Filesystem cylinder groups is approximately %ld\n",
cylgroups);
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 677c5140..a581ef09 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -820,12 +820,12 @@ static void parse_extended_opts(struct ext2_super_block *param,
if (!bpg)
bpg = blocksize * 8;
gdpb = blocksize / sizeof(struct ext2_group_desc);
- group_desc_count = (param->s_blocks_count +
- bpg - 1) / bpg;
+ group_desc_count =
+ ext2fs_div_ceil(param->s_blocks_count, bpg);
desc_blocks = (group_desc_count +
gdpb - 1) / gdpb;
- rsv_groups = (resize + bpg - 1) / bpg;
- rsv_gdb = (rsv_groups + gdpb - 1) / gdpb -
+ rsv_groups = ext2fs_div_ceil(resize, bpg);
+ rsv_gdb = ext2fs_div_ceil(rsv_groups, gdpb) -
desc_blocks;
if (rsv_gdb > (int) EXT2_ADDR_PER_BLOCK(param))
rsv_gdb = EXT2_ADDR_PER_BLOCK(param);
diff --git a/resize/ChangeLog b/resize/ChangeLog
index db770ce5..32f116bc 100644
--- a/resize/ChangeLog
+++ b/resize/ChangeLog
@@ -1,3 +1,9 @@
+2006-08-30 Theodore Tso <tytso@mit.edu>
+
+ * resize2fs.c (adjust_fs_info): Use ext2fs_div_ceil() instead of a
+ using an open-coded expression which was subject to
+ overflows.
+
2006-05-22 Theodore Tso <tytso@mit.edu>
* resize2fs.8.in: Fixed spelling mistake (Addresses Debian Bug:
diff --git a/resize/resize2fs.c b/resize/resize2fs.c
index de8f00dc..f6c3ede8 100644
--- a/resize/resize2fs.c
+++ b/resize/resize2fs.c
@@ -190,15 +190,13 @@ errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs, blk_t new_size)
fs->super->s_blocks_count = new_size;
retry:
- fs->group_desc_count = (fs->super->s_blocks_count -
- fs->super->s_first_data_block +
- EXT2_BLOCKS_PER_GROUP(fs->super) - 1)
- / EXT2_BLOCKS_PER_GROUP(fs->super);
+ fs->group_desc_count = ext2fs_div_ceil(fs->super->s_blocks_count -
+ fs->super->s_first_data_block,
+ EXT2_BLOCKS_PER_GROUP(fs->super));
if (fs->group_desc_count == 0)
return EXT2_ET_TOOSMALL;
- fs->desc_blocks = (fs->group_desc_count +
- EXT2_DESC_PER_BLOCK(fs->super) - 1)
- / EXT2_DESC_PER_BLOCK(fs->super);
+ fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
+ EXT2_DESC_PER_BLOCK(fs->super));
/*
* Overhead is the number of bookkeeping blocks per group. It