diff options
author | Eric Sandeen <esandeen@redhat.com> | 2006-09-27 01:49:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-27 08:26:10 -0700 |
commit | 32c2d2bc4bed61323f14f2a7d69ccbd567253d8a (patch) | |
tree | 07b65d42ae5fa3d38ad8832928408dcd4aa31fc6 | |
parent | a4e4de36dc446b2193bdc8ebb96a96e44b69dd94 (diff) | |
download | linux-32c2d2bc4bed61323f14f2a7d69ccbd567253d8a.tar.bz2 |
[PATCH] more ext3 16T overflow fixes
Some of the changes in balloc.c are just cosmetic, as Andreas pointed out -
if they overflow they'll then underflow and things are fine.
5th hunk actually fixes an overflow problem.
Also check for potential overflows in inode & block counts when resizing.
Signed-off-by: Eric Sandeen <esandeen@redhat.com>
Cc: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/ext3/balloc.c | 12 | ||||
-rw-r--r-- | fs/ext3/resize.c | 17 |
2 files changed, 23 insertions, 6 deletions
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index c19be8fc3e51..b41a7d7e20f0 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -202,7 +202,7 @@ goal_in_my_reservation(struct ext3_reserve_window *rsv, ext3_grpblk_t grp_goal, ext3_fsblk_t group_first_block, group_last_block; group_first_block = ext3_group_first_block_no(sb, group); - group_last_block = group_first_block + EXT3_BLOCKS_PER_GROUP(sb) - 1; + group_last_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1); if ((rsv->_rsv_start > group_last_block) || (rsv->_rsv_end < group_first_block)) @@ -1047,7 +1047,7 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv, spinlock_t *rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock; group_first_block = ext3_group_first_block_no(sb, group); - group_end_block = group_first_block + EXT3_BLOCKS_PER_GROUP(sb) - 1; + group_end_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1); if (grp_goal < 0) start_block = group_first_block; @@ -1239,7 +1239,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, struct ext3_reserve_window_node * my_rsv, unsigned long *count, int *errp) { - ext3_fsblk_t group_first_block; + ext3_fsblk_t group_first_block, group_last_block; ext3_grpblk_t ret = 0; int fatal; unsigned long num = *count; @@ -1276,6 +1276,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, * first block is the block number of the first block in this group */ group_first_block = ext3_group_first_block_no(sb, group); + group_last_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1); /* * Basically we will allocate a new block from inode's reservation @@ -1311,9 +1312,8 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, try_to_extend_reservation(my_rsv, sb, *count-my_rsv->rsv_end + grp_goal - 1); - if ((my_rsv->rsv_start >= group_first_block + - EXT3_BLOCKS_PER_GROUP(sb)) - || (my_rsv->rsv_end < group_first_block)) { + if ((my_rsv->rsv_start > group_last_block) || + (my_rsv->rsv_end < group_first_block)) { rsv_window_dump(&EXT3_SB(sb)->s_rsv_window_root, 1); BUG(); } diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index e186f7fb698b..9e318a5cfc87 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c @@ -731,6 +731,18 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input) return -EPERM; } + if (le32_to_cpu(es->s_blocks_count) + input->blocks_count < + le32_to_cpu(es->s_blocks_count)) { + ext3_warning(sb, __FUNCTION__, "blocks_count overflow\n"); + return -EINVAL; + } + + if (le32_to_cpu(es->s_inodes_count) + EXT3_INODES_PER_GROUP(sb) < + le32_to_cpu(es->s_inodes_count)) { + ext3_warning(sb, __FUNCTION__, "inodes_count overflow\n"); + return -EINVAL; + } + if (reserved_gdb || gdb_off == 0) { if (!EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_RESIZE_INODE)){ @@ -959,6 +971,11 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, add = EXT3_BLOCKS_PER_GROUP(sb) - last; + if (o_blocks_count + add < o_blocks_count) { + ext3_warning(sb, __FUNCTION__, "blocks_count overflow"); + return -EINVAL; + } + if (o_blocks_count + add > n_blocks_count) add = n_blocks_count - o_blocks_count; |