Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2974169imu; Mon, 19 Nov 2018 08:50:51 -0800 (PST) X-Google-Smtp-Source: AJdET5dY1EKeykCbgBAIhuuroviwOKOBWXC6Xl7YLAT8hvZ0riNjJCJ1wpo5bdvI+PunNxNiYYp0 X-Received: by 2002:a63:3f44:: with SMTP id m65mr21318916pga.115.1542646251283; Mon, 19 Nov 2018 08:50:51 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542646251; cv=none; d=google.com; s=arc-20160816; b=tFjTtLLJXiyRYV34+9XUALrdmpul0n1K4cVvHrTabzAyBJ6TiPwMa4L+bMbJUdGfCX rZnQ0ogf++G9KfAQqnnEVRoQm+Y5it1Tn+iUstLxty/O5jEKir/k+MbJ5Y+anMbywgMO +J8yzdk6C4wDmyrOvhTAKVZVSZM0iwLW5ccTQHC9ygG5xCThPYFf8K21vKdYgOqhX0xK Jtx/pGmzjZW5XAeTN4a0BKWdtjg7xWnfujMO8+rjImmjP7TagRfK+eLup3tJBJXeGGHZ 6j+ZMJTxdvZiZP0P38dsGG6erZHsaGnPjlku4yxhVXa+BkXiDNshwIMjFJ+zPDNaYbMn kMSw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=HkZqihgMn2cTkdZ9O9UEpkWs1CX83Z4XJ1LujguKrIk=; b=Sr+uEaryJind3gXuwm8Stxh0t5KkVwpUGk3wideOXMU7TPJIOHPS7bAWIpxgAkh1rD ro7F/ArABzBYCp9heefJ1wpCBchRWjTpmkkGjx+kWKlEAOUhGukcqQp+2n3r2XqRigjL 8zYb1cO2HCGhjblNDELhW5QapRnT+1ZcOuXKzzP0tQXB4tuDlA/YiNBgsQhDxHbLx5yN +4BDvCSfiLVELuJ3O57+bUCdrAkYxeANVy6dZzyZElTYPXlbNPSAaO9jyA0B6BsnsOEg uzd4FtS5ruBxkea4JeZlpjLIBQOxR6T7sj4zLNbDq2D5FrEtadw2Yf6Pfcid5dXhd1ia 1/Og== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=frPEyZIH; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u10si25377558plr.439.2018.11.19.08.50.36; Mon, 19 Nov 2018 08:50:51 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=frPEyZIH; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389876AbeKTDOH (ORCPT + 99 others); Mon, 19 Nov 2018 22:14:07 -0500 Received: from mail.kernel.org ([198.145.29.99]:51282 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388976AbeKTDOG (ORCPT ); Mon, 19 Nov 2018 22:14:06 -0500 Received: from localhost (5356596B.cm-6-7b.dynamic.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 41042208E3; Mon, 19 Nov 2018 16:49:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1542646193; bh=kfeWNCP1BnrYJvrCm1kH6+IY03YeXtNQvBWu4KNR3Fs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=frPEyZIHURoWpNWInF983sSdYgMyGvmty3HDCNQF4WEjPCvbSRbnEKzNtv6m8/ord bYUODjSpTbztvfRc9gjT2l9wOA57eVs82yos+KqfYM7ncdp5dUiLtpObdHy/FDWsla WLhg1ur5YHL7Dw9eQnRsMzSRiaLieA9DTxqri+Qk= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Filipe Manana , David Sterba Subject: [PATCH 4.14 071/124] Btrfs: fix data corruption due to cloning of eof block Date: Mon, 19 Nov 2018 17:28:45 +0100 Message-Id: <20181119162626.953616726@linuxfoundation.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181119162612.951907286@linuxfoundation.org> References: <20181119162612.951907286@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Filipe Manana commit ac765f83f1397646c11092a032d4f62c3d478b81 upstream. We currently allow cloning a range from a file which includes the last block of the file even if the file's size is not aligned to the block size. This is fine and useful when the destination file has the same size, but when it does not and the range ends somewhere in the middle of the destination file, it leads to corruption because the bytes between the EOF and the end of the block have undefined data (when there is support for discard/trimming they have a value of 0x00). Example: $ mkfs.btrfs -f /dev/sdb $ mount /dev/sdb /mnt $ export foo_size=$((256 * 1024 + 100)) $ xfs_io -f -c "pwrite -S 0x3c 0 $foo_size" /mnt/foo $ xfs_io -f -c "pwrite -S 0xb5 0 1M" /mnt/bar $ xfs_io -c "reflink /mnt/foo 0 512K $foo_size" /mnt/bar $ od -A d -t x1 /mnt/bar 0000000 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 * 0524288 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c 3c * 0786528 3c 3c 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 0786544 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 0790528 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 b5 * 1048576 The bytes in the range from 786532 (512Kb + 256Kb + 100 bytes) to 790527 (512Kb + 256Kb + 4Kb - 1) got corrupted, having now a value of 0x00 instead of 0xb5. This is similar to the problem we had for deduplication that got recently fixed by commit de02b9f6bb65 ("Btrfs: fix data corruption when deduplicating between different files"). Fix this by not allowing such operations to be performed and return the errno -EINVAL to user space. This is what XFS is doing as well at the VFS level. This change however now makes us return -EINVAL instead of -EOPNOTSUPP for cases where the source range maps to an inline extent and the destination range's end is smaller then the destination file's size, since the detection of inline extents is done during the actual process of dropping file extent items (at __btrfs_drop_extents()). Returning the -EINVAL error is done early on and solely based on the input parameters (offsets and length) and destination file's size. This makes us consistent with XFS and anyone else supporting cloning since this case is now checked at a higher level in the VFS and is where the -EINVAL will be returned from starting with kernel 4.20 (the VFS changed was introduced in 4.20-rc1 by commit 07d19dc9fbe9 ("vfs: avoid problematic remapping requests into partial EOF block"). So this change is more geared towards stable kernels, as it's unlikely the new VFS checks get removed intentionally. A test case for fstests follows soon, as well as an update to filter existing tests that expect -EOPNOTSUPP to accept -EINVAL as well. CC: # 4.4+ Signed-off-by: Filipe Manana Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/ioctl.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -3909,9 +3909,17 @@ static noinline int btrfs_clone_files(st goto out_unlock; if (len == 0) olen = len = src->i_size - off; - /* if we extend to eof, continue to block boundary */ - if (off + len == src->i_size) + /* + * If we extend to eof, continue to block boundary if and only if the + * destination end offset matches the destination file's size, otherwise + * we would be corrupting data by placing the eof block into the middle + * of a file. + */ + if (off + len == src->i_size) { + if (!IS_ALIGNED(len, bs) && destoff + len < inode->i_size) + goto out_unlock; len = ALIGN(src->i_size, bs) - off; + } if (len == 0) { ret = 0;