All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Btrfs: fix partly checksummed file races
@ 2018-05-22 22:02 Omar Sandoval
  2018-05-22 22:02 ` [PATCH 1/2] Btrfs: fix clone vs chattr NODATASUM race Omar Sandoval
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Omar Sandoval @ 2018-05-22 22:02 UTC (permalink / raw)
  To: linux-btrfs; +Cc: kernel-team, David Sterba, Timofey Titovets

From: Omar Sandoval <osandov@fb.com>

Clone and dedupe both have checks to make sure that we're not mixing
checksummed and not checksummed extents in a single file. However, both
checks are racy; we need to have the inodes locked or else the flags can
change after we check. The clone check has always been wrong. The dedupe
check was previously correct but is broken in kdave/for-next.

Based on kdave/for-next. Note that there's a Fixes: tag in there
referencing a commit in the for-next branch, so that would have to be
updated if the commit gets rebased. These patches are also available at
https://github.com/osandov/linux/tree/btrfs-nodatasum-race.

Thanks!

Omar Sandoval (2):
  Btrfs: fix clone vs chattr NODATASUM race
  Btrfs: fix dedupe vs chattr NODATASUM race

 fs/btrfs/ioctl.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

-- 
2.17.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/2] Btrfs: fix clone vs chattr NODATASUM race
  2018-05-22 22:02 [PATCH 0/2] Btrfs: fix partly checksummed file races Omar Sandoval
@ 2018-05-22 22:02 ` Omar Sandoval
  2018-05-23  6:07   ` Nikolay Borisov
  2018-05-23 18:22   ` David Sterba
  2018-05-22 22:02 ` [PATCH 2/2] Btrfs: fix dedupe " Omar Sandoval
  2018-05-23 10:17 ` [PATCH 0/2] Btrfs: fix partly checksummed file races David Sterba
  2 siblings, 2 replies; 9+ messages in thread
From: Omar Sandoval @ 2018-05-22 22:02 UTC (permalink / raw)
  To: linux-btrfs; +Cc: kernel-team, David Sterba, Timofey Titovets

From: Omar Sandoval <osandov@fb.com>

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.

Fixes: 0e7b824c4ef9 ("Btrfs: don't make a file partly checksummed through file clone")
Signed-off-by: Omar Sandoval <osandov@fb.com>
---
 fs/btrfs/ioctl.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index cf0d3bc6f625..784e267aad32 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -4280,11 +4280,6 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
 	    src->i_sb != inode->i_sb)
 		return -EXDEV;
 
-	/* don't make the dst file partly checksummed */
-	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
-	    (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM))
-		return -EINVAL;
-
 	if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))
 		return -EISDIR;
 
@@ -4294,6 +4289,13 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
 		inode_lock(src);
 	}
 
+	/* don't make the dst file partly checksummed */
+	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
+	    (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
 	/* determine range to clone */
 	ret = -EINVAL;
 	if (off + len > src->i_size || off + len < off)
-- 
2.17.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/2] Btrfs: fix dedupe vs chattr NODATASUM race
  2018-05-22 22:02 [PATCH 0/2] Btrfs: fix partly checksummed file races Omar Sandoval
  2018-05-22 22:02 ` [PATCH 1/2] Btrfs: fix clone vs chattr NODATASUM race Omar Sandoval
@ 2018-05-22 22:02 ` Omar Sandoval
  2018-05-23  6:10   ` Nikolay Borisov
  2018-05-23 10:17 ` [PATCH 0/2] Btrfs: fix partly checksummed file races David Sterba
  2 siblings, 1 reply; 9+ messages in thread
From: Omar Sandoval @ 2018-05-22 22:02 UTC (permalink / raw)
  To: linux-btrfs; +Cc: kernel-team, David Sterba, Timofey Titovets

From: Omar Sandoval <osandov@fb.com>

In btrfs_extent_same(), 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. This was correct until a recent
change.

Fixes: 0a38effca37c ("Btrfs: split btrfs_extent_same")
Signed-off-by: Omar Sandoval <osandov@fb.com>
---
 fs/btrfs/ioctl.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 784e267aad32..c2263bf4d6f5 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3586,12 +3586,6 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,
 	if (olen == 0)
 		return 0;
 
-	/* don't make the dst file partly checksummed */
-	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
-	    (BTRFS_I(dst)->flags & BTRFS_INODE_NODATASUM)) {
-		return -EINVAL;
-	}
-
 	tail_len = olen % BTRFS_MAX_DEDUPE_LEN;
 	chunk_count = div_u64(olen, BTRFS_MAX_DEDUPE_LEN);
 	if (chunk_count == 0)
@@ -3624,6 +3618,13 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,
 	else
 		btrfs_double_inode_lock(src, dst);
 
+	/* don't make the dst file partly checksummed */
+	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
+	    (BTRFS_I(dst)->flags & BTRFS_INODE_NODATASUM)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	for (i = 0; i < chunk_count; i++) {
 		ret = btrfs_extent_same_range(src, loff, BTRFS_MAX_DEDUPE_LEN,
 					      dst, dst_loff, &cmp);
-- 
2.17.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] Btrfs: fix clone vs chattr NODATASUM race
  2018-05-22 22:02 ` [PATCH 1/2] Btrfs: fix clone vs chattr NODATASUM race Omar Sandoval
@ 2018-05-23  6:07   ` Nikolay Borisov
  2018-05-23 18:22   ` David Sterba
  1 sibling, 0 replies; 9+ messages in thread
From: Nikolay Borisov @ 2018-05-23  6:07 UTC (permalink / raw)
  To: Omar Sandoval, linux-btrfs; +Cc: kernel-team, David Sterba, Timofey Titovets



On 23.05.2018 01:02, Omar Sandoval wrote:
> From: Omar Sandoval <osandov@fb.com>
> 
> 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.
> 
> Fixes: 0e7b824c4ef9 ("Btrfs: don't make a file partly checksummed through file clone")
> Signed-off-by: Omar Sandoval <osandov@fb.com>

Reviewed-by: Nikolay Borisov <nborisov@suse.com>
> ---
>  fs/btrfs/ioctl.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index cf0d3bc6f625..784e267aad32 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -4280,11 +4280,6 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
>  	    src->i_sb != inode->i_sb)
>  		return -EXDEV;
>  
> -	/* don't make the dst file partly checksummed */
> -	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
> -	    (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM))
> -		return -EINVAL;
> -
>  	if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))
>  		return -EISDIR;
>  
> @@ -4294,6 +4289,13 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
>  		inode_lock(src);
>  	}
>  
> +	/* don't make the dst file partly checksummed */
> +	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
> +	    (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
> +		ret = -EINVAL;
> +		goto out_unlock;
> +	}
> +
>  	/* determine range to clone */
>  	ret = -EINVAL;
>  	if (off + len > src->i_size || off + len < off)
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/2] Btrfs: fix dedupe vs chattr NODATASUM race
  2018-05-22 22:02 ` [PATCH 2/2] Btrfs: fix dedupe " Omar Sandoval
