diff mbox series

[2/2] btrfs: Use btrfs_try_lock_balance in btrfs_ioctl_balance

Message ID 20220503083637.1051023-3-nborisov@suse.com (mailing list archive)
State New, archived
Headers show
Series Refactor btrfs_ioctl_balance | expand

Commit Message

Nikolay Borisov May 3, 2022, 8:36 a.m. UTC
This eliminates 2 labels and makes the code generally more streamlined.
Also rename the 'out_bargs' label to 'out_unlock' since bargs is going
to be freed under the 'out' label. This also fixes a memory leak since
bargs wasn't correctly freed in one of the condition which are now moved
in btrfs_try_lock_balance.

Signed-off-by: Nikolay Borisov <nborisov@suse.com>
---
 fs/btrfs/ioctl.c | 52 ++++++------------------------------------------
 1 file changed, 6 insertions(+), 46 deletions(-)

Comments

Dan Carpenter May 4, 2022, 6:46 a.m. UTC | #1
Hi Nikolay,

url:    https://github.com/intel-lab-lkp/linux/commits/Nikolay-Borisov/Refactor-btrfs_ioctl_balance/20220503-163837 
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git  for-next
config: i386-randconfig-m021-20220502 (https://download.01.org/0day-ci/archive/20220504/202205041423.NVVJIHSj-lkp@intel.com/config )
compiler: gcc-11 (Debian 11.2.0-20) 11.2.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

smatch warnings:
fs/btrfs/ioctl.c:4493 btrfs_ioctl_balance() error: double free of 'bargs'

vim +/bargs +4493 fs/btrfs/ioctl.c

c9e9f97bdfb64d Ilya Dryomov         2012-01-16  4484  
0f89abf56abbd0 Christian Engelmayer 2015-10-21  4485  	kfree(bctl);
ed0fb78fb6aa29 Ilya Dryomov         2013-01-20  4486  out_unlock:
c9e9f97bdfb64d Ilya Dryomov         2012-01-16  4487  	mutex_unlock(&fs_info->balance_mutex);
ed0fb78fb6aa29 Ilya Dryomov         2013-01-20  4488  	if (need_unlock)
c3e1f96c37d0f8 Goldwyn Rodrigues    2020-08-25  4489  		btrfs_exclop_finish(fs_info);
ed0fb78fb6aa29 Ilya Dryomov         2013-01-20  4490  out:
c696e46e6ec2b3 Nikolay Borisov      2022-05-03  4491  	kfree(bargs);
                                                              ^^^^^

e54bfa31044d60 Liu Bo               2012-06-29  4492  	mnt_drop_write_file(file);
c746db1b6ed99f Nikolay Borisov      2022-03-30 @4493  	kfree(bargs);
                                                              ^^^^^

Freed twice.

c9e9f97bdfb64d Ilya Dryomov         2012-01-16  4494  	return ret;
c9e9f97bdfb64d Ilya Dryomov         2012-01-16  4495  }
Nikolay Borisov May 4, 2022, 8:44 a.m. UTC | #2
On 4.05.22 г. 9:46 ч., Dan Carpenter wrote:
> Hi Nikolay,
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Nikolay-Borisov/Refactor-btrfs_ioctl_balance/20220503-163837
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git  for-next
> config: i386-randconfig-m021-20220502 (https://download.01.org/0day-ci/archive/20220504/202205041423.NVVJIHSj-lkp@intel.com/config )
> compiler: gcc-11 (Debian 11.2.0-20) 11.2.0
> 
> If you fix the issue, kindly add following tag as appropriate
> Reported-by: kernel test robot <lkp@intel.com>
> Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> 
> smatch warnings:
> fs/btrfs/ioctl.c:4493 btrfs_ioctl_balance() error: double free of 'bargs'
> 
> vim +/bargs +4493 fs/btrfs/ioctl.c


Yep, a genuine braino, the fix is to remove either of the calls. I 
personally would go with the one before mnt_drop_write so that we drop 
the write ASAP but in the end I doubt it makes any practical difference. 
David care to fold this or shall I resend?

> 
> c9e9f97bdfb64d Ilya Dryomov         2012-01-16  4484
> 0f89abf56abbd0 Christian Engelmayer 2015-10-21  4485  	kfree(bctl);
> ed0fb78fb6aa29 Ilya Dryomov         2013-01-20  4486  out_unlock:
> c9e9f97bdfb64d Ilya Dryomov         2012-01-16  4487  	mutex_unlock(&fs_info->balance_mutex);
> ed0fb78fb6aa29 Ilya Dryomov         2013-01-20  4488  	if (need_unlock)
> c3e1f96c37d0f8 Goldwyn Rodrigues    2020-08-25  4489  		btrfs_exclop_finish(fs_info);
> ed0fb78fb6aa29 Ilya Dryomov         2013-01-20  4490  out:
> c696e46e6ec2b3 Nikolay Borisov      2022-05-03  4491  	kfree(bargs);
>                                                                ^^^^^
> 
> e54bfa31044d60 Liu Bo               2012-06-29  4492  	mnt_drop_write_file(file);
> c746db1b6ed99f Nikolay Borisov      2022-03-30 @4493  	kfree(bargs);
>                                                                ^^^^^
> 
> Freed twice.
> 
> c9e9f97bdfb64d Ilya Dryomov         2012-01-16  4494  	return ret;
> c9e9f97bdfb64d Ilya Dryomov         2012-01-16  4495  }
>
David Sterba May 4, 2022, 3:25 p.m. UTC | #3
On Wed, May 04, 2022 at 11:44:51AM +0300, Nikolay Borisov wrote:
> 
> 
> On 4.05.22 г. 9:46 ч., Dan Carpenter wrote:
> > Hi Nikolay,
> > 
> > url:    https://github.com/intel-lab-lkp/linux/commits/Nikolay-Borisov/Refactor-btrfs_ioctl_balance/20220503-163837
> > base:   https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git  for-next
> > config: i386-randconfig-m021-20220502 (https://download.01.org/0day-ci/archive/20220504/202205041423.NVVJIHSj-lkp@intel.com/config )
> > compiler: gcc-11 (Debian 11.2.0-20) 11.2.0
> > 
> > If you fix the issue, kindly add following tag as appropriate
> > Reported-by: kernel test robot <lkp@intel.com>
> > Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> > 
> > smatch warnings:
> > fs/btrfs/ioctl.c:4493 btrfs_ioctl_balance() error: double free of 'bargs'
> > 
> > vim +/bargs +4493 fs/btrfs/ioctl.c
> 
> 
> Yep, a genuine braino, the fix is to remove either of the calls. I 
> personally would go with the one before mnt_drop_write so that we drop 
> the write ASAP but in the end I doubt it makes any practical difference. 
> David care to fold this or shall I resend?

Please resend, thanks.
kernel test robot May 6, 2022, 9:04 a.m. UTC | #4
Greeting,

FYI, we noticed the following commit (built with gcc-11):

commit: c696e46e6ec2b391d6e350b4323ef7e7bafa7bca ("[PATCH 2/2] btrfs: Use btrfs_try_lock_balance in btrfs_ioctl_balance")
url: https://github.com/intel-lab-lkp/linux/commits/Nikolay-Borisov/Refactor-btrfs_ioctl_balance/20220503-163837
base: https://git.kernel.org/cgit/linux/kernel/git/kdave/linux.git for-next
patch link: https://lore.kernel.org/linux-btrfs/20220503083637.1051023-3-nborisov@suse.com

in testcase: xfstests
version: xfstests-x86_64-46e1b83-1_20220414
with following parameters:

	disk: 6HDD
	fs: btrfs
	test: btrfs-group-04
	ucode: 0x28

test-description: xfstests is a regression test suite for xfs and other files ystems.
test-url: git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git


on test machine: 8 threads 1 sockets Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz with 8G memory

caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):



