From: Greg Kroah-Hartman Date: Tue, 15 Sep 2020 07:37:59 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v4.19.146~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cb414667a1862f514e67b1bb45d3abd4e13ba665;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: btrfs-fix-lockdep-splat-in-add_missing_dev.patch btrfs-fix-wrong-address-when-faulting-in-pages-in-the-search-ioctl.patch btrfs-require-only-sector-size-alignment-for-parent-eb-bytenr.patch firmware_loader-fix-memory-leak-for-paged-buffer.patch kobject-restore-old-behaviour-of-kobject_del-null.patch regulator-core-fix-slab-out-of-bounds-in-regulator_unlock_recursive.patch regulator-plug-of_node-leak-in-regulator_register-s-error-path.patch regulator-push-allocation-in-regulator_init_coupling-outside-of-lock.patch regulator-push-allocation-in-set_consumer_device_supply-out-of-lock.patch regulator-push-allocations-in-create_regulator-outside-of-lock.patch scsi-target-iscsi-fix-data-digest-calculation.patch scsi-target-iscsi-fix-hang-in-iscsit_access_np-when-getting-tpg-np_login_sem.patch --- diff --git a/queue-5.4/btrfs-fix-lockdep-splat-in-add_missing_dev.patch b/queue-5.4/btrfs-fix-lockdep-splat-in-add_missing_dev.patch new file mode 100644 index 00000000000..b3c670b6386 --- /dev/null +++ b/queue-5.4/btrfs-fix-lockdep-splat-in-add_missing_dev.patch @@ -0,0 +1,185 @@ +From fccc0007b8dc952c6bc0805cdf842eb8ea06a639 Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Mon, 31 Aug 2020 10:52:42 -0400 +Subject: btrfs: fix lockdep splat in add_missing_dev + +From: Josef Bacik + +commit fccc0007b8dc952c6bc0805cdf842eb8ea06a639 upstream. + +Nikolay reported a lockdep splat in generic/476 that I could reproduce +with btrfs/187. + + ====================================================== + WARNING: possible circular locking dependency detected + 5.9.0-rc2+ #1 Tainted: G W + ------------------------------------------------------ + kswapd0/100 is trying to acquire lock: + ffff9e8ef38b6268 (&delayed_node->mutex){+.+.}-{3:3}, at: __btrfs_release_delayed_node.part.0+0x3f/0x330 + + but task is already holding lock: + ffffffffa9d74700 (fs_reclaim){+.+.}-{0:0}, at: __fs_reclaim_acquire+0x5/0x30 + + which lock already depends on the new lock. + + the existing dependency chain (in reverse order) is: + + -> #2 (fs_reclaim){+.+.}-{0:0}: + fs_reclaim_acquire+0x65/0x80 + slab_pre_alloc_hook.constprop.0+0x20/0x200 + kmem_cache_alloc_trace+0x3a/0x1a0 + btrfs_alloc_device+0x43/0x210 + add_missing_dev+0x20/0x90 + read_one_chunk+0x301/0x430 + btrfs_read_sys_array+0x17b/0x1b0 + open_ctree+0xa62/0x1896 + btrfs_mount_root.cold+0x12/0xea + legacy_get_tree+0x30/0x50 + vfs_get_tree+0x28/0xc0 + vfs_kern_mount.part.0+0x71/0xb0 + btrfs_mount+0x10d/0x379 + legacy_get_tree+0x30/0x50 + vfs_get_tree+0x28/0xc0 + path_mount+0x434/0xc00 + __x64_sys_mount+0xe3/0x120 + do_syscall_64+0x33/0x40 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + + -> #1 (&fs_info->chunk_mutex){+.+.}-{3:3}: + __mutex_lock+0x7e/0x7e0 + btrfs_chunk_alloc+0x125/0x3a0 + find_free_extent+0xdf6/0x1210 + btrfs_reserve_extent+0xb3/0x1b0 + btrfs_alloc_tree_block+0xb0/0x310 + alloc_tree_block_no_bg_flush+0x4a/0x60 + __btrfs_cow_block+0x11a/0x530 + btrfs_cow_block+0x104/0x220 + btrfs_search_slot+0x52e/0x9d0 + btrfs_lookup_inode+0x2a/0x8f + __btrfs_update_delayed_inode+0x80/0x240 + btrfs_commit_inode_delayed_inode+0x119/0x120 + btrfs_evict_inode+0x357/0x500 + evict+0xcf/0x1f0 + vfs_rmdir.part.0+0x149/0x160 + do_rmdir+0x136/0x1a0 + do_syscall_64+0x33/0x40 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + + -> #0 (&delayed_node->mutex){+.+.}-{3:3}: + __lock_acquire+0x1184/0x1fa0 + lock_acquire+0xa4/0x3d0 + __mutex_lock+0x7e/0x7e0 + __btrfs_release_delayed_node.part.0+0x3f/0x330 + btrfs_evict_inode+0x24c/0x500 + evict+0xcf/0x1f0 + dispose_list+0x48/0x70 + prune_icache_sb+0x44/0x50 + super_cache_scan+0x161/0x1e0 + do_shrink_slab+0x178/0x3c0 + shrink_slab+0x17c/0x290 + shrink_node+0x2b2/0x6d0 + balance_pgdat+0x30a/0x670 + kswapd+0x213/0x4c0 + kthread+0x138/0x160 + ret_from_fork+0x1f/0x30 + + other info that might help us debug this: + + Chain exists of: + &delayed_node->mutex --> &fs_info->chunk_mutex --> fs_reclaim + + Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + lock(fs_reclaim); + lock(&fs_info->chunk_mutex); + lock(fs_reclaim); + lock(&delayed_node->mutex); + + *** DEADLOCK *** + + 3 locks held by kswapd0/100: + #0: ffffffffa9d74700 (fs_reclaim){+.+.}-{0:0}, at: __fs_reclaim_acquire+0x5/0x30 + #1: ffffffffa9d65c50 (shrinker_rwsem){++++}-{3:3}, at: shrink_slab+0x115/0x290 + #2: ffff9e8e9da260e0 (&type->s_umount_key#48){++++}-{3:3}, at: super_cache_scan+0x38/0x1e0 + + stack backtrace: + CPU: 1 PID: 100 Comm: kswapd0 Tainted: G W 5.9.0-rc2+ #1 + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014 + Call Trace: + dump_stack+0x92/0xc8 + check_noncircular+0x12d/0x150 + __lock_acquire+0x1184/0x1fa0 + lock_acquire+0xa4/0x3d0 + ? __btrfs_release_delayed_node.part.0+0x3f/0x330 + __mutex_lock+0x7e/0x7e0 + ? __btrfs_release_delayed_node.part.0+0x3f/0x330 + ? __btrfs_release_delayed_node.part.0+0x3f/0x330 + ? lock_acquire+0xa4/0x3d0 + ? btrfs_evict_inode+0x11e/0x500 + ? find_held_lock+0x2b/0x80 + __btrfs_release_delayed_node.part.0+0x3f/0x330 + btrfs_evict_inode+0x24c/0x500 + evict+0xcf/0x1f0 + dispose_list+0x48/0x70 + prune_icache_sb+0x44/0x50 + super_cache_scan+0x161/0x1e0 + do_shrink_slab+0x178/0x3c0 + shrink_slab+0x17c/0x290 + shrink_node+0x2b2/0x6d0 + balance_pgdat+0x30a/0x670 + kswapd+0x213/0x4c0 + ? _raw_spin_unlock_irqrestore+0x46/0x60 + ? add_wait_queue_exclusive+0x70/0x70 + ? balance_pgdat+0x670/0x670 + kthread+0x138/0x160 + ? kthread_create_worker_on_cpu+0x40/0x40 + ret_from_fork+0x1f/0x30 + +This is because we are holding the chunk_mutex when we call +btrfs_alloc_device, which does a GFP_KERNEL allocation. We don't want +to switch that to a GFP_NOFS lock because this is the only place where +it matters. So instead use memalloc_nofs_save() around the allocation +in order to avoid the lockdep splat. + +Reported-by: Nikolay Borisov +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Anand Jain +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/volumes.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -4,6 +4,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -6708,8 +6709,17 @@ static struct btrfs_device *add_missing_ + u64 devid, u8 *dev_uuid) + { + struct btrfs_device *device; ++ unsigned int nofs_flag; + ++ /* ++ * We call this under the chunk_mutex, so we want to use NOFS for this ++ * allocation, however we don't want to change btrfs_alloc_device() to ++ * always do NOFS because we use it in a lot of other GFP_KERNEL safe ++ * places. ++ */ ++ nofs_flag = memalloc_nofs_save(); + device = btrfs_alloc_device(NULL, &devid, dev_uuid); ++ memalloc_nofs_restore(nofs_flag); + if (IS_ERR(device)) + return device; + diff --git a/queue-5.4/btrfs-fix-wrong-address-when-faulting-in-pages-in-the-search-ioctl.patch b/queue-5.4/btrfs-fix-wrong-address-when-faulting-in-pages-in-the-search-ioctl.patch new file mode 100644 index 00000000000..1295b92e214 --- /dev/null +++ b/queue-5.4/btrfs-fix-wrong-address-when-faulting-in-pages-in-the-search-ioctl.patch @@ -0,0 +1,51 @@ +From 1c78544eaa4660096aeb6a57ec82b42cdb3bfe5a Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Mon, 14 Sep 2020 09:01:04 +0100 +Subject: btrfs: fix wrong address when faulting in pages in the search ioctl + +From: Filipe Manana + +commit 1c78544eaa4660096aeb6a57ec82b42cdb3bfe5a upstream. + +When faulting in the pages for the user supplied buffer for the search +ioctl, we are passing only the base address of the buffer to the function +fault_in_pages_writeable(). This means that after the first iteration of +the while loop that searches for leaves, when we have a non-zero offset, +stored in 'sk_offset', we try to fault in a wrong page range. + +So fix this by adding the offset in 'sk_offset' to the base address of the +user supplied buffer when calling fault_in_pages_writeable(). + +Several users have reported that the applications compsize and bees have +started to operate incorrectly since commit a48b73eca4ceb9 ("btrfs: fix +potential deadlock in the search ioctl") was added to stable trees, and +these applications make heavy use of the search ioctls. This fixes their +issues. + +Link: https://lore.kernel.org/linux-btrfs/632b888d-a3c3-b085-cdf5-f9bb61017d92@lechevalier.se/ +Link: https://github.com/kilobyte/compsize/issues/34 +Fixes: a48b73eca4ceb9 ("btrfs: fix potential deadlock in the search ioctl") +CC: stable@vger.kernel.org # 4.4+ +Tested-by: A L +Reviewed-by: Josef Bacik +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/ioctl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -2215,7 +2215,8 @@ static noinline int search_ioctl(struct + key.offset = sk->min_offset; + + while (1) { +- ret = fault_in_pages_writeable(ubuf, *buf_size - sk_offset); ++ ret = fault_in_pages_writeable(ubuf + sk_offset, ++ *buf_size - sk_offset); + if (ret) + break; + diff --git a/queue-5.4/btrfs-require-only-sector-size-alignment-for-parent-eb-bytenr.patch b/queue-5.4/btrfs-require-only-sector-size-alignment-for-parent-eb-bytenr.patch new file mode 100644 index 00000000000..f84c8c6d1f3 --- /dev/null +++ b/queue-5.4/btrfs-require-only-sector-size-alignment-for-parent-eb-bytenr.patch @@ -0,0 +1,151 @@ +From ea57788eb76dc81f6003245427356a1dcd0ac524 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Wed, 26 Aug 2020 17:26:43 +0800 +Subject: btrfs: require only sector size alignment for parent eb bytenr + +From: Qu Wenruo + +commit ea57788eb76dc81f6003245427356a1dcd0ac524 upstream. + +[BUG] +A completely sane converted fs will cause kernel warning at balance +time: + + [ 1557.188633] BTRFS info (device sda7): relocating block group 8162107392 flags data + [ 1563.358078] BTRFS info (device sda7): found 11722 extents + [ 1563.358277] BTRFS info (device sda7): leaf 7989321728 gen 95 total ptrs 213 free space 3458 owner 2 + [ 1563.358280] item 0 key (7984947200 169 0) itemoff 16250 itemsize 33 + [ 1563.358281] extent refs 1 gen 90 flags 2 + [ 1563.358282] ref#0: tree block backref root 4 + [ 1563.358285] item 1 key (7985602560 169 0) itemoff 16217 itemsize 33 + [ 1563.358286] extent refs 1 gen 93 flags 258 + [ 1563.358287] ref#0: shared block backref parent 7985602560 + [ 1563.358288] (parent 7985602560 is NOT ALIGNED to nodesize 16384) + [ 1563.358290] item 2 key (7985635328 169 0) itemoff 16184 itemsize 33 + ... + [ 1563.358995] BTRFS error (device sda7): eb 7989321728 invalid extent inline ref type 182 + [ 1563.358996] ------------[ cut here ]------------ + [ 1563.359005] WARNING: CPU: 14 PID: 2930 at 0xffffffff9f231766 + +Then with transaction abort, and obviously failed to balance the fs. + +[CAUSE] +That mentioned inline ref type 182 is completely sane, it's +BTRFS_SHARED_BLOCK_REF_KEY, it's some extra check making kernel to +believe it's invalid. + +Commit 64ecdb647ddb ("Btrfs: add one more sanity check for shared ref +type") introduced extra checks for backref type. + +One of the requirement is, parent bytenr must be aligned to node size, +which is not correct. + +One example is like this: + +0 1G 1G+4K 2G 2G+4K + | |///////////////////|//| <- A chunk starts at 1G+4K + | | <- A tree block get reserved at bytenr 1G+4K + +Then we have a valid tree block at bytenr 1G+4K, but not aligned to +nodesize (16K). + +Such chunk is not ideal, but current kernel can handle it pretty well. +We may warn about such tree block in the future, but should not reject +them. + +[FIX] +Change the alignment requirement from node size alignment to sector size +alignment. + +Also, to make our lives a little easier, also output @iref when +btrfs_get_extent_inline_ref_type() failed, so we can locate the item +easier. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=205475 +Fixes: 64ecdb647ddb ("Btrfs: add one more sanity check for shared ref type") +CC: stable@vger.kernel.org # 4.14+ +Reviewed-by: Josef Bacik +Signed-off-by: Qu Wenruo +[ update comments and messages ] +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/extent-tree.c | 19 +++++++++---------- + fs/btrfs/print-tree.c | 12 +++++++----- + 2 files changed, 16 insertions(+), 15 deletions(-) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -402,12 +402,11 @@ int btrfs_get_extent_inline_ref_type(con + if (type == BTRFS_SHARED_BLOCK_REF_KEY) { + ASSERT(eb->fs_info); + /* +- * Every shared one has parent tree +- * block, which must be aligned to +- * nodesize. ++ * Every shared one has parent tree block, ++ * which must be aligned to sector size. + */ + if (offset && +- IS_ALIGNED(offset, eb->fs_info->nodesize)) ++ IS_ALIGNED(offset, eb->fs_info->sectorsize)) + return type; + } + } else if (is_data == BTRFS_REF_TYPE_DATA) { +@@ -416,12 +415,11 @@ int btrfs_get_extent_inline_ref_type(con + if (type == BTRFS_SHARED_DATA_REF_KEY) { + ASSERT(eb->fs_info); + /* +- * Every shared one has parent tree +- * block, which must be aligned to +- * nodesize. ++ * Every shared one has parent tree block, ++ * which must be aligned to sector size. + */ + if (offset && +- IS_ALIGNED(offset, eb->fs_info->nodesize)) ++ IS_ALIGNED(offset, eb->fs_info->sectorsize)) + return type; + } + } else { +@@ -431,8 +429,9 @@ int btrfs_get_extent_inline_ref_type(con + } + + btrfs_print_leaf((struct extent_buffer *)eb); +- btrfs_err(eb->fs_info, "eb %llu invalid extent inline ref type %d", +- eb->start, type); ++ btrfs_err(eb->fs_info, ++ "eb %llu iref 0x%lx invalid extent inline ref type %d", ++ eb->start, (unsigned long)iref, type); + WARN_ON(1); + + return BTRFS_REF_TYPE_INVALID; +--- a/fs/btrfs/print-tree.c ++++ b/fs/btrfs/print-tree.c +@@ -95,9 +95,10 @@ static void print_extent_item(struct ext + * offset is supposed to be a tree block which + * must be aligned to nodesize. + */ +- if (!IS_ALIGNED(offset, eb->fs_info->nodesize)) +- pr_info("\t\t\t(parent %llu is NOT ALIGNED to nodesize %llu)\n", +- offset, (unsigned long long)eb->fs_info->nodesize); ++ if (!IS_ALIGNED(offset, eb->fs_info->sectorsize)) ++ pr_info( ++ "\t\t\t(parent %llu not aligned to sectorsize %u)\n", ++ offset, eb->fs_info->sectorsize); + break; + case BTRFS_EXTENT_DATA_REF_KEY: + dref = (struct btrfs_extent_data_ref *)(&iref->offset); +@@ -112,8 +113,9 @@ static void print_extent_item(struct ext + * must be aligned to nodesize. + */ + if (!IS_ALIGNED(offset, eb->fs_info->nodesize)) +- pr_info("\t\t\t(parent %llu is NOT ALIGNED to nodesize %llu)\n", +- offset, (unsigned long long)eb->fs_info->nodesize); ++ pr_info( ++ "\t\t\t(parent %llu not aligned to sectorsize %u)\n", ++ offset, eb->fs_info->sectorsize); + break; + default: + pr_cont("(extent %llu has INVALID ref type %d)\n", diff --git a/queue-5.4/firmware_loader-fix-memory-leak-for-paged-buffer.patch b/queue-5.4/firmware_loader-fix-memory-leak-for-paged-buffer.patch new file mode 100644 index 00000000000..2738dc1b227 --- /dev/null +++ b/queue-5.4/firmware_loader-fix-memory-leak-for-paged-buffer.patch @@ -0,0 +1,91 @@ +From 4965b8cd1bc1ffb017e5c58e622da82b55e49414 Mon Sep 17 00:00:00 2001 +From: Prateek Sood +Date: Fri, 21 Aug 2020 02:27:50 +0530 +Subject: firmware_loader: fix memory leak for paged buffer + +From: Prateek Sood + +commit 4965b8cd1bc1ffb017e5c58e622da82b55e49414 upstream. + +vfree() is being called on paged buffer allocated +using alloc_page() and mapped using vmap(). + +Freeing of pages in vfree() relies on nr_pages of +struct vm_struct. vmap() does not update nr_pages. +It can lead to memory leaks. + +Fixes: ddaf29fd9bb6 ("firmware: Free temporary page table after vmapping") +Signed-off-by: Prateek Sood +Reviewed-by: Takashi Iwai +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/1597957070-27185-1-git-send-email-prsood@codeaurora.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/base/firmware_loader/firmware.h | 2 ++ + drivers/base/firmware_loader/main.c | 17 +++++++++++------ + 2 files changed, 13 insertions(+), 6 deletions(-) + +--- a/drivers/base/firmware_loader/firmware.h ++++ b/drivers/base/firmware_loader/firmware.h +@@ -139,10 +139,12 @@ int assign_fw(struct firmware *fw, struc + void fw_free_paged_buf(struct fw_priv *fw_priv); + int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed); + int fw_map_paged_buf(struct fw_priv *fw_priv); ++bool fw_is_paged_buf(struct fw_priv *fw_priv); + #else + static inline void fw_free_paged_buf(struct fw_priv *fw_priv) {} + static inline int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; } + static inline int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; } ++static inline bool fw_is_paged_buf(struct fw_priv *fw_priv) { return false; } + #endif + + #endif /* __FIRMWARE_LOADER_H */ +--- a/drivers/base/firmware_loader/main.c ++++ b/drivers/base/firmware_loader/main.c +@@ -252,9 +252,11 @@ static void __free_fw_priv(struct kref * + list_del(&fw_priv->list); + spin_unlock(&fwc->lock); + +- fw_free_paged_buf(fw_priv); /* free leftover pages */ +- if (!fw_priv->allocated_size) ++ if (fw_is_paged_buf(fw_priv)) ++ fw_free_paged_buf(fw_priv); ++ else if (!fw_priv->allocated_size) + vfree(fw_priv->data); ++ + kfree_const(fw_priv->fw_name); + kfree(fw_priv); + } +@@ -268,6 +270,11 @@ static void free_fw_priv(struct fw_priv + } + + #ifdef CONFIG_FW_LOADER_PAGED_BUF ++bool fw_is_paged_buf(struct fw_priv *fw_priv) ++{ ++ return fw_priv->is_paged_buf; ++} ++ + void fw_free_paged_buf(struct fw_priv *fw_priv) + { + int i; +@@ -275,6 +282,8 @@ void fw_free_paged_buf(struct fw_priv *f + if (!fw_priv->pages) + return; + ++ vunmap(fw_priv->data); ++ + for (i = 0; i < fw_priv->nr_pages; i++) + __free_page(fw_priv->pages[i]); + kvfree(fw_priv->pages); +@@ -328,10 +337,6 @@ int fw_map_paged_buf(struct fw_priv *fw_ + if (!fw_priv->data) + return -ENOMEM; + +- /* page table is no longer needed after mapping, let's free */ +- kvfree(fw_priv->pages); +- fw_priv->pages = NULL; +- + return 0; + } + #endif diff --git a/queue-5.4/kobject-restore-old-behaviour-of-kobject_del-null.patch b/queue-5.4/kobject-restore-old-behaviour-of-kobject_del-null.patch new file mode 100644 index 00000000000..b821392320b --- /dev/null +++ b/queue-5.4/kobject-restore-old-behaviour-of-kobject_del-null.patch @@ -0,0 +1,42 @@ +From 40b8b826a6998639dd1c26f0e127f18371e1058d Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Mon, 3 Aug 2020 11:27:06 +0300 +Subject: kobject: Restore old behaviour of kobject_del(NULL) + +From: Andy Shevchenko + +commit 40b8b826a6998639dd1c26f0e127f18371e1058d upstream. + +The commit 079ad2fb4bf9 ("kobject: Avoid premature parent object freeing in +kobject_cleanup()") inadvertently dropped a possibility to call kobject_del() +with NULL pointer. Restore the old behaviour. + +Fixes: 079ad2fb4bf9 ("kobject: Avoid premature parent object freeing in kobject_cleanup()") +Cc: stable +Reported-by: Qu Wenruo +Cc: Heikki Krogerus +Signed-off-by: Andy Shevchenko +Reviewed-by: Qu Wenruo +Link: https://lore.kernel.org/r/20200803082706.65347-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Greg Kroah-Hartman + +--- + lib/kobject.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/lib/kobject.c ++++ b/lib/kobject.c +@@ -630,8 +630,12 @@ static void __kobject_del(struct kobject + */ + void kobject_del(struct kobject *kobj) + { +- struct kobject *parent = kobj->parent; ++ struct kobject *parent; + ++ if (!kobj) ++ return; ++ ++ parent = kobj->parent; + __kobject_del(kobj); + kobject_put(parent); + } diff --git a/queue-5.4/regulator-core-fix-slab-out-of-bounds-in-regulator_unlock_recursive.patch b/queue-5.4/regulator-core-fix-slab-out-of-bounds-in-regulator_unlock_recursive.patch new file mode 100644 index 00000000000..36d4af4d637 --- /dev/null +++ b/queue-5.4/regulator-core-fix-slab-out-of-bounds-in-regulator_unlock_recursive.patch @@ -0,0 +1,59 @@ +From 0a7416f94707c60b9f66b01c0a505b7e41375f3a Mon Sep 17 00:00:00 2001 +From: Dmitry Osipenko +Date: Mon, 31 Aug 2020 23:43:35 +0300 +Subject: regulator: core: Fix slab-out-of-bounds in regulator_unlock_recursive() + +From: Dmitry Osipenko + +commit 0a7416f94707c60b9f66b01c0a505b7e41375f3a upstream. + +The recent commit 7d8196641ee1 ("regulator: Remove pointer table +overallocation") changed the size of coupled_rdevs and now KASAN is able +to detect slab-out-of-bounds problem in regulator_unlock_recursive(), +which is a legit problem caused by a typo in the code. The recursive +unlock function uses n_coupled value of a parent regulator for unlocking +supply regulator, while supply's n_coupled should be used. In practice +problem may only affect platforms that use coupled regulators. + +Cc: stable@vger.kernel.org # 5.0+ +Fixes: f8702f9e4aa7 ("regulator: core: Use ww_mutex for regulators locking") +Signed-off-by: Dmitry Osipenko +Link: https://lore.kernel.org/r/20200831204335.19489-1-digetx@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/core.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -235,8 +235,8 @@ static bool regulator_supply_is_couple(s + static void regulator_unlock_recursive(struct regulator_dev *rdev, + unsigned int n_coupled) + { +- struct regulator_dev *c_rdev; +- int i; ++ struct regulator_dev *c_rdev, *supply_rdev; ++ int i, supply_n_coupled; + + for (i = n_coupled; i > 0; i--) { + c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1]; +@@ -244,10 +244,13 @@ static void regulator_unlock_recursive(s + if (!c_rdev) + continue; + +- if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) +- regulator_unlock_recursive( +- c_rdev->supply->rdev, +- c_rdev->coupling_desc.n_coupled); ++ if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) { ++ supply_rdev = c_rdev->supply->rdev; ++ supply_n_coupled = supply_rdev->coupling_desc.n_coupled; ++ ++ regulator_unlock_recursive(supply_rdev, ++ supply_n_coupled); ++ } + + regulator_unlock(c_rdev); + } diff --git a/queue-5.4/regulator-plug-of_node-leak-in-regulator_register-s-error-path.patch b/queue-5.4/regulator-plug-of_node-leak-in-regulator_register-s-error-path.patch new file mode 100644 index 00000000000..72f3b6b4368 --- /dev/null +++ b/queue-5.4/regulator-plug-of_node-leak-in-regulator_register-s-error-path.patch @@ -0,0 +1,85 @@ +From d3c731564e09b6c2ebefcd1344743a91a237d6dc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= +Date: Wed, 12 Aug 2020 03:31:36 +0200 +Subject: regulator: plug of_node leak in regulator_register()'s error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michał Mirosław + +commit d3c731564e09b6c2ebefcd1344743a91a237d6dc upstream. + +By calling device_initialize() earlier and noting that kfree(NULL) is +ok, we can save a bit of code in error handling and plug of_node leak. +Fixed commit already did part of the work. + +Fixes: 9177514ce349 ("regulator: fix memory leak on error path of regulator_register()") +Signed-off-by: Michał Mirosław +Reviewed-by: Vladimir Zapolskiy +Acked-by: Vladimir Zapolskiy +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/f5035b1b4d40745e66bacd571bbbb5e4644d21a1.1597195321.git.mirq-linux@rere.qmqm.pl +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/core.c | 13 ++++--------- + 1 file changed, 4 insertions(+), 9 deletions(-) + +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -5065,6 +5065,7 @@ regulator_register(const struct regulato + ret = -ENOMEM; + goto rinse; + } ++ device_initialize(&rdev->dev); + + /* + * Duplicate the config so the driver could override it after +@@ -5072,9 +5073,8 @@ regulator_register(const struct regulato + */ + config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); + if (config == NULL) { +- kfree(rdev); + ret = -ENOMEM; +- goto rinse; ++ goto clean; + } + + init_data = regulator_of_get_init_data(dev, regulator_desc, config, +@@ -5086,10 +5086,8 @@ regulator_register(const struct regulato + * from a gpio extender or something else. + */ + if (PTR_ERR(init_data) == -EPROBE_DEFER) { +- kfree(config); +- kfree(rdev); + ret = -EPROBE_DEFER; +- goto rinse; ++ goto clean; + } + + /* +@@ -5142,7 +5140,6 @@ regulator_register(const struct regulato + } + + /* register with sysfs */ +- device_initialize(&rdev->dev); + rdev->dev.class = ®ulator_class; + rdev->dev.parent = dev; + dev_set_name(&rdev->dev, "regulator.%lu", +@@ -5220,13 +5217,11 @@ wash: + mutex_lock(®ulator_list_mutex); + regulator_ena_gpio_free(rdev); + mutex_unlock(®ulator_list_mutex); +- put_device(&rdev->dev); +- rdev = NULL; + clean: + if (dangling_of_gpiod) + gpiod_put(config->ena_gpiod); +- kfree(rdev); + kfree(config); ++ put_device(&rdev->dev); + rinse: + if (dangling_cfg_gpiod) + gpiod_put(cfg->ena_gpiod); diff --git a/queue-5.4/regulator-push-allocation-in-regulator_init_coupling-outside-of-lock.patch b/queue-5.4/regulator-push-allocation-in-regulator_init_coupling-outside-of-lock.patch new file mode 100644 index 00000000000..592694b8b5b --- /dev/null +++ b/queue-5.4/regulator-push-allocation-in-regulator_init_coupling-outside-of-lock.patch @@ -0,0 +1,88 @@ +From 73a32129f8ccb556704a26b422f54e048bf14bd0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= +Date: Wed, 12 Aug 2020 03:31:34 +0200 +Subject: regulator: push allocation in regulator_init_coupling() outside of lock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michał Mirosław + +commit 73a32129f8ccb556704a26b422f54e048bf14bd0 upstream. + +Allocating memory with regulator_list_mutex held makes lockdep unhappy +when memory pressure makes the system do fs_reclaim on eg. eMMC using +a regulator. Push the lock inside regulator_init_coupling() after the +allocation. + +====================================================== +WARNING: possible circular locking dependency detected +5.7.13+ #533 Not tainted +------------------------------------------------------ +kswapd0/383 is trying to acquire lock: +cca78ca4 (&sbi->write_io[i][j].io_rwsem){++++}-{3:3}, at: __submit_merged_write_cond+0x104/0x154 +but task is already holding lock: +c0e38518 (fs_reclaim){+.+.}-{0:0}, at: __fs_reclaim_acquire+0x0/0x50 +which lock already depends on the new lock. +the existing dependency chain (in reverse order) is: +-> #2 (fs_reclaim){+.+.}-{0:0}: + fs_reclaim_acquire.part.11+0x40/0x50 + fs_reclaim_acquire+0x24/0x28 + __kmalloc+0x54/0x218 + regulator_register+0x860/0x1584 + dummy_regulator_probe+0x60/0xa8 +[...] +other info that might help us debug this: + +Chain exists of: + &sbi->write_io[i][j].io_rwsem --> regulator_list_mutex --> fs_reclaim + +Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + lock(fs_reclaim); + lock(regulator_list_mutex); + lock(fs_reclaim); + lock(&sbi->write_io[i][j].io_rwsem); + *** DEADLOCK *** + +1 lock held by kswapd0/383: + #0: c0e38518 (fs_reclaim){+.+.}-{0:0}, at: __fs_reclaim_acquire+0x0/0x50 +[...] + +Fixes: d8ca7d184b33 ("regulator: core: Introduce API for regulators coupling customization") +Signed-off-by: Michał Mirosław +Reviewed-by: Dmitry Osipenko +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/1a889cf7f61c6429c9e6b34ddcdde99be77a26b6.1597195321.git.mirq-linux@rere.qmqm.pl +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/core.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -4955,7 +4955,10 @@ static int regulator_init_coupling(struc + if (!of_check_coupling_data(rdev)) + return -EPERM; + ++ mutex_lock(®ulator_list_mutex); + rdev->coupling_desc.coupler = regulator_find_coupler(rdev); ++ mutex_unlock(®ulator_list_mutex); ++ + if (IS_ERR(rdev->coupling_desc.coupler)) { + err = PTR_ERR(rdev->coupling_desc.coupler); + rdev_err(rdev, "failed to get coupler: %d\n", err); +@@ -5155,9 +5158,7 @@ regulator_register(const struct regulato + if (ret < 0) + goto wash; + +- mutex_lock(®ulator_list_mutex); + ret = regulator_init_coupling(rdev); +- mutex_unlock(®ulator_list_mutex); + if (ret < 0) + goto wash; + diff --git a/queue-5.4/regulator-push-allocation-in-set_consumer_device_supply-out-of-lock.patch b/queue-5.4/regulator-push-allocation-in-set_consumer_device_supply-out-of-lock.patch new file mode 100644 index 00000000000..716d20358ac --- /dev/null +++ b/queue-5.4/regulator-push-allocation-in-set_consumer_device_supply-out-of-lock.patch @@ -0,0 +1,116 @@ +From 5c06540165d443c6455123eb48e7f1a9b618ab34 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= +Date: Wed, 12 Aug 2020 03:31:36 +0200 +Subject: regulator: push allocation in set_consumer_device_supply() out of lock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michał Mirosław + +commit 5c06540165d443c6455123eb48e7f1a9b618ab34 upstream. + +Pull regulator_list_mutex into set_consumer_device_supply() and keep +allocations outside of it. Fourth of the fs_reclaim deadlock case. + +Fixes: 45389c47526d ("regulator: core: Add early supply resolution for regulators") +Signed-off-by: Michał Mirosław +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/f0380bdb3d60aeefa9693c4e234d2dcda7e56747.1597195321.git.mirq-linux@rere.qmqm.pl +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/core.c | 46 ++++++++++++++++++++++++++-------------------- + 1 file changed, 26 insertions(+), 20 deletions(-) + +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1456,7 +1456,7 @@ static int set_consumer_device_supply(st + const char *consumer_dev_name, + const char *supply) + { +- struct regulator_map *node; ++ struct regulator_map *node, *new_node; + int has_dev; + + if (supply == NULL) +@@ -1467,6 +1467,22 @@ static int set_consumer_device_supply(st + else + has_dev = 0; + ++ new_node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); ++ if (new_node == NULL) ++ return -ENOMEM; ++ ++ new_node->regulator = rdev; ++ new_node->supply = supply; ++ ++ if (has_dev) { ++ new_node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); ++ if (new_node->dev_name == NULL) { ++ kfree(new_node); ++ return -ENOMEM; ++ } ++ } ++ ++ mutex_lock(®ulator_list_mutex); + list_for_each_entry(node, ®ulator_map_list, list) { + if (node->dev_name && consumer_dev_name) { + if (strcmp(node->dev_name, consumer_dev_name) != 0) +@@ -1484,26 +1500,19 @@ static int set_consumer_device_supply(st + node->regulator->desc->name, + supply, + dev_name(&rdev->dev), rdev_get_name(rdev)); +- return -EBUSY; ++ goto fail; + } + +- node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); +- if (node == NULL) +- return -ENOMEM; +- +- node->regulator = rdev; +- node->supply = supply; +- +- if (has_dev) { +- node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); +- if (node->dev_name == NULL) { +- kfree(node); +- return -ENOMEM; +- } +- } ++ list_add(&new_node->list, ®ulator_map_list); ++ mutex_unlock(®ulator_list_mutex); + +- list_add(&node->list, ®ulator_map_list); + return 0; ++ ++fail: ++ mutex_unlock(®ulator_list_mutex); ++ kfree(new_node->dev_name); ++ kfree(new_node); ++ return -EBUSY; + } + + static void unset_regulator_supplies(struct regulator_dev *rdev) +@@ -5167,19 +5176,16 @@ regulator_register(const struct regulato + + /* add consumers devices */ + if (init_data) { +- mutex_lock(®ulator_list_mutex); + for (i = 0; i < init_data->num_consumer_supplies; i++) { + ret = set_consumer_device_supply(rdev, + init_data->consumer_supplies[i].dev_name, + init_data->consumer_supplies[i].supply); + if (ret < 0) { +- mutex_unlock(®ulator_list_mutex); + dev_err(dev, "Failed to set supply %s\n", + init_data->consumer_supplies[i].supply); + goto unset_supplies; + } + } +- mutex_unlock(®ulator_list_mutex); + } + + if (!rdev->desc->ops->get_voltage && diff --git a/queue-5.4/regulator-push-allocations-in-create_regulator-outside-of-lock.patch b/queue-5.4/regulator-push-allocations-in-create_regulator-outside-of-lock.patch new file mode 100644 index 00000000000..852bd4e7c7d --- /dev/null +++ b/queue-5.4/regulator-push-allocations-in-create_regulator-outside-of-lock.patch @@ -0,0 +1,148 @@ +From 87fe29b61f9522a3d7b60a4580851f548558186f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= +Date: Wed, 12 Aug 2020 03:31:35 +0200 +Subject: regulator: push allocations in create_regulator() outside of lock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michał Mirosław + +commit 87fe29b61f9522a3d7b60a4580851f548558186f upstream. + +Move all allocations outside of the regulator_lock()ed section. + +====================================================== +WARNING: possible circular locking dependency detected +5.7.13+ #535 Not tainted +------------------------------------------------------ +f2fs_discard-179:7/702 is trying to acquire lock: +c0e5d920 (regulator_list_mutex){+.+.}-{3:3}, at: regulator_lock_dependent+0x54/0x2c0 + +but task is already holding lock: +cb95b080 (&dcc->cmd_lock){+.+.}-{3:3}, at: __issue_discard_cmd+0xec/0x5f8 + +which lock already depends on the new lock. + +the existing dependency chain (in reverse order) is: + +[...] + +-> #3 (fs_reclaim){+.+.}-{0:0}: + fs_reclaim_acquire.part.11+0x40/0x50 + fs_reclaim_acquire+0x24/0x28 + __kmalloc_track_caller+0x54/0x218 + kstrdup+0x40/0x5c + create_regulator+0xf4/0x368 + regulator_resolve_supply+0x1a0/0x200 + regulator_register+0x9c8/0x163c + +[...] + +other info that might help us debug this: + +Chain exists of: + regulator_list_mutex --> &sit_i->sentry_lock --> &dcc->cmd_lock + +[...] + +Fixes: f8702f9e4aa7 ("regulator: core: Use ww_mutex for regulators locking") +Signed-off-by: Michał Mirosław +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/6eebc99b2474f4ffaa0405b15178ece0e7e4f608.1597195321.git.mirq-linux@rere.qmqm.pl +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/core.c | 53 ++++++++++++++++++++++++----------------------- + 1 file changed, 28 insertions(+), 25 deletions(-) + +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1575,44 +1575,53 @@ static struct regulator *create_regulato + const char *supply_name) + { + struct regulator *regulator; +- char buf[REG_STR_SIZE]; +- int err, size; ++ int err; ++ ++ if (dev) { ++ char buf[REG_STR_SIZE]; ++ int size; ++ ++ size = snprintf(buf, REG_STR_SIZE, "%s-%s", ++ dev->kobj.name, supply_name); ++ if (size >= REG_STR_SIZE) ++ return NULL; ++ ++ supply_name = kstrdup(buf, GFP_KERNEL); ++ if (supply_name == NULL) ++ return NULL; ++ } else { ++ supply_name = kstrdup_const(supply_name, GFP_KERNEL); ++ if (supply_name == NULL) ++ return NULL; ++ } + + regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); +- if (regulator == NULL) ++ if (regulator == NULL) { ++ kfree(supply_name); + return NULL; ++ } + +- regulator_lock(rdev); + regulator->rdev = rdev; ++ regulator->supply_name = supply_name; ++ ++ regulator_lock(rdev); + list_add(®ulator->list, &rdev->consumer_list); ++ regulator_unlock(rdev); + + if (dev) { + regulator->dev = dev; + + /* Add a link to the device sysfs entry */ +- size = snprintf(buf, REG_STR_SIZE, "%s-%s", +- dev->kobj.name, supply_name); +- if (size >= REG_STR_SIZE) +- goto overflow_err; +- +- regulator->supply_name = kstrdup(buf, GFP_KERNEL); +- if (regulator->supply_name == NULL) +- goto overflow_err; +- + err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, +- buf); ++ supply_name); + if (err) { + rdev_dbg(rdev, "could not add device link %s err %d\n", + dev->kobj.name, err); + /* non-fatal */ + } +- } else { +- regulator->supply_name = kstrdup_const(supply_name, GFP_KERNEL); +- if (regulator->supply_name == NULL) +- goto overflow_err; + } + +- regulator->debugfs = debugfs_create_dir(regulator->supply_name, ++ regulator->debugfs = debugfs_create_dir(supply_name, + rdev->debugfs); + if (!regulator->debugfs) { + rdev_dbg(rdev, "Failed to create debugfs directory\n"); +@@ -1637,13 +1646,7 @@ static struct regulator *create_regulato + _regulator_is_enabled(rdev)) + regulator->always_on = true; + +- regulator_unlock(rdev); + return regulator; +-overflow_err: +- list_del(®ulator->list); +- kfree(regulator); +- regulator_unlock(rdev); +- return NULL; + } + + static int _regulator_get_enable_time(struct regulator_dev *rdev) diff --git a/queue-5.4/scsi-target-iscsi-fix-data-digest-calculation.patch b/queue-5.4/scsi-target-iscsi-fix-data-digest-calculation.patch new file mode 100644 index 00000000000..c35abbca465 --- /dev/null +++ b/queue-5.4/scsi-target-iscsi-fix-data-digest-calculation.patch @@ -0,0 +1,57 @@ +From 5528d03183fe5243416c706f64b1faa518b05130 Mon Sep 17 00:00:00 2001 +From: Varun Prakash +Date: Tue, 25 Aug 2020 18:05:10 +0530 +Subject: scsi: target: iscsi: Fix data digest calculation + +From: Varun Prakash + +commit 5528d03183fe5243416c706f64b1faa518b05130 upstream. + +Current code does not consider 'page_off' in data digest calculation. To +fix this, add a local variable 'first_sg' and set first_sg.offset to +sg->offset + page_off. + +Link: https://lore.kernel.org/r/1598358910-3052-1-git-send-email-varun@chelsio.com +Fixes: e48354ce078c ("iscsi-target: Add iSCSI fabric support for target v4.1") +Cc: +Reviewed-by: Mike Christie +Signed-off-by: Varun Prakash +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -1386,14 +1386,27 @@ static u32 iscsit_do_crypto_hash_sg( + sg = cmd->first_data_sg; + page_off = cmd->first_data_sg_off; + ++ if (data_length && page_off) { ++ struct scatterlist first_sg; ++ u32 len = min_t(u32, data_length, sg->length - page_off); ++ ++ sg_init_table(&first_sg, 1); ++ sg_set_page(&first_sg, sg_page(sg), len, sg->offset + page_off); ++ ++ ahash_request_set_crypt(hash, &first_sg, NULL, len); ++ crypto_ahash_update(hash); ++ ++ data_length -= len; ++ sg = sg_next(sg); ++ } ++ + while (data_length) { +- u32 cur_len = min_t(u32, data_length, (sg->length - page_off)); ++ u32 cur_len = min_t(u32, data_length, sg->length); + + ahash_request_set_crypt(hash, sg, NULL, cur_len); + crypto_ahash_update(hash); + + data_length -= cur_len; +- page_off = 0; + /* iscsit_map_iovec has already checked for invalid sg pointers */ + sg = sg_next(sg); + } diff --git a/queue-5.4/scsi-target-iscsi-fix-hang-in-iscsit_access_np-when-getting-tpg-np_login_sem.patch b/queue-5.4/scsi-target-iscsi-fix-hang-in-iscsit_access_np-when-getting-tpg-np_login_sem.patch new file mode 100644 index 00000000000..bb3706ccf59 --- /dev/null +++ b/queue-5.4/scsi-target-iscsi-fix-hang-in-iscsit_access_np-when-getting-tpg-np_login_sem.patch @@ -0,0 +1,117 @@ +From ed43ffea78dcc97db3f561da834f1a49c8961e33 Mon Sep 17 00:00:00 2001 +From: Hou Pu +Date: Wed, 29 Jul 2020 09:03:43 -0400 +Subject: scsi: target: iscsi: Fix hang in iscsit_access_np() when getting tpg->np_login_sem + +From: Hou Pu + +commit ed43ffea78dcc97db3f561da834f1a49c8961e33 upstream. + +The iSCSI target login thread might get stuck with the following stack: + +cat /proc/`pidof iscsi_np`/stack +[<0>] down_interruptible+0x42/0x50 +[<0>] iscsit_access_np+0xe3/0x167 +[<0>] iscsi_target_locate_portal+0x695/0x8ac +[<0>] __iscsi_target_login_thread+0x855/0xb82 +[<0>] iscsi_target_login_thread+0x2f/0x5a +[<0>] kthread+0xfa/0x130 +[<0>] ret_from_fork+0x1f/0x30 + +This can be reproduced via the following steps: + +1. Initiator A tries to log in to iqn1-tpg1 on port 3260. After finishing + PDU exchange in the login thread and before the negotiation is finished + the the network link goes down. At this point A has not finished login + and tpg->np_login_sem is held. + +2. Initiator B tries to log in to iqn2-tpg1 on port 3260. After finishing + PDU exchange in the login thread the target expects to process remaining + login PDUs in workqueue context. + +3. Initiator A' tries to log in to iqn1-tpg1 on port 3260 from a new + socket. A' will wait for tpg->np_login_sem with np->np_login_timer + loaded to wait for at most 15 seconds. The lock is held by A so A' + eventually times out. + +4. Before A' got timeout initiator B gets negotiation failed and calls + iscsi_target_login_drop()->iscsi_target_login_sess_out(). The + np->np_login_timer is canceled and initiator A' will hang forever. + Because A' is now in the login thread, no new login requests can be + serviced. + +Fix this by moving iscsi_stop_login_thread_timer() out of +iscsi_target_login_sess_out(). Also remove iscsi_np parameter from +iscsi_target_login_sess_out(). + +Link: https://lore.kernel.org/r/20200729130343.24976-1-houpu@bytedance.com +Cc: stable@vger.kernel.org +Reviewed-by: Mike Christie +Signed-off-by: Hou Pu +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target_login.c | 6 +++--- + drivers/target/iscsi/iscsi_target_login.h | 3 +-- + drivers/target/iscsi/iscsi_target_nego.c | 3 +-- + 3 files changed, 5 insertions(+), 7 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target_login.c ++++ b/drivers/target/iscsi/iscsi_target_login.c +@@ -1172,7 +1172,7 @@ void iscsit_free_conn(struct iscsi_conn + } + + void iscsi_target_login_sess_out(struct iscsi_conn *conn, +- struct iscsi_np *np, bool zero_tsih, bool new_sess) ++ bool zero_tsih, bool new_sess) + { + if (!new_sess) + goto old_sess_out; +@@ -1190,7 +1190,6 @@ void iscsi_target_login_sess_out(struct + conn->sess = NULL; + + old_sess_out: +- iscsi_stop_login_thread_timer(np); + /* + * If login negotiation fails check if the Time2Retain timer + * needs to be restarted. +@@ -1430,8 +1429,9 @@ static int __iscsi_target_login_thread(s + new_sess_out: + new_sess = true; + old_sess_out: ++ iscsi_stop_login_thread_timer(np); + tpg_np = conn->tpg_np; +- iscsi_target_login_sess_out(conn, np, zero_tsih, new_sess); ++ iscsi_target_login_sess_out(conn, zero_tsih, new_sess); + new_sess = false; + + if (tpg) { +--- a/drivers/target/iscsi/iscsi_target_login.h ++++ b/drivers/target/iscsi/iscsi_target_login.h +@@ -22,8 +22,7 @@ extern int iscsit_put_login_tx(struct is + extern void iscsit_free_conn(struct iscsi_conn *); + extern int iscsit_start_kthreads(struct iscsi_conn *); + extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8); +-extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *, +- bool, bool); ++extern void iscsi_target_login_sess_out(struct iscsi_conn *, bool, bool); + extern int iscsi_target_login_thread(void *); + extern void iscsi_handle_login_thread_timeout(struct timer_list *t); + +--- a/drivers/target/iscsi/iscsi_target_nego.c ++++ b/drivers/target/iscsi/iscsi_target_nego.c +@@ -535,12 +535,11 @@ static bool iscsi_target_sk_check_and_cl + + static void iscsi_target_login_drop(struct iscsi_conn *conn, struct iscsi_login *login) + { +- struct iscsi_np *np = login->np; + bool zero_tsih = login->zero_tsih; + + iscsi_remove_failed_auth_entry(conn); + iscsi_target_nego_release(conn); +- iscsi_target_login_sess_out(conn, np, zero_tsih, true); ++ iscsi_target_login_sess_out(conn, zero_tsih, true); + } + + struct conn_timeout { diff --git a/queue-5.4/series b/queue-5.4/series index 9225d97921a..a9e42a3f623 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -88,3 +88,15 @@ iio-accel-kxsd9-fix-alignment-of-local-buffer.patch iio-accel-mma7455-fix-timestamp-alignment-and-prevent-data-leak.patch iio-accel-mma8452-fix-timestamp-alignment-and-prevent-data-leak.patch staging-wlan-ng-fix-out-of-bounds-read-in-prism2sta_probe_usb.patch +btrfs-require-only-sector-size-alignment-for-parent-eb-bytenr.patch +btrfs-fix-lockdep-splat-in-add_missing_dev.patch +btrfs-fix-wrong-address-when-faulting-in-pages-in-the-search-ioctl.patch +firmware_loader-fix-memory-leak-for-paged-buffer.patch +kobject-restore-old-behaviour-of-kobject_del-null.patch +regulator-push-allocation-in-regulator_init_coupling-outside-of-lock.patch +regulator-push-allocations-in-create_regulator-outside-of-lock.patch +regulator-push-allocation-in-set_consumer_device_supply-out-of-lock.patch +regulator-plug-of_node-leak-in-regulator_register-s-error-path.patch +regulator-core-fix-slab-out-of-bounds-in-regulator_unlock_recursive.patch +scsi-target-iscsi-fix-data-digest-calculation.patch +scsi-target-iscsi-fix-hang-in-iscsit_access_np-when-getting-tpg-np_login_sem.patch