@ 2018-05-23  6:10   ` Nikolay Borisov
  0 siblings, 0 replies; 9+ messages in thread
From: Nikolay Borisov @ 2018-05-23  6:10 UTC (permalink / raw)
  To: Omar Sandoval, linux-btrfs; +Cc: kernel-team, David Sterba, Timofey Titovets



On 23.05.2018 01:02, Omar Sandoval wrote:
> From: Omar Sandoval <osandov@fb.com>
> 
> In btrfs_extent_same(), 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. This was correct until a recent
> change.
> 
> Fixes: 0a38effca37c ("Btrfs: split btrfs_extent_same")
> Signed-off-by: Omar Sandoval <osandov@fb.com>

Reviewed-by: Nikolay Borisov <nborisov@suse.com>

> ---
>  fs/btrfs/ioctl.c | 13 +++++++------
>  1 file changed, 7 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 784e267aad32..c2263bf4d6f5 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -3586,12 +3586,6 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,
>  	if (olen == 0)
>  		return 0;
>  
> -	/* don't make the dst file partly checksummed */
> -	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
> -	    (BTRFS_I(dst)->flags & BTRFS_INODE_NODATASUM)) {
> -		return -EINVAL;
> -	}
> -
>  	tail_len = olen % BTRFS_MAX_DEDUPE_LEN;
>  	chunk_count = div_u64(olen, BTRFS_MAX_DEDUPE_LEN);
>  	if (chunk_count == 0)
> @@ -3624,6 +3618,13 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,
>  	else
>  		btrfs_double_inode_lock(src, dst);
>  
> +	/* don't make the dst file partly checksummed */
> +	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
> +	    (BTRFS_I(dst)->flags & BTRFS_INODE_NODATASUM)) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
>  	for (i = 0; i < chunk_count; i++) {
>  		ret = btrfs_extent_same_range(src, loff, BTRFS_MAX_DEDUPE_LEN,
>  					      dst, dst_loff, &cmp);
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/2] Btrfs: fix partly checksummed file races
  2018-05-22 22:02 [PATCH 0/2] Btrfs: fix partly checksummed file races Omar Sandoval
  2018-05-22 22:02 ` [PATCH 1/2] Btrfs: fix clone vs chattr NODATASUM race Omar Sandoval
  2018-05-22 22:02 ` [PATCH 2/2] Btrfs: fix dedupe " Omar Sandoval
@ 2018-05-23 10:17 ` David Sterba
  2018-05-23 17:14   ` Omar Sandoval
  2 siblings, 1 reply; 9+ messages in thread
From: David Sterba @ 2018-05-23 10:17 UTC (permalink / raw)
  To: Omar Sandoval; +Cc: linux-btrfs, kernel-team, David Sterba, Timofey Titovets

On Tue, May 22, 2018 at 03:02:11PM -0700, Omar Sandoval wrote:
> Based on kdave/for-next. Note that there's a Fixes: tag in there
> referencing a commit in the for-next branch, so that would have to be
> updated if the commit gets rebased. These patches are also available at
> https://github.com/osandov/linux/tree/btrfs-nodatasum-race.

If the original patch is not in any released or frozen branch, then the
fix should be folded to the original patch. The for-next branch is for
preview, testing and catching bugs that slip past the review. And gets
reassembled frequently so referencing a patch from there does not make
sense.

Sending the fixups as patches is ok, replies to the original thread
might get lost in the noise.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/2] Btrfs: fix partly checksummed file races
  2018-05-23 10:17 ` [PATCH 0/2] Btrfs: fix partly checksummed file races David Sterba
@ 2018-05-23 17:14   ` Omar Sandoval
  2018-05-23 18:03     ` David Sterba
  0 siblings, 1 reply; 9+ messages in thread
From: Omar Sandoval @ 2018-05-23 17:14 UTC (permalink / raw)
  To: David Sterba; +Cc: linux-btrfs, kernel-team, David Sterba, Timofey Titovets

On Wed, May 23, 2018 at 12:17:14PM +0200, David Sterba wrote:
> On Tue, May 22, 2018 at 03:02:11PM -0700, Omar Sandoval wrote:
> > Based on kdave/for-next. Note that there's a Fixes: tag in there
> > referencing a commit in the for-next branch, so that would have to be
> > updated if the commit gets rebased. These patches are also available at
> > https://github.com/osandov/linux/tree/btrfs-nodatasum-race.
> 
> If the original patch is not in any released or frozen branch, then the
> fix should be folded to the original patch. The for-next branch is for
> preview, testing and catching bugs that slip past the review. And gets
> reassembled frequently so referencing a patch from there does not make
> sense.
> 
> Sending the fixups as patches is ok, replies to the original thread
> might get lost in the noise.

Ok, let's fold it in. I pushed Timofey's series with the fix folded in
here: https://github.com/osandov/linux/tree/btrfs-ioctl-fixes, based on
misc-next with Timofey's patches removed. The diff vs his original
patches is the same as my patch:

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 65d709002775..75c66ac77fd7 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3113,12 +3113,6 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,
 	if (olen == 0)
 		return 0;
 
-	/* don't make the dst file partly checksummed */
-	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
-	    (BTRFS_I(dst)->flags & BTRFS_INODE_NODATASUM)) {
-		return -EINVAL;
-	}
-
 	tail_len = olen % BTRFS_MAX_DEDUPE_LEN;
 	chunk_count = div_u64(olen, BTRFS_MAX_DEDUPE_LEN);
 	if (chunk_count == 0)
