Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2988847imu; Mon, 19 Nov 2018 09:02:58 -0800 (PST) X-Google-Smtp-Source: AJdET5cIJk7YwA1jXHtCUdIn92dFixisqx8X/kkTajegyLjecMCCE4cG8H7a8No/igtZ0LVOnR5V X-Received: by 2002:a62:29c4:: with SMTP id p187-v6mr23642323pfp.62.1542646978911; Mon, 19 Nov 2018 09:02:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542646978; cv=none; d=google.com; s=arc-20160816; b=aX7lMU6YvvlWJQYOtaVn9cgJNZZwj+322gHHBVtotEFA+xV98oJAAFH92q02X53fl/ ACB/9GTvmHck3JveXMVONKvFPZsw9z/yoHWX1T3XCHzXLQpeAk8+OgICoeIzl8koVkBY wvQ7jMOVT3zI26zaWtPDkFT8ycDgVqI8KqSH/+kZMzN2Na6pzgFEpjOjKtQbwfNRUpUd 3ON5ukPAzzPapeJHBKfJmeqf+EVyA18xCU+BqQunZ1XP5GSCul6DNar/5VCuV6+PSUSV t01XNoVECR1QiIn2YOCxQfy6GtcYRw3QRkKVX+/uRKugT2D0D8BhJdkpne4hbCAgBHCp B20w== 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=bInYONCxWE2xmkBVdrCbMpIV5edaU5xOvYHKn0XFggY=; b=qQohPDJJNMFDi970agXhfztQzzyqFa6xngkLy24H16B0CMQf5RdP0Gx/01wiCX47xV dYtoREkdysSmCLjtNsuXjVKFGzgKlSNM8cD+QUForn312ECOMD1t/a1z8ujAk0m8qux0 FONH03zNMD3FBgCQwv5U8J7CBkh+ILnl6uVmtnrgLF5WDAqlqfRMPZoNneon6tSw6ie+ y/GJypuOxS1fB3WG0FYL2szxJHVmON9D7UY4Dfd+vB4X5/gQ6izYdiZbG89gR0tcCtQp iGX9Ec4Jr0tB5MkG0GyN8Qckqizyy+SIvFlWSpGGtRkhUSTwfDm5VMwkWgMJ9FpuJn/u Zrzg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=CnVdFAK5; 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 k19-v6si40495331pls.211.2018.11.19.09.02.36; Mon, 19 Nov 2018 09:02:58 -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=CnVdFAK5; 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 S2405752AbeKTD0E (ORCPT + 99 others); Mon, 19 Nov 2018 22:26:04 -0500 Received: from mail.kernel.org ([198.145.29.99]:39454 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2404876AbeKTD0D (ORCPT ); Mon, 19 Nov 2018 22:26:03 -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 F16A3223D8; Mon, 19 Nov 2018 17:01:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1542646906; bh=muhf99+GR5ZkHE2gV50qzg1cEVJh0tW3JgApA+td0sk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CnVdFAK5DuSL4OkDssMWttjBzGFwxOVvphipvEZ/FwYRbmEoGmENZPxPppwpuHmdc VsMRRULmBGv6ZHi8o6W627D5wKHXQ3v1NgRMkV3qS7eEjDa//6AyifSXxm+ifuJWo2 rYDjz+Utk5bWQ4WYXRexpFUDdsH7Es1Znn+siEs0= 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.4 135/160] Btrfs: fix data corruption due to cloning of eof block Date: Mon, 19 Nov 2018 17:29:34 +0100 Message-Id: <20181119162643.264100287@linuxfoundation.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181119162630.031306128@linuxfoundation.org> References: <20181119162630.031306128@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.4-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 @@ -3950,9 +3950,17 @@ static noinline long btrfs_ioctl_clone(s 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;