Whamcloud - gitweb
libext2fs: avoid 32-bit overflow in ext2fs_initialize with a 512M cluster size
authorTheodore Ts'o <tytso@mit.edu>
Tue, 15 Jan 2013 00:29:54 +0000 (19:29 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 15 Jan 2013 19:08:18 +0000 (14:08 -0500)
If the user attemps to create a 512MB cluster, we need to adjust the
defaults to avoid a 32-bit overflow of s_blocks_per_group.  Also check
to make sure that the caller of ext2fs_initialize() has not given a
value of s_clusters_per_group that would result in an overflow of
s_blocks_per_group.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Reviewed-by: Zheng Liu <wenqing.lz@taobao.com>
lib/ext2fs/initialize.c

index b0c15d2..5afdc27 100644 (file)
@@ -207,6 +207,8 @@ errcode_t ext2fs_initialize(const char *name, int flags,
                super->s_log_block_size;
 
        if (bigalloc_flag) {
+               unsigned long long bpg;
+
                if (param->s_blocks_per_group &&
                    param->s_clusters_per_group &&
                    ((param->s_clusters_per_group * EXT2FS_CLUSTER_RATIO(fs)) !=
@@ -220,12 +222,19 @@ errcode_t ext2fs_initialize(const char *name, int flags,
                        super->s_clusters_per_group = 
                                param->s_blocks_per_group /
                                EXT2FS_CLUSTER_RATIO(fs);
-               else
+               else if (super->s_log_cluster_size + 15 < 32)
                        super->s_clusters_per_group = fs->blocksize * 8;
+               else
+                       super->s_clusters_per_group = (fs->blocksize - 1) * 8;
                if (super->s_clusters_per_group > EXT2_MAX_CLUSTERS_PER_GROUP(super))
                        super->s_clusters_per_group = EXT2_MAX_CLUSTERS_PER_GROUP(super);
-               super->s_blocks_per_group = EXT2FS_C2B(fs,
-                                      super->s_clusters_per_group);
+               bpg = EXT2FS_C2B(fs,
+                       (unsigned long long) super->s_clusters_per_group);
+               if (bpg >= (((unsigned long long) 1) << 32)) {
+                       retval = EXT2_ET_INVALID_ARGUMENT;
+                       goto cleanup;
+               }
+               super->s_blocks_per_group = bpg;
        } else {
                set_field(s_blocks_per_group, fs->blocksize * 8);
                if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super))