Linux XFS filesystem development
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: Dave Chinner <dgc@kernel.org>
Cc: Carlos Maiolino <cem@kernel.org>,
	Norbert Szetei <norbert@doyensec.com>,
	linux-xfs@vger.kernel.org, Christoph Hellwig <hch@infradead.org>
Subject: Re: [PATCH] xfs: fix exchange-range-to-eof file size exchange
Date: Tue, 6 Oct 2026 08:00:01 -0700	[thread overview]
Message-ID: <20261006150001.GY2705364@frogsfrogsfrogs> (raw)
In-Reply-To: <asSiXW4XxBl8Kivw@dread>

On Tue, Oct 06, 2026 at 06:25:17PM +1100, Dave Chinner wrote:
> On Mon, Oct 05, 2026 at 10:09:14PM -0700, Darrick J. Wong wrote:
> > From: Darrick J. Wong <djwong@kernel.org>
> > 
> > Norbert Szetei posted a patch containing an incomplete description of a
> > bug in XFS_IOC_EXCHANGE_RANGE's TO_EOF flag.  The bug tricks
> > exchange-range into modifying a file so that it has shared blocks
> > starting beyond EOF, which is never allowed because files never have
> > written data beyond EOF, and you can only share written data blocks.
> > This is key to all the incorrect behavior that follows.
> ....
> > 
> > Having confused the file sizes, the PoC uses a second exchange-range
> > call on what looks like a non-reflinked single-block file.  Because the
> > file size is set incorrectly, exchange-range thinks it's exchanging the
> > full contents of two files and clears the reflink flag on the broken
> > file.
> 
> Hmmm, another "exchrange reflink flag coherency" bug.
> 
> Aside from fixing this specific issue, how can we prevent
> other/future logic bugs from failing to set the reflink flag
> appropriately and so never expose such a bug to userspace again?
> 
> I'm thinking that we should not try to swap the reflink flag along
> with the extents. Instead, if one of the files had the reflink flag
> set before the swap, then we scan scan the extents of both files
> after the swap for shared extents and set the reflink flags for each
> file appropriately.  EXCHRANGE isn't really performance sensitive,
> so the cost of the refcount scans shouldn't be an issue.
> 
> Setting the flags this way means it doesn't matter what file shared
> extent(s) ends up in, the inode(s) that owns it(them) will always
> have the reflink flag set correctly. Hence there is no way to use
> EXCHRANGE creatively to expose this "didn't COW when it should have'
> class of corruption bugs ever again...

That is what Norbert's patch actually does.  If you think removing
xfs_exchmaps_clear_reflink and all the stuff that calls it is a good
idea (and it probably is!) then let's move that discussion and review to
that patch's thread.

> > That enables an extending write of the broken file to rewrite the
> > shared block that's just past EOF.  This has become known colloquially
> > as refluxfs.
> > 
> > Once the file sizes are set correctly, the second exchange-range no
> > longer thinks that it's doing a full-contents swap, so it won't clear
> > the reflink flag on either of its file arguments.
> > 
> > Link: https://lore.kernel.org/linux-xfs/1E196589-DEBE-40AC-AFEA-D420DAAB067F@doyensec.com/
> > Reported-by: Norbert Szetei <norbert@doyensec.com>
> > Cc: <stable@vger.kernel.org> # v6.10
> > Fixes: 966ceafc7a4371 ("xfs: create deferred log items for file mapping exchanges")
> > Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
> > ---
> >  fs/xfs/libxfs/xfs_exchmaps.c |    8 ++++++--
> >  fs/xfs/xfs_exchrange.c       |   10 ++++++----
> >  2 files changed, 12 insertions(+), 6 deletions(-)
> > 
> > diff --git a/fs/xfs/libxfs/xfs_exchmaps.c b/fs/xfs/libxfs/xfs_exchmaps.c
> > index 6a66b6075e0af4..c9d9464e9d39f5 100644
> > --- a/fs/xfs/libxfs/xfs_exchmaps.c
> > +++ b/fs/xfs/libxfs/xfs_exchmaps.c
> > @@ -987,6 +987,7 @@ xfs_exchmaps_init_intent(
> >  	const struct xfs_exchmaps_req	*req)
> >  {
> >  	struct xfs_exchmaps_intent	*xmi;
> > +	struct xfs_mount		*mp = req->ip1->i_mount;
> >  	unsigned int			rs = 0;
> >  
> >  	xmi = kmem_cache_zalloc(xfs_exchmaps_intent_cache,
> > @@ -1006,9 +1007,12 @@ xfs_exchmaps_init_intent(
> >  	}
> >  
> >  	if (req->flags & XFS_EXCHMAPS_SET_SIZES) {
> > +		loff_t	off1 = XFS_FSB_TO_B(mp, xmi->xmi_startoff1);
> > +		loff_t	off2 = XFS_FSB_TO_B(mp, xmi->xmi_startoff2);
> > +
> >  		xmi->xmi_flags |= XFS_EXCHMAPS_SET_SIZES;
> > -		xmi->xmi_isize1 = req->ip2->i_disk_size;
> > -		xmi->xmi_isize2 = req->ip1->i_disk_size;
> > +		xmi->xmi_isize1 = off1 + (req->ip2->i_disk_size - off2);
> > +		xmi->xmi_isize2 = off2 + (req->ip1->i_disk_size - off1);
> >  	}
> 
> I think this really needs a comment to explain why the calculation
> is structured this way. I think it is trying to set the file sizes
> to the "destination offset" + "swap length from other file" because
> the ranges in each file might be different lengths, but I could be
> wrong...

That's correct.  I'll add that as a code comment.

--D

> 
> Cheers,
> 
> Dave.
> -- 
> Dave Chinner
> dgc@kernel.org
> 

  reply	other threads:[~2026-10-06 15:00 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-06  5:09 [PATCH] xfs: fix exchange-range-to-eof file size exchange Darrick J. Wong
2026-10-06  6:15 ` [PATCH] xfs: add regression test for exchangerange-to-eof reflux Darrick J. Wong
2026-10-06  7:25 ` [PATCH] xfs: fix exchange-range-to-eof file size exchange Dave Chinner
2026-10-06 15:00   ` Darrick J. Wong [this message]
2026-10-06 20:12     ` Norbert Szetei
2026-10-06 23:40       ` Darrick J. Wong
2026-10-06 20:02 ` Norbert Szetei
2026-10-06 21:47   ` Darrick J. Wong
2026-10-06 22:43     ` Darrick J. Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261006150001.GY2705364@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=cem@kernel.org \
    --cc=dgc@kernel.org \
    --cc=hch@infradead.org \
    --cc=linux-xfs@vger.kernel.org \
    --cc=norbert@doyensec.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox