]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
xfs: validate fsmap offsets specified in the query keys
authorDarrick J. Wong <djwong@kernel.org>
Wed, 11 Jun 2025 21:01:10 +0000 (14:01 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jun 2025 10:07:19 +0000 (11:07 +0100)
[ Upstream commit 3ee9351e74907fe3acb0721c315af25b05dc87da ]

Improve the validation of the fsmap offset fields in the query keys and
move the validation to the top of the function now that we have pushed
the low key adjustment code downwards.

Also fix some indenting issues that aren't worth a separate patch.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Leah Rumancik <leah.rumancik@gmail.com>
Acked-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/xfs/xfs_fsmap.c

index cdd806d80b7cff2c82c816955525322667389705..d10f2c719220d1c5d3bdebdb56829784c93c39fa 100644 (file)
@@ -802,6 +802,19 @@ xfs_getfsmap_check_keys(
        struct xfs_fsmap                *low_key,
        struct xfs_fsmap                *high_key)
 {
+       if (low_key->fmr_flags & (FMR_OF_SPECIAL_OWNER | FMR_OF_EXTENT_MAP)) {
+               if (low_key->fmr_offset)
+                       return false;
+       }
+       if (high_key->fmr_flags != -1U &&
+           (high_key->fmr_flags & (FMR_OF_SPECIAL_OWNER |
+                                   FMR_OF_EXTENT_MAP))) {
+               if (high_key->fmr_offset && high_key->fmr_offset != -1ULL)
+                       return false;
+       }
+       if (high_key->fmr_length && high_key->fmr_length != -1ULL)
+               return false;
+
        if (low_key->fmr_device > high_key->fmr_device)
                return false;
        if (low_key->fmr_device < high_key->fmr_device)
@@ -845,15 +858,15 @@ xfs_getfsmap_check_keys(
  * ----------------
  * There are multiple levels of keys and counters at work here:
  * xfs_fsmap_head.fmh_keys     -- low and high fsmap keys passed in;
- *                                these reflect fs-wide sector addrs.
+ *                                these reflect fs-wide sector addrs.
  * dkeys                       -- fmh_keys used to query each device;
- *                                these are fmh_keys but w/ the low key
- *                                bumped up by fmr_length.
+ *                                these are fmh_keys but w/ the low key
+ *                                bumped up by fmr_length.
  * xfs_getfsmap_info.next_daddr        -- next disk addr we expect to see; this
  *                                is how we detect gaps in the fsmap
                                   records and report them.
  * xfs_getfsmap_info.low/high  -- per-AG low/high keys computed from
- *                                dkeys; used to query the metadata.
+ *                                dkeys; used to query the metadata.
  */
 int
 xfs_getfsmap(
@@ -874,6 +887,8 @@ xfs_getfsmap(
        if (!xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[0]) ||
            !xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[1]))
                return -EINVAL;
+       if (!xfs_getfsmap_check_keys(&head->fmh_keys[0], &head->fmh_keys[1]))
+               return -EINVAL;
 
        use_rmap = xfs_has_rmapbt(mp) &&
                   has_capability_noaudit(current, CAP_SYS_ADMIN);
@@ -919,15 +934,8 @@ xfs_getfsmap(
         * other mapping for the same physical block range.
         */
        dkeys[0] = head->fmh_keys[0];
-       if (dkeys[0].fmr_flags & (FMR_OF_SPECIAL_OWNER | FMR_OF_EXTENT_MAP)) {
-               if (dkeys[0].fmr_offset)
-                       return -EINVAL;
-       }
        memset(&dkeys[1], 0xFF, sizeof(struct xfs_fsmap));
 
-       if (!xfs_getfsmap_check_keys(dkeys, &head->fmh_keys[1]))
-               return -EINVAL;
-
        info.next_daddr = head->fmh_keys[0].fmr_physical +
                          head->fmh_keys[0].fmr_length;
        info.fsmap_recs = fsmap_recs;