]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: forbid AG btrees with level == 0
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 10 Jan 2017 02:18:49 +0000 (20:18 -0600)
committerEric Sandeen <sandeen@redhat.com>
Tue, 10 Jan 2017 02:18:49 +0000 (20:18 -0600)
Source kernel commit: d2a047f31e86941fa896e0e3271536d50aba415e

There is no such thing as a zero-level AG btree since even a single-node
zero-records btree has one level.  Btree cursor constructors read
cur_nlevels straight from disk and then access things like
cur_bufs[cur_nlevels - 1] which is /really/ bad if cur_nlevels is zero!
Therefore, strengthen the verifiers to prevent this possibility.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/xfs_alloc.c
libxfs/xfs_ialloc.c

index 1ca32685766df68fe18d593b96a0d9da6d4080e3..a12d5c65e89cd97f4511bcb0d053e4c51c831c91 100644 (file)
@@ -2451,12 +2451,15 @@ xfs_agf_verify(
              be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp)))
                return false;
 
-       if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) > XFS_BTREE_MAXLEVELS ||
+       if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) < 1 ||
+           be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) < 1 ||
+           be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) > XFS_BTREE_MAXLEVELS ||
            be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > XFS_BTREE_MAXLEVELS)
                return false;
 
        if (xfs_sb_version_hasrmapbt(&mp->m_sb) &&
-           be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > XFS_BTREE_MAXLEVELS)
+           (be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) < 1 ||
+            be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > XFS_BTREE_MAXLEVELS))
                return false;
 
        /*
@@ -2473,7 +2476,8 @@ xfs_agf_verify(
                return false;
 
        if (xfs_sb_version_hasreflink(&mp->m_sb) &&
-           be32_to_cpu(agf->agf_refcount_level) > XFS_BTREE_MAXLEVELS)
+           (be32_to_cpu(agf->agf_refcount_level) < 1 ||
+            be32_to_cpu(agf->agf_refcount_level) > XFS_BTREE_MAXLEVELS))
                return false;
 
        return true;;
index 31ab2a7dc8a87a2a4b038004b8bb658ac01bb289..4f1b2fe71f70d15dd88f04335df67c6a2e85231c 100644 (file)
@@ -2505,8 +2505,15 @@ xfs_agi_verify(
        if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)))
                return false;
 
-       if (be32_to_cpu(agi->agi_level) > XFS_BTREE_MAXLEVELS)
+       if (be32_to_cpu(agi->agi_level) < 1 ||
+           be32_to_cpu(agi->agi_level) > XFS_BTREE_MAXLEVELS)
                return false;
+
+       if (xfs_sb_version_hasfinobt(&mp->m_sb) &&
+           (be32_to_cpu(agi->agi_free_level) < 1 ||
+            be32_to_cpu(agi->agi_free_level) > XFS_BTREE_MAXLEVELS))
+               return false;
+
        /*
         * during growfs operations, the perag is not fully initialised,
         * so we can't use it for any useful checking. growfs ensures we can't