Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2979348imu; Mon, 19 Nov 2018 08:55:22 -0800 (PST) X-Google-Smtp-Source: AJdET5diNvifxeRUqG/rHHd9x4ea6PflShN7WJbp5GSPpa8qpA5KO7ZTdi/hDKlLY/bbyU6WmJZD X-Received: by 2002:a63:d904:: with SMTP id r4mr20824047pgg.207.1542646522834; Mon, 19 Nov 2018 08:55:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542646522; cv=none; d=google.com; s=arc-20160816; b=VnswtW9SQoabeZuzv0Vq9Qzb1MTCnZVkF5xFsxb6DWKLilB6IFXY82hYvWNmZ/B6yl oLLMVUus+C1gzARaC7ziwd/O5YT9T9+o31t9hsYIi8zLlLJdHrZimwvx+xY26RRN2Scz qFeFsIbAfxyXVHFDiLVRFIbTXoYT3jA62ckgo0Gt3Ji5CLpEHYs3S9F/jK/ErMSoIhLb /E4kICuFl3DBUpTbXJNAAs/7X0H1tfZP+jhENXoBtA0hhTRA/dXwaGJsRRdNJY8G3tA3 bKs6PtIKY5BCert7ckqZdzDsQe+fupeKGoa2aLqTWEKw6b3q2YXHTHTzC4Iam/bJt6vQ AfFw== 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=iHUTi8XKb7MDGdiF4See5Fgmd6MXGwTN/KzfqdBT+WU=; b=oRE+KMoQeTkB1uQ88LiuuayaUTaklkbJbvYdGZZm3RI3wKHd1/14gvFk4oBU6UWk8t ZgFodhMOFO4BX+YJxl/jP5QpaH5EtEI99yufD8GxaHc+TGbZ30jSJWXXuN6jdUppIc6E Fi3ft4NkiuWByDD91iN1ZWhIR4DeMhsA6kvQUUFWKjoozZ6s6OCUXDWQE5qmNrWukyfA G9lQfz/bPp3Q1t0m1wRtlTD5VcT138cXdyCOrdRfqSXHIpAChOZ5BMX/+1Eu7hWkRpbI RVsaD7WIjxPd181LgRyRy5MzR2ZDeLjwBhBX5tuKyDzYfa9VU9HH1KZDSCEgV9F66WxA Lz8Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=cLLyzca+; 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 r12si40068271pgf.22.2018.11.19.08.55.07; Mon, 19 Nov 2018 08:55:22 -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=cLLyzca+; 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 S2403944AbeKTDSl (ORCPT + 99 others); Mon, 19 Nov 2018 22:18:41 -0500 Received: from mail.kernel.org ([198.145.29.99]:57596 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390256AbeKTDSi (ORCPT ); Mon, 19 Nov 2018 22:18:38 -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 7E1962145D; Mon, 19 Nov 2018 16:54:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1542646464; bh=JZyWaoa2scCtGszudxOCPpIKPPI06Arci6tUySQQwEI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cLLyzca+kT9yUaN3yOvYwhZPSpd1gvwrafigEeDp0s+W5BFzYMcpvpSHM0q+dQB/n Pq5PAnFpAKHpEJNj+KkBK6GczpcUA3F5wxf6aZ+VQFX5LQv9ZeG4NG7Iqedc3erstP T+BMJPZM5NMKpX82vu7n009AULhExarH2wPHBblM= 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.9 51/83] Btrfs: fix data corruption due to cloning of eof block Date: Mon, 19 Nov 2018 17:29:17 +0100 Message-Id: <20181119162622.575776362@linuxfoundation.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181119162612.046511542@linuxfoundation.org> References: <20181119162612.046511542@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.9-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 @@ -3911,9 +3911,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;