Btrfs: fix clone vs chattr NODATASUM race
authorOmar Sandoval <osandov@fb.com>
Tue, 22 May 2018 22:02:12 +0000 (15:02 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 25 Jun 2018 23:53:57 +0000 (07:53 +0800)
commitd0cdc600b9fe753dac92ffe4f7ccb6f21eacf57c
treeb8a59c638c8e76d51a5d7712253c852fa929955f
parent020db42c835c0cf31118bfbe30c824f30d2c1a91
Btrfs: fix clone vs chattr NODATASUM race

commit b5c40d598f5408bd0ca22dfffa82f03cd9433f23 upstream.

In btrfs_clone_files(), we must check the NODATASUM flag while the
inodes are locked. Otherwise, it's possible that btrfs_ioctl_setflags()
will change the flags after we check and we can end up with a party
checksummed file.

The race window is only a few instructions in size, between the if and
the locks which is:

3834         if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))
3835                 return -EISDIR;

where the setflags must be run and toggle the NODATASUM flag (provided
the file size is 0).  The clone will block on the inode lock, segflags
takes the inode lock, changes flags, releases log and clone continues.

Not impossible but still needs a lot of bad luck to hit unintentionally.

Fixes: 0e7b824c4ef9 ("Btrfs: don't make a file partly checksummed through file clone")
CC: stable@vger.kernel.org # 4.4+
Signed-off-by: Omar Sandoval <osandov@fb.com>
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
[ update changelog ]
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/btrfs/ioctl.c