| From 230ed397435e85b54f055c524fcb267ae2ce3bc4 Mon Sep 17 00:00:00 2001 |
| From: Josef Bacik <josef@toxicpanda.com> |
| Date: Mon, 6 Jul 2020 09:14:12 -0400 |
| Subject: btrfs: fix double put of block group with nocow |
| |
| From: Josef Bacik <josef@toxicpanda.com> |
| |
| commit 230ed397435e85b54f055c524fcb267ae2ce3bc4 upstream. |
| |
| While debugging a patch that I wrote I was hitting use-after-free panics |
| when accessing block groups on unmount. This turned out to be because |
| in the nocow case if we bail out of doing the nocow for whatever reason |
| we need to call btrfs_dec_nocow_writers() if we called the inc. This |
| puts our block group, but a few error cases does |
| |
| if (nocow) { |
| btrfs_dec_nocow_writers(); |
| goto error; |
| } |
| |
| unfortunately, error is |
| |
| error: |
| if (nocow) |
| btrfs_dec_nocow_writers(); |
| |
| so we get a double put on our block group. Fix this by dropping the |
| error cases calling of btrfs_dec_nocow_writers(), as it's handled at the |
| error label now. |
| |
| Fixes: 762bf09893b4 ("btrfs: improve error handling in run_delalloc_nocow") |
| CC: stable@vger.kernel.org # 5.4+ |
| Reviewed-by: Filipe Manana <fdmanana@suse.com> |
| Signed-off-by: Josef Bacik <josef@toxicpanda.com> |
| Reviewed-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/btrfs/inode.c | 9 +-------- |
| 1 file changed, 1 insertion(+), 8 deletions(-) |
| |
| --- a/fs/btrfs/inode.c |
| +++ b/fs/btrfs/inode.c |
| @@ -1657,12 +1657,8 @@ out_check: |
| ret = fallback_to_cow(inode, locked_page, cow_start, |
| found_key.offset - 1, |
| page_started, nr_written); |
| - if (ret) { |
| - if (nocow) |
| - btrfs_dec_nocow_writers(fs_info, |
| - disk_bytenr); |
| + if (ret) |
| goto error; |
| - } |
| cow_start = (u64)-1; |
| } |
| |
| @@ -1678,9 +1674,6 @@ out_check: |
| ram_bytes, BTRFS_COMPRESS_NONE, |
| BTRFS_ORDERED_PREALLOC); |
| if (IS_ERR(em)) { |
| - if (nocow) |
| - btrfs_dec_nocow_writers(fs_info, |
| - disk_bytenr); |
| ret = PTR_ERR(em); |
| goto error; |
| } |