aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@sandeen.net>2020-10-01 08:34:48 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-10-07 08:01:24 +0200
commitaee38af574a136425d89cf4760ece0e0c2fe0fb3 (patch)
treecabdc68651d59e944ed2e16127d10f9b2e4e071f
parentnet: virtio_vsock: Enhance connection semantics (diff)
downloadwireguard-linux-aee38af574a136425d89cf4760ece0e0c2fe0fb3.tar.xz
wireguard-linux-aee38af574a136425d89cf4760ece0e0c2fe0fb3.zip
xfs: trim IO to found COW extent limit
A bug existed in the XFS reflink code between v5.1 and v5.5 in which the mapping for a COW IO was not trimmed to the mapping of the COW extent that was found. This resulted in a too-short copy, and corruption of other files which shared the original extent. (This happened only when extent size hints were set, which bypasses delalloc and led to this code path.) This was (inadvertently) fixed upstream with 36adcbace24e "xfs: fill out the srcmap in iomap_begin" and related patches which moved lots of this functionality to the iomap subsystem. Hence, this is a -stable only patch, targeted to fix this corruption vector without other major code changes. Fixes: 78f0cc9d55cb ("xfs: don't use delalloc extents for COW on files with extsize hints") Cc: <stable@vger.kernel.org> # 5.4.x Signed-off-by: Eric Sandeen <sandeen@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--fs/xfs/xfs_iomap.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index f780e223b118..239c9548b156 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -1002,9 +1002,15 @@ xfs_file_iomap_begin(
* I/O, which must be block aligned, we need to report the
* newly allocated address. If the data fork has a hole, copy
* the COW fork mapping to avoid allocating to the data fork.
+ *
+ * Otherwise, ensure that the imap range does not extend past
+ * the range allocated/found in cmap.
*/
if (directio || imap.br_startblock == HOLESTARTBLOCK)
imap = cmap;
+ else
+ xfs_trim_extent(&imap, cmap.br_startoff,
+ cmap.br_blockcount);
end_fsb = imap.br_startoff + imap.br_blockcount;
length = XFS_FSB_TO_B(mp, end_fsb) - offset;