aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorEric Sandeen <esandeen@redhat.com>2006-09-27 04:49:36 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-27 11:26:10 -0400
commit32c2d2bc4bed61323f14f2a7d69ccbd567253d8a (patch)
tree07b65d42ae5fa3d38ad8832928408dcd4aa31fc6 /fs
parenta4e4de36dc446b2193bdc8ebb96a96e44b69dd94 (diff)
[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>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext3/balloc.c12
-rw-r--r--fs/ext3/resize.c17
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,
202 ext3_fsblk_t group_first_block, group_last_block; 202 ext3_fsblk_t group_first_block, group_last_block;
203 203
204 group_first_block = ext3_group_first_block_no(sb, group); 204 group_first_block = ext3_group_first_block_no(sb, group);
205 group_last_block = group_first_block + EXT3_BLOCKS_PER_GROUP(sb) - 1; 205 group_last_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1);
206 206
207 if ((rsv->_rsv_start > group_last_block) || 207 if ((rsv->_rsv_start > group_last_block) ||
208 (rsv->_rsv_end < group_first_block)) 208 (rsv->_rsv_end < group_first_block))
@@ -1047,7 +1047,7 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv,
1047 spinlock_t *rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock; 1047 spinlock_t *rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock;
1048 1048
1049 group_first_block = ext3_group_first_block_no(sb, group); 1049 group_first_block = ext3_group_first_block_no(sb, group);
1050 group_end_block = group_first_block + EXT3_BLOCKS_PER_GROUP(sb) - 1; 1050 group_end_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1);
1051 1051
1052 if (grp_goal < 0) 1052 if (grp_goal < 0)
1053 start_block = group_first_block; 1053 start_block = group_first_block;
@@ -1239,7 +1239,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
1239 struct ext3_reserve_window_node * my_rsv, 1239 struct ext3_reserve_window_node * my_rsv,
1240 unsigned long *count, int *errp) 1240 unsigned long *count, int *errp)
1241{ 1241{
1242 ext3_fsblk_t group_first_block; 1242 ext3_fsblk_t group_first_block, group_last_block;
1243 ext3_grpblk_t ret = 0; 1243 ext3_grpblk_t ret = 0;
1244 int fatal; 1244 int fatal;
1245 unsigned long num = *count; 1245 unsigned long num = *count;
@@ -1276,6 +1276,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
1276 * first block is the block number of the first block in this group 1276 * first block is the block number of the first block in this group
1277 */ 1277 */
1278 group_first_block = ext3_group_first_block_no(sb, group); 1278 group_first_block = ext3_group_first_block_no(sb, group);
1279 group_last_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1);
1279 1280
1280 /* 1281 /*
1281 * Basically we will allocate a new block from inode's reservation 1282 * 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,
1311 try_to_extend_reservation(my_rsv, sb, 1312 try_to_extend_reservation(my_rsv, sb,
1312 *count-my_rsv->rsv_end + grp_goal - 1); 1313 *count-my_rsv->rsv_end + grp_goal - 1);
1313 1314
1314 if ((my_rsv->rsv_start >= group_first_block + 1315 if ((my_rsv->rsv_start > group_last_block) ||
1315 EXT3_BLOCKS_PER_GROUP(sb)) 1316 (my_rsv->rsv_end < group_first_block)) {
1316 || (my_rsv->rsv_end < group_first_block)) {
1317 rsv_window_dump(&EXT3_SB(sb)->s_rsv_window_root, 1); 1317 rsv_window_dump(&EXT3_SB(sb)->s_rsv_window_root, 1);
1318 BUG(); 1318 BUG();
1319 } 1319 }
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)
731 return -EPERM; 731 return -EPERM;
732 } 732 }
733 733
734 if (le32_to_cpu(es->s_blocks_count) + input->blocks_count <
735 le32_to_cpu(es->s_blocks_count)) {
736 ext3_warning(sb, __FUNCTION__, "blocks_count overflow\n");
737 return -EINVAL;
738 }
739
740 if (le32_to_cpu(es->s_inodes_count) + EXT3_INODES_PER_GROUP(sb) <
741 le32_to_cpu(es->s_inodes_count)) {
742 ext3_warning(sb, __FUNCTION__, "inodes_count overflow\n");
743 return -EINVAL;
744 }
745
734 if (reserved_gdb || gdb_off == 0) { 746 if (reserved_gdb || gdb_off == 0) {
735 if (!EXT3_HAS_COMPAT_FEATURE(sb, 747 if (!EXT3_HAS_COMPAT_FEATURE(sb,
736 EXT3_FEATURE_COMPAT_RESIZE_INODE)){ 748 EXT3_FEATURE_COMPAT_RESIZE_INODE)){
@@ -959,6 +971,11 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
959 971
960 add = EXT3_BLOCKS_PER_GROUP(sb) - last; 972 add = EXT3_BLOCKS_PER_GROUP(sb) - last;
961 973
974 if (o_blocks_count + add < o_blocks_count) {
975 ext3_warning(sb, __FUNCTION__, "blocks_count overflow");
976 return -EINVAL;
977 }
978
962 if (o_blocks_count + add > n_blocks_count) 979 if (o_blocks_count + add > n_blocks_count)
963 add = n_blocks_count - o_blocks_count; 980 add = n_blocks_count - o_blocks_count;
964 981