aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWenwen Wang <wenwen@cs.uga.edu>2020-02-01 20:38:38 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-02-19 19:53:00 +0100
commitf3cdf024ed196ecf54cb22aeadabbc329fccd27e (patch)
tree06eff24966f5b55e5ebf4977548f2a9d21468a06
parentbf4a9715a914d29f1e15e76cd1f4866f75972ce2 (diff)
downloadlinux-yocto-f3cdf024ed196ecf54cb22aeadabbc329fccd27e.tar.gz
linux-yocto-f3cdf024ed196ecf54cb22aeadabbc329fccd27e.tar.bz2
linux-yocto-f3cdf024ed196ecf54cb22aeadabbc329fccd27e.zip
btrfs: ref-verify: fix memory leaks
commit f311ade3a7adf31658ed882aaab9f9879fdccef7 upstream. In btrfs_ref_tree_mod(), 'ref' and 'ra' are allocated through kzalloc() and kmalloc(), respectively. In the following code, if an error occurs, the execution will be redirected to 'out' or 'out_unlock' and the function will be exited. However, on some of the paths, 'ref' and 'ra' are not deallocated, leading to memory leaks. For example, if 'action' is BTRFS_ADD_DELAYED_EXTENT, add_block_entry() will be invoked. If the return value indicates an error, the execution will be redirected to 'out'. But, 'ref' is not deallocated on this path, causing a memory leak. To fix the above issues, deallocate both 'ref' and 'ra' before exiting from the function when an error is encountered. CC: stable@vger.kernel.org # 4.15+ Signed-off-by: Wenwen Wang <wenwen@cs.uga.edu> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/btrfs/ref-verify.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/fs/btrfs/ref-verify.c b/fs/btrfs/ref-verify.c
index b57f3618e58e..454a1015d026 100644
--- a/fs/btrfs/ref-verify.c
+++ b/fs/btrfs/ref-verify.c
@@ -744,6 +744,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
*/
be = add_block_entry(fs_info, bytenr, num_bytes, ref_root);
if (IS_ERR(be)) {
+ kfree(ref);
kfree(ra);
ret = PTR_ERR(be);
goto out;
@@ -757,6 +758,8 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
"re-allocated a block that still has references to it!");
dump_block_entry(fs_info, be);
dump_ref_action(fs_info, ra);
+ kfree(ref);
+ kfree(ra);
goto out_unlock;
}
@@ -819,6 +822,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
"dropping a ref for a existing root that doesn't have a ref on the block");
dump_block_entry(fs_info, be);
dump_ref_action(fs_info, ra);
+ kfree(ref);
kfree(ra);
goto out_unlock;
}
@@ -834,6 +838,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
"attempting to add another ref for an existing ref on a tree block");
dump_block_entry(fs_info, be);
dump_ref_action(fs_info, ra);
+ kfree(ref);
kfree(ra);
goto out_unlock;
}