• Omar Sandoval's avatar
    Btrfs: fix clone vs chattr NODATASUM race · b5c40d59
    Omar Sandoval authored
    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: 0e7b824c ("Btrfs: don't make a file partly checksummed through file clone")
    CC: stable@vger.kernel.org # 4.4+
    Signed-off-by: default avatarOmar Sandoval <osandov@fb.com>
    Reviewed-by: default avatarNikolay Borisov <nborisov@suse.com>
    Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
    [ update changelog ]
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    b5c40d59
ioctl.c 135 KB