If you fix the issue, kindly add following tag
Reported-by: kernel test robot <oliver.sang@intel.com>



[   72.075848][ T6752] BTRFS info (device sda2): balance: paused
[   72.081574][ T6752] ==================================================================
[   72.089422][ T6752] BUG: KASAN: double-free or invalid-free in btrfs_ioctl_balance+0x2d6/0x600 [btrfs]
[   72.098720][ T6752]
[   72.100885][ T6752] CPU: 0 PID: 6752 Comm: btrfs Not tainted 5.18.0-rc4-00382-gc696e46e6ec2 #1
[   72.109425][ T6752] Hardware name: Dell Inc. OptiPlex 9020/0DNKMN, BIOS A05 12/05/2013
[   72.117278][ T6752] Call Trace:
[   72.120393][ T6752]  <TASK>
[   72.123164][ T6752]  ? btrfs_ioctl_balance+0x2d6/0x600 [btrfs]
[   72.129004][ T6752]  dump_stack_lvl+0x34/0x44
[   72.133326][ T6752]  print_address_description+0x1f/0x200
[   72.133821][ T6763] BTRFS warning (device sda2): cannot activate swapfile while exclusive operation is running
[   72.139714][ T6752]  ? btrfs_ioctl_balance+0x2d6/0x600 [btrfs]
[   72.155412][ T6752]  print_report.cold+0x55/0x22c
[   72.160078][ T6752]  ? _raw_spin_lock_irqsave+0x87/0x100
[   72.165343][ T6752]  ? btrfs_ioctl_balance+0x2d6/0x600 [btrfs]
[   72.171179][ T6752]  ? btrfs_ioctl_balance+0x2d6/0x600 [btrfs]
[   72.177002][ T6752]  kasan_report_invalid_free+0x79/0x100
[   72.182354][ T6752]  ? __kasan_kmalloc+0x80/0xc0
[   72.186929][ T6752]  ? btrfs_ioctl_balance+0x2d6/0x600 [btrfs]
[   72.192753][ T6752]  __kasan_slab_free+0x152/0x180
[   72.197499][ T6752]  kfree+0xa6/0x340
[   72.201129][ T6752]  btrfs_ioctl_balance+0x2d6/0x600 [btrfs]
[   72.206780][ T6752]  btrfs_ioctl+0x893/0x2580 [btrfs]
[   72.211831][ T6752]  ? btrfs_ioctl_get_supported_features+0x40/0x40 [btrfs]
[   72.218772][ T6752]  ? vma_link+0x4e8/0x900
[   72.222920][ T6752]  ? handle_mm_fault+0x1c7/0x640
[   72.227673][ T6752]  ? up_read+0x15/0xc0
[   72.231560][ T6752]  __x64_sys_ioctl+0x127/0x1c0
[   72.236136][ T6752]  do_syscall_64+0x3b/0xc0
[   72.240369][ T6752]  entry_SYSCALL_64_after_hwframe+0x44/0xae
[   72.246063][ T6752] RIP: 0033:0x7febcb4af427
[   72.250294][ T6752] Code: 00 00 90 48 8b 05 69 aa 0c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 39 aa 0c 00 f7 d8 64 89 01 48
[   72.269589][ T6752] RSP: 002b:00007ffde9257118 EFLAGS: 00000206 ORIG_RAX: 0000000000000010
[   72.277781][ T6752] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007febcb4af427
[   72.285542][ T6752] RDX: 00007ffde92571a8 RSI: 00000000c4009420 RDI: 0000000000000004
[   72.293302][ T6752] RBP: 00007ffde92571a8 R08: 0000000000000003 R09: 0000000000000078
[   72.301060][ T6752] R10: fffffffffffffa4a R11: 0000000000000206 R12: 0000000000000004
[   72.308819][ T6752] R13: 00007ffde92598b8 R14: 0000000000000002 R15: 0000000000000000
[   72.316579][ T6752]  </TASK>
[   72.319432][ T6752]
[   72.321597][ T6752] Allocated by task 3586:
[   72.325741][ T6752]  kasan_save_stack+0x1e/0x40
[   72.330232][ T6752]  __kasan_kmalloc+0x81/0xc0
[   72.334636][ T6752]  load_elf_phdrs+0xd9/0x1c0
[   72.339039][ T6752]  load_elf_binary+0x194/0x2700
[   72.343707][ T6752]  search_binary_handler+0x18d/0x480
[   72.348811][ T6752]  exec_binprm+0xd6/0x440
[   72.352954][ T6752]  bprm_execve+0x485/0x840
[   72.357790][ T6752]  do_execveat_common+0x4c7/0x680
[   72.363226][ T6752]  __x64_sys_execve+0x88/0xc0
[   72.367719][ T6752]  do_syscall_64+0x3b/0xc0
[   72.371950][ T6752]  entry_SYSCALL_64_after_hwframe+0x44/0xae
[   72.377643][ T6752]
[   72.379805][ T6752] Freed by task 6752:
[   72.383605][ T6752]  kasan_save_stack+0x1e/0x40
[   72.388096][ T6752]  kasan_set_track+0x21/0x40
[   72.392499][ T6752]  kasan_set_free_info+0x20/0x40
[   72.397248][ T6752]  __kasan_slab_free+0x108/0x180
[   72.401994][ T6752]  kfree+0xa6/0x340
[   72.405621][ T6752]  btrfs_ioctl_balance+0x2c4/0x600 [btrfs]
[   72.411298][ T6752]  btrfs_ioctl+0x893/0x2580 [btrfs]
[   72.416347][ T6752]  __x64_sys_ioctl+0x127/0x1c0
[   72.420923][ T6752]  do_syscall_64+0x3b/0xc0
[   72.425155][ T6752]  entry_SYSCALL_64_after_hwframe+0x44/0xae
[   72.430848][ T6752]
[   72.433012][ T6752] The buggy address belongs to the object at ffff88811a7ee000
[   72.433012][ T6752]  which belongs to the cache kmalloc-1k of size 1024
[   72.446798][ T6752] The buggy address is located 0 bytes inside of
[   72.446798][ T6752]  1024-byte region [ffff88811a7ee000, ffff88811a7ee400)
[   72.459724][ T6752]
[   72.461890][ T6752] The buggy address belongs to the physical page:
[   72.468099][ T6752] page:00000000a7668fa1 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x11a7e8
[   72.478097][ T6752] head:00000000a7668fa1 order:3 compound_mapcount:0 compound_pincount:0
[   72.486200][ T6752] flags: 0x17ffffc0010200(slab|head|node=0|zone=2|lastcpupid=0x1fffff)
[   72.494221][ T6752] raw: 0017ffffc0010200 ffffea0008552200 dead000000000002 ffff888100042dc0
[   72.502583][ T6752] raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
[   72.510944][ T6752] page dumped because: kasan: bad access detected
[   72.517154][ T6752]
[   72.519316][ T6752] Memory state around the buggy address:
[   72.524750][ T6752]  ffff88811a7edf00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[   72.532596][ T6752]  ffff88811a7edf80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[   72.540443][ T6752] >ffff88811a7ee000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   72.548288][ T6752]                    ^
[   72.552173][ T6752]  ffff88811a7ee080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   72.560018][ T6752]  ffff88811a7ee100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[   72.567863][ T6752] ==================================================================
[   72.575771][ T6752] Disabling lock debugging due to kernel taint



To reproduce:

        git clone https://github.com/intel/lkp-tests.git
        cd lkp-tests
        sudo bin/lkp install job.yaml           # job file is attached in this email
        bin/lkp split-job --compatible job.yaml # generate the yaml file for lkp run
        sudo bin/lkp run generated-yaml-file

        # if come across any failure that blocks the test,
        # please remove ~/.lkp and /lkp dir to run from a clean state.
diff mbox series

Patch

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 8e0cc17d5f81..f2cfbce9bec4 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -4406,7 +4406,7 @@  static long btrfs_ioctl_balance(struct file *file, void __user *arg)
 	struct btrfs_fs_info *fs_info = root->fs_info;
 	struct btrfs_ioctl_balance_args *bargs;
 	struct btrfs_balance_control *bctl;
-	bool need_unlock; /* for mut. excl. ops lock */
+	bool need_unlock = true; /* for mut. excl. ops lock */
 	int ret;
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -4423,53 +4423,12 @@  static long btrfs_ioctl_balance(struct file *file, void __user *arg)
 		goto out;
 	}
 
-again:
-	if (btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE)) {
-		mutex_lock(&fs_info->balance_mutex);
-		need_unlock = true;
-		goto locked;
-	}
-
-	/*
-	 * mut. excl. ops lock is locked.  Three possibilities:
-	 *   (1) some other op is running
-	 *   (2) balance is running
-	 *   (3) balance is paused -- special case (think resume)
-	 */
-	mutex_lock(&fs_info->balance_mutex);
-	if (fs_info->balance_ctl) {
-		/* this is either (2) or (3) */
-		if (!test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags)) {
-			mutex_unlock(&fs_info->balance_mutex);
-			/*
-			 * Lock released to allow other waiters to continue,
-			 * we'll reexamine the status again.
-			 */
-			mutex_lock(&fs_info->balance_mutex);
-
-			if (fs_info->balance_ctl &&
-			    !test_bit(BTRFS_FS_BALANCE_RUNNING, &fs_info->flags)) {
-				/* this is (3) */
-				need_unlock = false;
-				goto locked;
-			}
-
-			mutex_unlock(&fs_info->balance_mutex);
-			goto again;
-		} else {
-			/* this is (2) */
-			mutex_unlock(&fs_info->balance_mutex);
-			ret = -EINPROGRESS;
-			goto out;
-		}
-	} else {
-		/* this is (1) */
-		mutex_unlock(&fs_info->balance_mutex);
-		ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
+	ret = btrfs_try_lock_balance(fs_info, &need_unlock);
+	if (ret)
 		goto out;
-	}
 
-locked:
+	lockdep_assert_held(&fs_info->balance_mutex);
+
 	if (bargs->flags & BTRFS_BALANCE_RESUME) {
 		if (!fs_info->balance_ctl) {
 			ret = -ENOTCONN;
@@ -4529,6 +4488,7 @@  static long btrfs_ioctl_balance(struct file *file, void __user *arg)
 	if (need_unlock)
 		btrfs_exclop_finish(fs_info);
 out:
+	kfree(bargs);
 	mnt_drop_write_file(file);
 	kfree(bargs);
 	return ret;