]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: make sure aglen never goes negative in xfs_refcount_adjust_extents
authorDarrick J. Wong <djwong@kernel.org>
Fri, 18 Nov 2022 10:00:45 +0000 (11:00 +0100)
committerCarlos Maiolino <cem@kernel.org>
Mon, 21 Nov 2022 14:26:48 +0000 (15:26 +0100)
Source kernel commit: f850995f60e49818093ef5e477cdb0ff2c11a0a4

Prior to calling xfs_refcount_adjust_extents, we trimmed agbno/aglen
such that the end of the range would not be in the middle of a refcount
record.  If this is no longer the case, something is seriously wrong
with the btree.  Bail out with a corruption error.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
libxfs/xfs_refcount.c

index bcd760fe12be76424532d04404fba9d248ea7be9..146e833b0d180527a1820f90fa362904814d934e 100644 (file)
@@ -985,15 +985,29 @@ xfs_refcount_adjust_extents(
                        (*agbno) += tmp.rc_blockcount;
                        (*aglen) -= tmp.rc_blockcount;
 
+                       /* Stop if there's nothing left to modify */
+                       if (*aglen == 0 || !xfs_refcount_still_have_space(cur))
+                               break;
+
+                       /* Move the cursor to the start of ext. */
                        error = xfs_refcount_lookup_ge(cur, *agbno,
                                        &found_rec);
                        if (error)
                                goto out_error;
                }
 
-               /* Stop if there's nothing left to modify */
-               if (*aglen == 0 || !xfs_refcount_still_have_space(cur))
-                       break;
+               /*
+                * A previous step trimmed agbno/aglen such that the end of the
+                * range would not be in the middle of the record.  If this is
+                * no longer the case, something is seriously wrong with the
+                * btree.  Make sure we never feed the synthesized record into
+                * the processing loop below.
+                */
+               if (XFS_IS_CORRUPT(cur->bc_mp, ext.rc_blockcount == 0) ||
+                   XFS_IS_CORRUPT(cur->bc_mp, ext.rc_blockcount > *aglen)) {
+                       error = -EFSCORRUPTED;
+                       goto out_error;
+               }
 
                /*
                 * Adjust the reference count and either update the tree