1
0
Fork 0
alistair23-linux/fs/btrfs
Josef Bacik 4254a4f798 btrfs: fix potential deadlock in the search ioctl
[ Upstream commit a48b73eca4 ]

With the conversion of the tree locks to rwsem I got the following
lockdep splat:

  ======================================================
  WARNING: possible circular locking dependency detected
  5.8.0-rc7-00165-g04ec4da5f45f-dirty #922 Not tainted
  ------------------------------------------------------
  compsize/11122 is trying to acquire lock:
  ffff889fabca8768 (&mm->mmap_lock#2){++++}-{3:3}, at: __might_fault+0x3e/0x90

  but task is already holding lock:
  ffff889fe720fe40 (btrfs-fs-00){++++}-{3:3}, at: __btrfs_tree_read_lock+0x39/0x180

  which lock already depends on the new lock.

  the existing dependency chain (in reverse order) is:

  -> #2 (btrfs-fs-00){++++}-{3:3}:
	 down_write_nested+0x3b/0x70
	 __btrfs_tree_lock+0x24/0x120
	 btrfs_search_slot+0x756/0x990
	 btrfs_lookup_inode+0x3a/0xb4
	 __btrfs_update_delayed_inode+0x93/0x270
	 btrfs_async_run_delayed_root+0x168/0x230
	 btrfs_work_helper+0xd4/0x570
	 process_one_work+0x2ad/0x5f0
	 worker_thread+0x3a/0x3d0
	 kthread+0x133/0x150
	 ret_from_fork+0x1f/0x30

  -> #1 (&delayed_node->mutex){+.+.}-{3:3}:
	 __mutex_lock+0x9f/0x930
	 btrfs_delayed_update_inode+0x50/0x440
	 btrfs_update_inode+0x8a/0xf0
	 btrfs_dirty_inode+0x5b/0xd0
	 touch_atime+0xa1/0xd0
	 btrfs_file_mmap+0x3f/0x60
	 mmap_region+0x3a4/0x640
	 do_mmap+0x376/0x580
	 vm_mmap_pgoff+0xd5/0x120
	 ksys_mmap_pgoff+0x193/0x230
	 do_syscall_64+0x50/0x90
	 entry_SYSCALL_64_after_hwframe+0x44/0xa9

  -> #0 (&mm->mmap_lock#2){++++}-{3:3}:
	 __lock_acquire+0x1272/0x2310
	 lock_acquire+0x9e/0x360
	 __might_fault+0x68/0x90
	 _copy_to_user+0x1e/0x80
	 copy_to_sk.isra.32+0x121/0x300
	 search_ioctl+0x106/0x200
	 btrfs_ioctl_tree_search_v2+0x7b/0xf0
	 btrfs_ioctl+0x106f/0x30a0
	 ksys_ioctl+0x83/0xc0
	 __x64_sys_ioctl+0x16/0x20
	 do_syscall_64+0x50/0x90
	 entry_SYSCALL_64_after_hwframe+0x44/0xa9

  other info that might help us debug this:

  Chain exists of:
    &mm->mmap_lock#2 --> &delayed_node->mutex --> btrfs-fs-00

   Possible unsafe locking scenario:

	 CPU0                    CPU1
	 ----                    ----
    lock(btrfs-fs-00);
				 lock(&delayed_node->mutex);
				 lock(btrfs-fs-00);
    lock(&mm->mmap_lock#2);

   *** DEADLOCK ***

  1 lock held by compsize/11122:
   #0: ffff889fe720fe40 (btrfs-fs-00){++++}-{3:3}, at: __btrfs_tree_read_lock+0x39/0x180

  stack backtrace:
  CPU: 17 PID: 11122 Comm: compsize Kdump: loaded Not tainted 5.8.0-rc7-00165-g04ec4da5f45f-dirty #922
  Hardware name: Quanta Tioga Pass Single Side 01-0030993006/Tioga Pass Single Side, BIOS F08_3A18 12/20/2018
  Call Trace:
   dump_stack+0x78/0xa0
   check_noncircular+0x165/0x180
   __lock_acquire+0x1272/0x2310
   lock_acquire+0x9e/0x360
   ? __might_fault+0x3e/0x90
   ? find_held_lock+0x72/0x90
   __might_fault+0x68/0x90
   ? __might_fault+0x3e/0x90
   _copy_to_user+0x1e/0x80
   copy_to_sk.isra.32+0x121/0x300
   ? btrfs_search_forward+0x2a6/0x360
   search_ioctl+0x106/0x200
   btrfs_ioctl_tree_search_v2+0x7b/0xf0
   btrfs_ioctl+0x106f/0x30a0
   ? __do_sys_newfstat+0x5a/0x70
   ? ksys_ioctl+0x83/0xc0
   ksys_ioctl+0x83/0xc0
   __x64_sys_ioctl+0x16/0x20
   do_syscall_64+0x50/0x90
   entry_SYSCALL_64_after_hwframe+0x44/0xa9

The problem is we're doing a copy_to_user() while holding tree locks,
which can deadlock if we have to do a page fault for the copy_to_user().
This exists even without my locking changes, so it needs to be fixed.
Rework the search ioctl to do the pre-fault and then
copy_to_user_nofault for the copying.

CC: stable@vger.kernel.org # 4.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: Sasha Levin <sashal@kernel.org>
2020-09-09 19:12:31 +02:00
..
tests btrfs: Correctly handle empty trees in find_first_clear_extent_bit 2020-02-11 04:35:34 -08:00
Kconfig btrfs: Fix build error while LIBCRC32C is module 2019-07-17 17:03:30 +02:00
Makefile btrfs: migrate the block group lookup code 2019-09-09 14:59:04 +02:00
acl.c btrfs: cleanup btrfs_setxattr_trans and drop transaction parameter 2019-04-29 19:02:44 +02:00
async-thread.c Btrfs: fix crash during unmount due to race with delayed inode workers 2020-04-17 10:50:15 +02:00
async-thread.h Btrfs: fix crash during unmount due to race with delayed inode workers 2020-04-17 10:50:15 +02:00
backref.c btrfs: fix double free on ulist after backref resolution failure 2020-07-29 10:18:30 +02:00
backref.h btrfs: fiemap: preallocate ulists for btrfs_check_shared 2019-07-01 13:34:53 +02:00
block-group.c btrfs: add wrapper for transaction abort predicate 2020-08-26 10:40:49 +02:00
block-group.h btrfs: move struct io_ctl to free-space-cache.h 2019-09-09 14:59:15 +02:00
block-rsv.c btrfs: force chunk allocation if our global rsv is larger than metadata 2020-06-22 09:31:13 +02:00
block-rsv.h btrfs: migrate the global_block_rsv helpers to block-rsv.c 2019-07-02 12:30:55 +02:00
btrfs_inode.h btrfs: remove assumption about csum type form btrfs_print_data_csum_error() 2019-07-01 13:35:02 +02:00
check-integrity.c btrfs: fix possible NULL-pointer dereference in integrity checks 2020-02-24 08:36:53 +01:00
check-integrity.h btrfs: replace GPL boilerplate by SPDX -- headers 2018-04-12 16:29:46 +02:00
compression.c btrfs: move cond_wake_up functions out of ctree 2019-09-09 14:59:15 +02:00
compression.h btrfs: compression: replace set_level callbacks by a common helper 2019-09-09 14:59:11 +02:00
ctree.c btrfs: set the lockdep class for log tree extent buffers 2020-09-09 19:12:31 +02:00
ctree.h btrfs: detect nocow for swap after snapshot delete 2020-09-03 11:27:02 +02:00
delalloc-space.c Btrfs: fix qgroup double free after failure to reserve metadata for delalloc 2019-10-17 20:13:44 +02:00
delalloc-space.h btrfs: migrate the delalloc space stuff to it's own home 2019-07-04 17:26:17 +02:00
delayed-inode.c btrfs: add wrapper for transaction abort predicate 2020-08-26 10:40:49 +02:00
delayed-inode.h Btrfs: delayed-inode: use rb_first_cached for ins_root and del_root 2018-10-15 17:23:33 +02:00
delayed-ref.c Btrfs: fix race between adding and putting tree mod seq elements and nodes 2020-02-11 04:35:34 -08:00
delayed-ref.h btrfs: migrate the delayed refs rsv code 2019-07-04 17:26:17 +02:00
dev-replace.c btrfs: move cond_wake_up functions out of ctree 2019-09-09 14:59:15 +02:00
dev-replace.h btrfs: get fs_info from trans in btrfs_run_dev_replace 2019-04-29 19:02:43 +02:00
dir-item.c btrfs: remove unused parameter fs_info from btrfs_extend_item 2019-04-29 19:02:50 +02:00
disk-io.c btrfs: fix space cache memory leak after transaction abort 2020-09-03 11:27:02 +02:00
disk-io.h btrfs: Make reada_tree_block_flagged private 2019-09-09 14:59:11 +02:00
export.c btrfs: export helpers for subvolume name/id resolution 2020-08-26 10:40:49 +02:00
export.h btrfs: export helpers for subvolume name/id resolution 2020-08-26 10:40:49 +02:00
extent-tree.c btrfs: set the correct lockdep class for new nodes 2020-09-09 19:12:31 +02:00
extent_io.c btrfs: fix potential deadlock in the search ioctl 2020-09-09 19:12:31 +02:00
extent_io.h btrfs: fix potential deadlock in the search ioctl 2020-09-09 19:12:31 +02:00
extent_map.c Btrfs: fix race between using extent maps and merging them 2020-02-19 19:53:00 +01:00
extent_map.h btrfs: Remove impossible condition from mergable_maps 2019-02-25 14:13:21 +01:00
file-item.c btrfs: do not ignore error from btrfs_next_leaf() when inserting checksums 2020-06-22 09:30:55 +02:00
file.c btrfs: detect nocow for swap after snapshot delete 2020-09-03 11:27:02 +02:00
free-space-cache.c btrfs: fix space cache memory leak after transaction abort 2020-09-03 11:27:02 +02:00
free-space-cache.h btrfs: move struct io_ctl to free-space-cache.h 2019-09-09 14:59:15 +02:00
free-space-tree.c btrfs: move basic block_group definitions to their own header 2019-09-09 14:59:03 +02:00
free-space-tree.h btrfs: move basic block_group definitions to their own header 2019-09-09 14:59:03 +02:00
inode-item.c btrfs: Make btrfs_find_name_in_ext_backref return struct btrfs_inode_extref 2019-09-09 14:59:16 +02:00
inode-map.c btrfs: qgroup: Always free PREALLOC META reserve in btrfs_delalloc_release_extents() 2019-10-15 18:50:07 +02:00
inode-map.h btrfs: replace GPL boilerplate by SPDX -- headers 2018-04-12 16:29:46 +02:00
inode.c btrfs: detect nocow for swap after snapshot delete 2020-09-03 11:27:02 +02:00
ioctl.c btrfs: fix potential deadlock in the search ioctl 2020-09-09 19:12:31 +02:00
locking.c btrfs: move cond_wake_up functions out of ctree 2019-09-09 14:59:15 +02:00
locking.h btrfs: Remove unused locking functions 2019-09-09 14:58:59 +02:00
lzo.c btrfs: compression: replace set_level callbacks by a common helper 2019-09-09 14:59:11 +02:00
misc.h btrfs: move math functions to misc.h 2019-09-09 14:59:15 +02:00
ordered-data.c Btrfs: fix btrfs_wait_ordered_range() so that it waits for all ordered extents 2020-02-28 17:22:24 +01:00
ordered-data.h btrfs: don't assume ordered sums to be 4 bytes 2019-07-01 13:35:00 +02:00
orphan.c btrfs: replace GPL boilerplate by SPDX -- sources 2018-04-12 16:29:51 +02:00
print-tree.c btrfs: switch extent_buffer write_locks from atomic to int 2019-07-02 12:30:47 +02:00
print-tree.h btrfs: print-tree: debugging output enhancement 2018-04-20 19:18:16 +02:00
props.c btrfs: rename the btrfs_calc_*_metadata_size helpers 2019-09-09 14:59:13 +02:00
props.h btrfs: delete unused function btrfs_set_prop_trans 2019-04-29 19:02:54 +02:00
qgroup.c btrfs: make btrfs_qgroup_check_reserved_leak take btrfs_inode 2020-09-03 11:26:47 +02:00
qgroup.h btrfs: make btrfs_qgroup_check_reserved_leak take btrfs_inode 2020-09-03 11:26:47 +02:00
raid56.c btrfs: get rid of unique workqueue helper functions 2020-01-09 10:20:06 +01:00
raid56.h btrfs: constify map parameter for nr_parity_stripes and nr_data_stripes 2019-07-01 13:34:58 +02:00
rcu-string.h btrfs: replace GPL boilerplate by SPDX -- headers 2018-04-12 16:29:46 +02:00
reada.c btrfs: get rid of unique workqueue helper functions 2020-01-09 10:20:06 +01:00
ref-verify.c btrfs: ref-verify: fix memory leak in add_block_entry 2020-08-21 13:05:21 +02:00
ref-verify.h btrfs: ref-verify: Use btrfs_ref to refactor btrfs_ref_tree_mod() 2019-04-29 19:02:49 +02:00
relocation.c btrfs: relocation: review the call sites which can be interrupted by signal 2020-08-21 13:05:22 +02:00
root-tree.c btrfs: do not delete mismatched root refs 2020-01-23 08:22:40 +01:00
scrub.c btrfs: allocate scrub workqueues outside of locks 2020-09-09 19:12:31 +02:00
send.c btrfs: send: emit file capabilities after chown 2020-06-22 09:31:12 +02:00
send.h btrfs: replace GPL boilerplate by SPDX -- headers 2018-04-12 16:29:46 +02:00
space-info.c btrfs: fix lockdep splat from btrfs_dump_space_info 2020-08-19 08:16:01 +02:00
space-info.h btrfs: improve global reserve stealing logic 2020-06-22 09:31:08 +02:00
struct-funcs.c btrfs: tie extent buffer and it's token together 2019-09-09 14:59:16 +02:00
super.c btrfs: reset compression level for lzo on remount 2020-09-03 11:27:02 +02:00
sysfs.c btrfs: sysfs: use NOFS for device creation 2020-08-21 13:05:22 +02:00
sysfs.h btrfs: sysfs: move helper macros to sysfs.c 2019-09-09 14:59:08 +02:00
transaction.c btrfs: add wrapper for transaction abort predicate 2020-08-26 10:40:49 +02:00
transaction.h btrfs: add wrapper for transaction abort predicate 2020-08-26 10:40:49 +02:00
tree-checker.c btrfs: tree-checker: fix the error message for transid error 2020-09-09 19:12:31 +02:00
tree-checker.h btrfs: get fs_info from eb in btrfs_check_chunk_valid 2019-04-29 19:02:39 +02:00
tree-defrag.c btrfs: open code now trivial btrfs_set_lock_blocking 2019-02-25 14:13:27 +01:00
tree-log.c btrfs: check the right error variable in btrfs_del_dir_entries_in_log 2020-09-03 11:27:02 +02:00
tree-log.h btrfs: get fs_info from trans in btrfs_set_log_full_commit 2019-04-29 19:02:41 +02:00
ulist.c btrfs: replace GPL boilerplate by SPDX -- sources 2018-04-12 16:29:51 +02:00
ulist.h btrfs: replace GPL boilerplate by SPDX -- headers 2018-04-12 16:29:46 +02:00
uuid-tree.c btrfs: handle ENOENT in btrfs_uuid_tree_iterate 2019-12-31 16:42:05 +01:00
volumes.c btrfs: drop path before adding new uuid tree entry 2020-09-09 19:12:30 +02:00
volumes.h btrfs: Remove btrfs_bio::flags member 2019-12-17 19:56:06 +01:00
xattr.c Btrfs: fix failure to persist compression property xattr deletion on fsync 2019-06-17 16:37:17 +02:00
xattr.h btrfs: cleanup btrfs_setxattr_trans and drop transaction parameter 2019-04-29 19:02:44 +02:00
zlib.c btrfs: compression: replace set_level callbacks by a common helper 2019-09-09 14:59:11 +02:00
zstd.c btrfs: move cond_wake_up functions out of ctree 2019-09-09 14:59:15 +02:00