2.4.36-stable kernel tree
修订版 | bf97a67dc4195ce0a3d5487a6287bc050aee864c (tree) |
---|---|
时间 | 2006-11-20 02:02:09 |
作者 | Willy Tarreau <w@1wt....> |
Commiter | Willy Tarreau |
[PATCH] EXT2: avoid crashing by not dividing by zero.
backport a few checks from 2.6 to avoid dividing by zero on invalid
superblocks.
@@ -480,12 +480,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, | ||
480 | 480 | es = (struct ext2_super_block *) (((char *)bh->b_data) + offset); |
481 | 481 | sb->u.ext2_sb.s_es = es; |
482 | 482 | sb->s_magic = le16_to_cpu(es->s_magic); |
483 | - if (sb->s_magic != EXT2_SUPER_MAGIC) { | |
484 | - if (!silent) | |
485 | - printk ("VFS: Can't find ext2 filesystem on dev %s.\n", | |
486 | - bdevname(dev)); | |
487 | - goto failed_mount; | |
488 | - } | |
483 | + if (sb->s_magic != EXT2_SUPER_MAGIC) | |
484 | + goto cantfind_ext2; | |
489 | 485 | if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV && |
490 | 486 | (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) || |
491 | 487 | EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) || |
@@ -561,16 +557,19 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, | ||
561 | 557 | } |
562 | 558 | sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE << |
563 | 559 | le32_to_cpu(es->s_log_frag_size); |
564 | - if (sb->u.ext2_sb.s_frag_size) | |
565 | - sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize / | |
566 | - sb->u.ext2_sb.s_frag_size; | |
567 | - else | |
568 | - sb->s_magic = 0; | |
560 | + if (sb->u.ext2_sb.s_frag_size == 0) | |
561 | + goto cantfind_ext2; | |
562 | + sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize / | |
563 | + sb->u.ext2_sb.s_frag_size; | |
569 | 564 | sb->u.ext2_sb.s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group); |
570 | 565 | sb->u.ext2_sb.s_frags_per_group = le32_to_cpu(es->s_frags_per_group); |
571 | 566 | sb->u.ext2_sb.s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group); |
567 | + if (EXT2_INODE_SIZE(sb) == 0) | |
568 | + goto cantfind_ext2; | |
572 | 569 | sb->u.ext2_sb.s_inodes_per_block = sb->s_blocksize / |
573 | 570 | EXT2_INODE_SIZE(sb); |
571 | + if (sb->u.ext2_sb.s_inodes_per_block == 0) | |
572 | + goto cantfind_ext2; | |
574 | 573 | sb->u.ext2_sb.s_itb_per_group = sb->u.ext2_sb.s_inodes_per_group / |
575 | 574 | sb->u.ext2_sb.s_inodes_per_block; |
576 | 575 | sb->u.ext2_sb.s_desc_per_block = sb->s_blocksize / |
@@ -589,13 +588,10 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, | ||
589 | 588 | log2 (EXT2_ADDR_PER_BLOCK(sb)); |
590 | 589 | sb->u.ext2_sb.s_desc_per_block_bits = |
591 | 590 | log2 (EXT2_DESC_PER_BLOCK(sb)); |
592 | - if (sb->s_magic != EXT2_SUPER_MAGIC) { | |
593 | - if (!silent) | |
594 | - printk ("VFS: Can't find an ext2 filesystem on dev " | |
595 | - "%s.\n", | |
596 | - bdevname(dev)); | |
597 | - goto failed_mount; | |
598 | - } | |
591 | + | |
592 | + if (sb->s_magic != EXT2_SUPER_MAGIC) | |
593 | + goto cantfind_ext2; | |
594 | + | |
599 | 595 | if (sb->s_blocksize != bh->b_size) { |
600 | 596 | if (!silent) |
601 | 597 | printk ("VFS: Unsupported blocksize on dev " |
@@ -625,6 +621,8 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, | ||
625 | 621 | goto failed_mount; |
626 | 622 | } |
627 | 623 | |
624 | + if (EXT2_BLOCKS_PER_GROUP(sb) == 0) | |
625 | + goto cantfind_ext2; | |
628 | 626 | sb->u.ext2_sb.s_groups_count = (le32_to_cpu(es->s_blocks_count) - |
629 | 627 | le32_to_cpu(es->s_first_data_block) + |
630 | 628 | EXT2_BLOCKS_PER_GROUP(sb) - 1) / |
@@ -678,6 +676,11 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data, | ||
678 | 676 | } |
679 | 677 | ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); |
680 | 678 | return sb; |
679 | +cantfind_ext2: | |
680 | + if (!silent) | |
681 | + printk ("VFS: Can't find ext2 filesystem on dev %s.\n", | |
682 | + bdevname(dev)); | |
683 | + goto failed_mount; | |
681 | 684 | failed_mount2: |
682 | 685 | for (i = 0; i < db_count; i++) |
683 | 686 | brelse(sb->u.ext2_sb.s_group_desc[i]); |