📄 ext3-16tb-overflow-fixes.patch
字号:
EXT3_XATTR_REFCOUNT_MAX) {Date: Tue, 19 Sep 2006 15:32:02 -0500From: Eric Sandeen <esandeen@redhat.com>Subject: [RHEL5 Patch 1/3] (resend) Fix ext3 overflows at 16TThis one is in -mm as fix-ext3-mounts-at-16t.patch and fix-ext3-mounts-at-16t-fix.patch this gets things mounting for a 16T ext3 filesystem. (patched up e2fsprogs will be needed too, working on that)jarod wilson has been helping with testing.This patch fixes these issues in the kernel:o sbi->s_groups_count overflows in ext3_fill_super() sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) - le32_to_cpu(es->s_first_data_block) + EXT3_BLOCKS_PER_GROUP(sb) - 1) / EXT3_BLOCKS_PER_GROUP(sb); at 16T, s_blocks_count is already maxed out; adding EXT3_BLOCKS_PER_GROUP(sb) overflows it and groups_count comes out to 0. Not really what we want, and causes a failed mount. Changing it this way works & avoids the overflow: (A + B - 1)/B changed to: ((A - 1)/B) + 1o ext3_check_descriptors() overflows range checks ext3_check_descriptors() iterates over all block groups making sure that various bits are within the right block ranges... on the last pass through, it is checking the error case [item] >= block + EXT3_BLOCKS_PER_GROUP(sb) where "block" is the first block in the last block group. The last block in this group (and the last one that will fit in 32 bits) is block + EXT3_BLOCKS_PER_GROUP(sb)- 1. block + EXT3_BLOCKS_PER_GROUP(sb) wraps back around to 0. so, make things clearer with "first_block" and "last_block" where those are first and last, inclusive, and use <, > rather than <, >=. Finally, the last block group may be smaller than the rest, so account for this on the last pass through: last_block = sb->s_blocks_count - 1;Signed-off-by: Eric Sandeen <esandeen@redhat.com>Cc: Mingming Cao <cmm@us.ibm.com>Signed-off-by: Andrew Morton <akpm@osdl.org>Index: linux-2.6.17-1.2654.el5/fs/ext3/super.c===================================================================--- linux-2.6.17-1.2654.el5.orig/fs/ext3/super.c+++ linux-2.6.17-1.2654.el5/fs/ext3/super.c@@ -1132,7 +1132,8 @@ static int ext3_setup_super(struct super static int ext3_check_descriptors (struct super_block * sb) { struct ext3_sb_info *sbi = EXT3_SB(sb);- ext3_fsblk_t block = le32_to_cpu(sbi->s_es->s_first_data_block);+ ext3_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);+ ext3_fsblk_t last_block; struct ext3_group_desc * gdp = NULL; int desc_block = 0; int i;@@ -1141,12 +1142,17 @@ static int ext3_check_descriptors (struc for (i = 0; i < sbi->s_groups_count; i++) {+ if (i == sbi->s_groups_count - 1)+ last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;+ else+ last_block = first_block ++ (EXT3_BLOCKS_PER_GROUP(sb) - 1);+ if ((i % EXT3_DESC_PER_BLOCK(sb)) == 0) gdp = (struct ext3_group_desc *) sbi->s_group_desc[desc_block++]->b_data;- if (le32_to_cpu(gdp->bg_block_bitmap) < block ||- le32_to_cpu(gdp->bg_block_bitmap) >=- block + EXT3_BLOCKS_PER_GROUP(sb))+ if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||+ le32_to_cpu(gdp->bg_block_bitmap) > last_block) { ext3_error (sb, "ext3_check_descriptors", "Block bitmap for group %d"@@ -1155,9 +1161,8 @@ static int ext3_check_descriptors (struc le32_to_cpu(gdp->bg_block_bitmap)); return 0; }- if (le32_to_cpu(gdp->bg_inode_bitmap) < block ||- le32_to_cpu(gdp->bg_inode_bitmap) >=- block + EXT3_BLOCKS_PER_GROUP(sb))+ if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block ||+ le32_to_cpu(gdp->bg_inode_bitmap) > last_block) { ext3_error (sb, "ext3_check_descriptors", "Inode bitmap for group %d"@@ -1166,9 +1171,9 @@ static int ext3_check_descriptors (struc le32_to_cpu(gdp->bg_inode_bitmap)); return 0; }- if (le32_to_cpu(gdp->bg_inode_table) < block ||- le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >=- block + EXT3_BLOCKS_PER_GROUP(sb))+ if (le32_to_cpu(gdp->bg_inode_table) < first_block ||+ le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >+ last_block) { ext3_error (sb, "ext3_check_descriptors", "Inode table for group %d"@@ -1177,7 +1182,7 @@ static int ext3_check_descriptors (struc le32_to_cpu(gdp->bg_inode_table)); return 0; }- block += EXT3_BLOCKS_PER_GROUP(sb);+ first_block += EXT3_BLOCKS_PER_GROUP(sb); gdp++; } @@ -1580,10 +1585,9 @@ static int ext3_fill_super (struct super if (EXT3_BLOCKS_PER_GROUP(sb) == 0) goto cantfind_ext3;- sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -- le32_to_cpu(es->s_first_data_block) +- EXT3_BLOCKS_PER_GROUP(sb) - 1) /- EXT3_BLOCKS_PER_GROUP(sb);+ sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -+ le32_to_cpu(es->s_first_data_block) - 1)+ / EXT3_BLOCKS_PER_GROUP(sb)) + 1; db_count = (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) / EXT3_DESC_PER_BLOCK(sb); sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),Date: Tue, 19 Sep 2006 15:32:42 -0500From: Eric Sandeen <esandeen@redhat.com>Subject: [RHEL5 Patch 2/3] (resend) Fix more ext3 overflows at 16TThis is in akpm's tree asmore-ext3-16t-overflow-fixes.patch and more-ext3-16t-overflow-fixes-fix.patchSome of the changes in balloc.c are just cosmetic -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>Index: linux-2.6.17-1.2654.el5/fs/ext3/balloc.c===================================================================--- linux-2.6.17-1.2654.el5.orig/fs/ext3/balloc.c+++ linux-2.6.17-1.2654.el5/fs/ext3/balloc.c@@ -168,7 +168,7 @@ goal_in_my_reservation(struct ext3_reser 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))@@ -897,7 +897,7 @@ static int alloc_new_reservation(struct 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;@@ -1063,7 +1063,7 @@ ext3_try_to_allocate_with_rsv(struct sup 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;@@ -1100,6 +1100,7 @@ ext3_try_to_allocate_with_rsv(struct sup * 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@@ -1132,8 +1133,8 @@ ext3_try_to_allocate_with_rsv(struct sup 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)) BUG(); ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, grp_goal, &num, &my_rsv->rsv_window);Index: linux-2.6.17-1.2654.el5/fs/ext3/resize.c===================================================================--- linux-2.6.17-1.2654.el5.orig/fs/ext3/resize.c+++ linux-2.6.17-1.2654.el5/fs/ext3/resize.c@@ -730,6 +730,18 @@ int ext3_group_add(struct super_block *s 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)){@@ -958,6 +970,11 @@ int ext3_group_extend(struct super_block 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -