linux-stable/fs/btrfs
Johannes Thumshirn 5bff4167f6 btrfs: fix memory leak in qgroup accounting
commit 26ef8493e1 upstream.

When running xfstests on the current btrfs I get the following splat from
kmemleak:

unreferenced object 0xffff88821b2404e0 (size 32):
  comm "kworker/u4:7", pid 26663, jiffies 4295283698 (age 8.776s)
  hex dump (first 32 bytes):
    01 00 00 00 00 00 00 00 10 ff fd 26 82 88 ff ff  ...........&....
    10 ff fd 26 82 88 ff ff 20 ff fd 26 82 88 ff ff  ...&.... ..&....
  backtrace:
    [<00000000f94fd43f>] ulist_alloc+0x25/0x60 [btrfs]
    [<00000000fd023d99>] btrfs_find_all_roots_safe+0x41/0x100 [btrfs]
    [<000000008f17bd32>] btrfs_find_all_roots+0x52/0x70 [btrfs]
    [<00000000b7660afb>] btrfs_qgroup_rescan_worker+0x343/0x680 [btrfs]
    [<0000000058e66778>] btrfs_work_helper+0xac/0x1e0 [btrfs]
    [<00000000f0188930>] process_one_work+0x1cf/0x350
    [<00000000af5f2f8e>] worker_thread+0x28/0x3c0
    [<00000000b55a1add>] kthread+0x109/0x120
    [<00000000f88cbd17>] ret_from_fork+0x35/0x40

This corresponds to:

  (gdb) l *(btrfs_find_all_roots_safe+0x41)
  0x8d7e1 is in btrfs_find_all_roots_safe (fs/btrfs/backref.c:1413).
  1408
  1409            tmp = ulist_alloc(GFP_NOFS);
  1410            if (!tmp)
  1411                    return -ENOMEM;
  1412            *roots = ulist_alloc(GFP_NOFS);
  1413            if (!*roots) {
  1414                    ulist_free(tmp);
  1415                    return -ENOMEM;
  1416            }
  1417

Following the lifetime of the allocated 'roots' ulist, it gets freed
again in btrfs_qgroup_account_extent().

But this does not happen if the function is called with the
'BTRFS_FS_QUOTA_ENABLED' flag cleared, then btrfs_qgroup_account_extent()
does a short leave and directly returns.

Instead of directly returning we should jump to the 'out_free' in order to
free all resources as expected.

CC: stable@vger.kernel.org # 4.14+
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
[ add comment ]
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2020-01-23 08:21:31 +01:00
..
tests btrfs: return error pointer from alloc_test_extent_buffer 2019-12-31 16:36:20 +01:00
acl.c Btrfs: setup a nofs context for memory allocation at __btrfs_set_acl 2019-03-23 20:10:00 +01:00
async-thread.c btrfs: don't prematurely free work in run_ordered_work() 2019-12-31 16:36:05 +01:00
async-thread.h
backref.c Btrfs: fix deadlock between fiemap and transaction commits 2019-08-25 10:47:54 +02:00
backref.h
btrfs_inode.h btrfs: use tagged writepage to mitigate livelock of snapshot 2019-02-12 19:47:11 +01:00
check-integrity.c btrfs: open-code bio_set_op_attrs 2018-08-06 13:12:44 +02:00
check-integrity.h
compression.c btrfs: correctly validate compression type 2019-09-16 08:22:19 +02:00
compression.h btrfs: correctly validate compression type 2019-09-16 08:22:19 +02:00
ctree.c Btrfs: fix removal logic of the tree mod log that leads to use-after-free issues 2019-12-31 16:34:44 +01:00
ctree.h Btrfs: fix missing data checksums after replaying a log tree 2019-12-31 16:34:42 +01:00
dedupe.h
delayed-inode.c btrfs: use refcount_inc_not_zero in kill_all_nodes 2019-12-17 20:34:46 +01:00
delayed-inode.h btrfs: Remove fs_info from btrfs_delete_delayed_dir_index 2018-08-06 13:13:00 +02:00
delayed-ref.c btrfs: only track ref_heads in delayed_ref_updates 2019-12-05 09:20:23 +01:00
delayed-ref.h btrfs: Remove fs_info from btrfs_add_delayed_data_ref 2018-08-06 13:12:34 +02:00
dev-replace.c btrfs: dev-replace: set result code of cancel by status of scrub 2019-12-05 09:20:21 +01:00
dev-replace.h
dir-item.c btrfs: Remove fs_info from btrfs_insert_delayed_dir_index 2018-08-06 13:13:00 +02:00
disk-io.c btrfs: don't prematurely free work in end_workqueue_fn() 2019-12-31 16:36:04 +01:00
disk-io.h btrfs: Check the first key and level for cached extent buffer 2019-05-22 07:37:42 +02:00
export.c
export.h
extent-tree.c Btrfs: fix missing data checksums after replaying a log tree 2019-12-31 16:34:42 +01:00
extent_io.c btrfs: return error pointer from alloc_test_extent_buffer 2019-12-31 16:36:20 +01:00
extent_io.h Btrfs: allow clear_extent_dirty() to receive a cached extent state record 2019-12-05 09:20:22 +01:00
extent_map.c
extent_map.h
file-item.c Btrfs: fix missing data checksums after replaying a log tree 2019-12-31 16:34:42 +01:00
file.c btrfs: simplify inode locking for RWF_NOWAIT 2020-01-17 19:47:02 +01:00
free-space-cache.c btrfs: check page->mapping when loading free space cache 2019-12-17 20:34:45 +01:00
free-space-cache.h
free-space-tree.c btrfs: Remove fs_info from btrfs_del_root 2018-08-06 13:13:00 +02:00
free-space-tree.h btrfs: Remove fs_info argument from add_to_free_space_tree 2018-05-28 18:07:36 +02:00
inode-item.c
inode-map.c btrfs: qgroup: Always free PREALLOC META reserve in btrfs_delalloc_release_extents() 2019-11-06 13:05:13 +01:00
inode-map.h
inode.c btrfs: fix invalid removal of root ref 2020-01-23 08:21:31 +01:00
ioctl.c btrfs: abort transaction after failed inode updates in create_subvol 2019-12-31 16:34:43 +01:00
Kconfig
locking.c btrfs: replace waitqueue_actvie with cond_wake_up 2018-05-28 18:23:09 +02:00
locking.h
lzo.c btrfs: lzo: Harden inline lzo compressed extent decompression 2018-05-30 16:46:43 +02:00
Makefile
math.h
ordered-data.c btrfs: prune unused includes 2018-08-06 13:12:43 +02:00
ordered-data.h btrfs: remove remaing full_sync logic from btrfs_sync_file 2018-08-06 13:12:31 +02:00
orphan.c
print-tree.c btrfs: annotate unlikely branches after V0 extent type removal 2018-08-06 13:12:41 +02:00
print-tree.h
props.c btrfs: correctly validate compression type 2019-09-16 08:22:19 +02:00
props.h
qgroup.c btrfs: fix memory leak in qgroup accounting 2020-01-23 08:21:31 +01:00
qgroup.h btrfs: qgroup: Avoid calling qgroup functions if qgroup is not enabled 2018-11-13 11:08:56 -08:00
raid56.c btrfs: raid56: properly unmap parity page in finish_parity_scrub() 2019-04-03 06:26:21 +02:00
raid56.h
rcu-string.h
reada.c btrfs: don't prematurely free work in reada_start_machine_worker() 2019-12-31 16:36:16 +01:00
ref-verify.c btrfs: fix uninitialized ret in ref-verify 2019-10-17 13:45:27 -07:00
ref-verify.h
relocation.c btrfs: do not leak reloc root if we fail to read the fs root 2019-12-31 16:34:43 +01:00
root-tree.c btrfs: do not delete mismatched root refs 2020-01-23 08:21:31 +01:00
scrub.c btrfs: don't prematurely free work in scrub_missing_raid56_worker() 2019-12-31 16:36:16 +01:00
send.c btrfs: send: remove WARN_ON for readonly mount 2019-12-31 16:34:42 +01:00
send.h
struct-funcs.c btrfs: prune unused includes 2018-08-06 13:12:43 +02:00
super.c btrfs: avoid link error with CONFIG_NO_AUTO_INLINE 2019-12-01 09:17:19 +01:00
sysfs.c btrfs: sysfs: don't leak memory when failing add fsid 2019-05-31 06:46:02 -07:00
sysfs.h btrfs: sysfs: Use enum/define value for feature array definitions 2018-05-28 18:23:39 +02:00
transaction.c Btrfs: fix deadlock between fiemap and transaction commits 2019-08-25 10:47:54 +02:00
transaction.h Btrfs: fix deadlock between fiemap and transaction commits 2019-08-25 10:47:54 +02:00
tree-checker.c btrfs: tree-checker: Don't check max block group size as current max chunk size limit is unreliable 2018-12-08 12:59:10 +01:00
tree-checker.h
tree-defrag.c
tree-log.c btrfs: skip log replay on orphaned roots 2019-12-31 16:34:43 +01:00
tree-log.h Btrfs: sync log after logging new name 2018-08-23 17:37:26 +02:00
ulist.c
ulist.h
uuid-tree.c btrfs: handle ENOENT in btrfs_uuid_tree_iterate 2019-12-31 16:34:44 +01:00
volumes.c btrfs: fix ncopies raid_attr for RAID56 2019-12-05 09:20:21 +01:00
volumes.h btrfs: Remove btrfs_bio::flags member 2019-12-17 20:34:48 +01:00
xattr.c Btrfs: use nofs context when initializing security xattrs to avoid deadlock 2019-01-16 22:04:37 +01:00
xattr.h
zlib.c
zstd.c