xfs: don't allow overly small or large realtime volumes
authorDarrick J. Wong <djwong@kernel.org>
Fri, 1 Dec 2023 17:24:18 +0000 (09:24 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 7 Dec 2023 02:45:17 +0000 (18:45 -0800)
Don't allow realtime volumes that are less than one rt extent long.
This has been broken across 4 LTS kernels with nobody noticing, so let's
just disable it.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_rtbitmap.h
fs/xfs/libxfs/xfs_sb.c
fs/xfs/xfs_rtalloc.c

index 6e5bae324cc3763f55ff21569f30cade29e7da3a..1c84b52de3d42455ca2f56d7e848a14ca144073d 100644 (file)
@@ -353,6 +353,18 @@ int xfs_rtfree_blocks(struct xfs_trans *tp, xfs_fsblock_t rtbno,
 
 uint8_t xfs_compute_rextslog(xfs_rtbxlen_t rtextents);
 
+/* Do we support an rt volume having this number of rtextents? */
+static inline bool
+xfs_validate_rtextents(
+       xfs_rtbxlen_t           rtextents)
+{
+       /* No runt rt volumes */
+       if (rtextents == 0)
+               return false;
+
+       return true;
+}
+
 xfs_filblks_t xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t
                rtextents);
 unsigned long long xfs_rtbitmap_wordcount(struct xfs_mount *mp,
@@ -372,6 +384,7 @@ unsigned long long xfs_rtsummary_wordcount(struct xfs_mount *mp,
 # define xfs_rtbuf_cache_relse(a)                      (0)
 # define xfs_rtalloc_extent_is_free(m,t,s,l,i)         (-ENOSYS)
 # define xfs_compute_rextslog(rtx)                     (0)
+# define xfs_validate_rtextents(rtx)                   (false)
 static inline xfs_filblks_t
 xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t rtextents)
 {
index df12bf82ed18f99062991165a924133abf2e2216..4a9e8588f4c98c3647a85682d56fe26620a59ffc 100644 (file)
@@ -509,7 +509,8 @@ xfs_validate_sb_common(
                rbmblocks = howmany_64(sbp->sb_rextents,
                                       NBBY * sbp->sb_blocksize);
 
-               if (sbp->sb_rextents != rexts ||
+               if (!xfs_validate_rtextents(rexts) ||
+                   sbp->sb_rextents != rexts ||
                    sbp->sb_rextslog != xfs_compute_rextslog(rexts) ||
                    sbp->sb_rbmblocks != rbmblocks) {
                        xfs_notice(mp,
index 7c5a50163d2dbab52404c5e1590197a444bd5115..8feb58c6241ce4b965b0bf7d1aa7afae03cfa9e3 100644 (file)
@@ -963,6 +963,8 @@ xfs_growfs_rt(
         */
        nrextents = nrblocks;
        do_div(nrextents, in->extsize);
+       if (!xfs_validate_rtextents(nrextents))
+               return -EINVAL;
        nrbmblocks = xfs_rtbitmap_blockcount(mp, nrextents);
        nrextslog = xfs_compute_rextslog(nrextents);
        nrsumlevels = nrextslog + 1;