[PATCH 2/2] btrfs: fix block group UAF bug with nocow

Josef Bacik
2020-07-01T20:22:26Z

While debugging a patch that I wrote I was hitting UAF 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")
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
fs/btrfs/inode.c | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index d301550b9c70..cb18b1a13dca 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1694,12 +1694,8 @@ static noinline int run_delalloc_nocow(struct inode *inode,
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;
}

@@ -1715,9 +1711,6 @@ static noinline int run_delalloc_nocow(struct inode *inode,
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;
}
--
2.24.1