aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2017-01-09 10:38:51 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-12 05:39:42 -0500
commitb85f32481d93a23488d208fca4558e84515dc0f4 (patch)
tree37fc914d5e42c633c1ac82b1db1ebb8a61065f6d /fs
parent4081d4a79a95252486569b014b9a666ad5bfdbee (diff)
xfs: forbid AG btrees with level == 0
commit d2a047f31e86941fa896e0e3271536d50aba415e upstream. 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> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c10
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c9
2 files changed, 15 insertions, 4 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index effb64cf714f..5050056a0b06 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -2455,12 +2455,15 @@ xfs_agf_verify(
2455 be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp))) 2455 be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp)))
2456 return false; 2456 return false;
2457 2457
2458 if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) > XFS_BTREE_MAXLEVELS || 2458 if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) < 1 ||
2459 be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) < 1 ||
2460 be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) > XFS_BTREE_MAXLEVELS ||
2459 be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > XFS_BTREE_MAXLEVELS) 2461 be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > XFS_BTREE_MAXLEVELS)
2460 return false; 2462 return false;
2461 2463
2462 if (xfs_sb_version_hasrmapbt(&mp->m_sb) && 2464 if (xfs_sb_version_hasrmapbt(&mp->m_sb) &&
2463 be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > XFS_BTREE_MAXLEVELS) 2465 (be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) < 1 ||
2466 be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > XFS_BTREE_MAXLEVELS))
2464 return false; 2467 return false;
2465 2468
2466 /* 2469 /*
@@ -2477,7 +2480,8 @@ xfs_agf_verify(
2477 return false; 2480 return false;
2478 2481
2479 if (xfs_sb_version_hasreflink(&mp->m_sb) && 2482 if (xfs_sb_version_hasreflink(&mp->m_sb) &&
2480 be32_to_cpu(agf->agf_refcount_level) > XFS_BTREE_MAXLEVELS) 2483 (be32_to_cpu(agf->agf_refcount_level) < 1 ||
2484 be32_to_cpu(agf->agf_refcount_level) > XFS_BTREE_MAXLEVELS))
2481 return false; 2485 return false;
2482 2486
2483 return true;; 2487 return true;;
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index c482b9716347..d45c03779dae 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -2510,8 +2510,15 @@ xfs_agi_verify(
2510 if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum))) 2510 if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)))
2511 return false; 2511 return false;
2512 2512
2513 if (be32_to_cpu(agi->agi_level) > XFS_BTREE_MAXLEVELS) 2513 if (be32_to_cpu(agi->agi_level) < 1 ||
2514 be32_to_cpu(agi->agi_level) > XFS_BTREE_MAXLEVELS)
2514 return false; 2515 return false;
2516
2517 if (xfs_sb_version_hasfinobt(&mp->m_sb) &&
2518 (be32_to_cpu(agi->agi_free_level) < 1 ||
2519 be32_to_cpu(agi->agi_free_level) > XFS_BTREE_MAXLEVELS))
2520 return false;
2521
2515 /* 2522 /*
2516 * during growfs operations, the perag is not fully initialised, 2523 * during growfs operations, the perag is not fully initialised,
2517 * so we can't use it for any useful checking. growfs ensures we can't 2524 * so we can't use it for any useful checking. growfs ensures we can't