Date: Mon, 18 Mar 2019 12:09:11 +0000 (UTC) From: Fedor Uporov <fsu@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r345266 - stable/12/sys/fs/ext2fs Message-ID: <201903181209.x2IC9BJD087635@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: fsu Date: Mon Mar 18 12:09:10 2019 New Revision: 345266 URL: https://svnweb.freebsd.org/changeset/base/345266 Log: MFC: r344753: Validate block bitmaps. Reviewed by: pfg Differential Revision: https://reviews.freebsd.org/D19324 Modified: stable/12/sys/fs/ext2fs/ext2_alloc.c Modified: stable/12/sys/fs/ext2fs/ext2_alloc.c ============================================================================== --- stable/12/sys/fs/ext2fs/ext2_alloc.c Mon Mar 18 12:04:43 2019 (r345265) +++ stable/12/sys/fs/ext2fs/ext2_alloc.c Mon Mar 18 12:09:10 2019 (r345266) @@ -902,6 +902,52 @@ ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg, return (0); } +static int +ext2_b_bitmap_validate(struct m_ext2fs *fs, struct buf *bp, int cg) +{ + struct ext2_gd *gd; + uint64_t group_first_block; + unsigned int offset, max_bit; + + if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG)) { + /* + * It is not possible to check block bitmap in case of this feature, + * because the inode and block bitmaps and inode table + * blocks may not be in the group at all. + * So, skip check in this case. + */ + return (0); + } + + gd = &fs->e2fs_gd[cg]; + max_bit = fs->e2fs_fpg; + group_first_block = ((uint64_t)cg) * fs->e2fs->e2fs_fpg + + fs->e2fs->e2fs_first_dblock; + + /* Check block bitmap block number */ + offset = e2fs_gd_get_b_bitmap(gd) - group_first_block; + if (offset >= max_bit || !isset(bp->b_data, offset)) { + printf("ext2fs: bad block bitmap, group %d\n", cg); + return (EINVAL); + } + + /* Check inode bitmap block number */ + offset = e2fs_gd_get_i_bitmap(gd) - group_first_block; + if (offset >= max_bit || !isset(bp->b_data, offset)) { + printf("ext2fs: bad inode bitmap, group %d\n", cg); + return (EINVAL); + } + + /* Check inode table */ + offset = e2fs_gd_get_i_tables(gd) - group_first_block; + if (offset >= max_bit || offset + fs->e2fs_itpg >= max_bit) { + printf("ext2fs: bad inode table, group %d\n", cg); + return (EINVAL); + } + + return (0); +} + /* * Determine whether a block can be allocated. * @@ -922,40 +968,37 @@ ext2_alloccg(struct inode *ip, int cg, daddr_t bpref, ump = ip->i_ump; if (e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) == 0) return (0); + EXT2_UNLOCK(ump); error = bread(ip->i_devvp, fsbtodb(fs, e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg])), (int)fs->e2fs_bsize, NOCRED, &bp); - if (error) { - brelse(bp); - EXT2_LOCK(ump); - return (0); - } + if (error) + goto fail; + if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) || EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) { error = ext2_cg_block_bitmap_init(fs, cg, bp); - if (error) { - brelse(bp); - EXT2_LOCK(ump); - return (0); - } + if (error) + goto fail; + ext2_gd_b_bitmap_csum_set(fs, cg, bp); } error = ext2_gd_b_bitmap_csum_verify(fs, cg, bp); - if (error) { - brelse(bp); - EXT2_LOCK(ump); - return (0); - } - if (e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) == 0) { - /* - * Another thread allocated the last block in this - * group while we were waiting for the buffer. - */ - brelse(bp); - EXT2_LOCK(ump); - return (0); - } + if (error) + goto fail; + + error = ext2_b_bitmap_validate(fs,bp, cg); + if (error) + goto fail; + + /* + * Check, that another thread did not not allocate the last block in this + * group while we were waiting for the buffer. + */ + if (e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) == 0) + goto fail; + bbp = (char *)bp->b_data; if (dtog(fs, bpref) != cg) @@ -1028,11 +1071,9 @@ retry: goto retry; } bno = ext2_mapsearch(fs, bbp, bpref); - if (bno < 0) { - brelse(bp); - EXT2_LOCK(ump); - return (0); - } + if (bno < 0) + goto fail; + gotit: #ifdef INVARIANTS if (isset(bbp, bno)) { @@ -1052,6 +1093,11 @@ gotit: ext2_gd_b_bitmap_csum_set(fs, cg, bp); bdwrite(bp); return (((uint64_t)cg) * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno); + +fail: + brelse(bp); + EXT2_LOCK(ump); + return (0); } /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201903181209.x2IC9BJD087635>