@@ -3151,6 +3145,13 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,
 	else
 		btrfs_double_inode_lock(src, dst);
 
+	/* don't make the dst file partly checksummed */
+	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
+	    (BTRFS_I(dst)->flags & BTRFS_INODE_NODATASUM)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	for (i = 0; i < chunk_count; i++) {
 		ret = btrfs_extent_same_range(src, loff, BTRFS_MAX_DEDUPE_LEN,
 					      dst, dst_loff, &cmp);

The clone fix and device remove fix are in that branch, too. Let me know
if you'd prefer it as patches.

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/2] Btrfs: fix partly checksummed file races
  2018-05-23 17:14   ` Omar Sandoval
@ 2018-05-23 18:03     ` David Sterba
  0 siblings, 0 replies; 9+ messages in thread
From: David Sterba @ 2018-05-23 18:03 UTC (permalink / raw)
  To: Omar Sandoval
  Cc: David Sterba, linux-btrfs, kernel-team, David Sterba, Timofey Titovets

On Wed, May 23, 2018 at 10:14:14AM -0700, Omar Sandoval wrote:
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c

> The clone fix and device remove fix are in that branch, too. Let me know
> if you'd prefer it as patches.

The diff like that is fine, there likely will be more conflicts with
followup patches that need to be resolved anyway. If you do that and
find something worth pointing out then it's good to be mentioned, but
otherwise I'm not asking you or other reporter to also post the resolved
version. Thanks.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/2] Btrfs: fix clone vs chattr NODATASUM race
  2018-05-22 22:02 ` [PATCH 1/2] Btrfs: fix clone vs chattr NODATASUM race Omar Sandoval
  2018-05-23  6:07   ` Nikolay Borisov
@ 2018-05-23 18:22   ` David Sterba
  1 sibling, 0 replies; 9+ messages in thread
From: David Sterba @ 2018-05-23 18:22 UTC (permalink / raw)
  To: Omar Sandoval; +Cc: linux-btrfs, kernel-team, David Sterba, Timofey Titovets

On Tue, May 22, 2018 at 03:02:12PM -0700, Omar Sandoval wrote:
> From: Omar Sandoval <osandov@fb.com>
> 
> 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 nodatacow 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.

Reviewed-by: David Sterba <dsterba@suse.com>

> Fixes: 0e7b824c4ef9 ("Btrfs: don't make a file partly checksummed through file clone")
> Signed-off-by: Omar Sandoval <osandov@fb.com>
> ---
>  fs/btrfs/ioctl.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index cf0d3bc6f625..784e267aad32 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -4280,11 +4280,6 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
>  	    src->i_sb != inode->i_sb)
>  		return -EXDEV;
>  
> -	/* don't make the dst file partly checksummed */
> -	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
> -	    (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM))
> -		return -EINVAL;
> -
>  	if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))
>  		return -EISDIR;
>  
> @@ -4294,6 +4289,13 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
>  		inode_lock(src);
>  	}
>  
> +	/* don't make the dst file partly checksummed */
> +	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
> +	    (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
> +		ret = -EINVAL;
> +		goto out_unlock;
> +	}
> +
>  	/* determine range to clone */
>  	ret = -EINVAL;
>  	if (off + len > src->i_size || off + len < off)
> -- 
> 2.17.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-05-23 18:24 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-22 22:02 [PATCH 0/2] Btrfs: fix partly checksummed file races Omar Sandoval
2018-05-22 22:02 ` [PATCH 1/2] Btrfs: fix clone vs chattr NODATASUM race Omar Sandoval
2018-05-23  6:07   ` Nikolay Borisov
2018-05-23 18:22   ` David Sterba
2018-05-22 22:02 ` [PATCH 2/2] Btrfs: fix dedupe " Omar Sandoval
2018-05-23  6:10   ` Nikolay Borisov
2018-05-23 10:17 ` [PATCH 0/2] Btrfs: fix partly checksummed file races David Sterba
2018-05-23 17:14   ` Omar Sandoval
2018-05-23 18:03     ` David Sterba

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.