aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Motin <[email protected]>2023-09-29 11:22:46 -0400
committerBrian Behlendorf <[email protected]>2023-10-03 09:06:07 -0700
commit3079bf2e6c0733b9bccac573324871f49dd6d503 (patch)
treef0532a2838e0eb176e9d069ce1d8ab03e3399763
parentb34bf2d5f6158c8ebeb47687a3fb7a2d3cc3aea7 (diff)
Restrict short block cloning requests
If we are copying only one block and it is smaller than recordsize property, do not allow destination to grow beyond one block if it is not there yet. Otherwise the destination will get stuck with that block size forever, that can be as small as 512 bytes, no matter how big the destination grow later. Reviewed-by: Kay Pedersen <[email protected]> Reviewed-by: Rob Norris <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Alexander Motin <[email protected]> Sponsored by: iXsystems, Inc. Closes #15321
-rw-r--r--module/zfs/zfs_vnops.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c
index a64e1e2dc..40d6c87a7 100644
--- a/module/zfs/zfs_vnops.c
+++ b/module/zfs/zfs_vnops.c
@@ -1206,6 +1206,19 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp,
goto unlock;
}
+ /*
+ * If we are copying only one block and it is smaller than recordsize
+ * property, do not allow destination to grow beyond one block if it
+ * is not there yet. Otherwise the destination will get stuck with
+ * that block size forever, that can be as small as 512 bytes, no
+ * matter how big the destination grow later.
+ */
+ if (len <= inblksz && inblksz < outzfsvfs->z_max_blksz &&
+ outzp->z_size <= inblksz && outoff + len > inblksz) {
+ error = SET_ERROR(EINVAL);
+ goto unlock;
+ }
+
error = zn_rlimit_fsize(outoff + len);
if (error != 0) {
goto unlock;