]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 15 Sep 2020 07:37:14 +0000 (09:37 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 15 Sep 2020 07:37:14 +0000 (09:37 +0200)
added patches:
btrfs-fix-wrong-address-when-faulting-in-pages-in-the-search-ioctl.patch
regulator-push-allocation-in-set_consumer_device_supply-out-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

queue-4.9/btrfs-fix-wrong-address-when-faulting-in-pages-in-the-search-ioctl.patch [new file with mode: 0644]
queue-4.9/regulator-push-allocation-in-set_consumer_device_supply-out-of-lock.patch [new file with mode: 0644]
queue-4.9/scsi-target-iscsi-fix-data-digest-calculation.patch [new file with mode: 0644]
queue-4.9/scsi-target-iscsi-fix-hang-in-iscsit_access_np-when-getting-tpg-np_login_sem.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/btrfs-fix-wrong-address-when-faulting-in-pages-in-the-search-ioctl.patch b/queue-4.9/btrfs-fix-wrong-address-when-faulting-in-pages-in-the-search-ioctl.patch
new file mode 100644 (file)
index 0000000..846f0d8
--- /dev/null
@@ -0,0 +1,51 @@
+From 1c78544eaa4660096aeb6a57ec82b42cdb3bfe5a Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+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 <fdmanana@suse.com>
+
+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 <mail@lechevalier.se>
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/ioctl.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -2151,7 +2151,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-4.9/regulator-push-allocation-in-set_consumer_device_supply-out-of-lock.patch b/queue-4.9/regulator-push-allocation-in-set_consumer_device_supply-out-of-lock.patch
new file mode 100644 (file)
index 0000000..3a0fe82
--- /dev/null
@@ -0,0 +1,116 @@
+From 5c06540165d443c6455123eb48e7f1a9b618ab34 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= <mirq-linux@rere.qmqm.pl>
+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 <mirq-linux@rere.qmqm.pl>
+
+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 <mirq-linux@rere.qmqm.pl>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/f0380bdb3d60aeefa9693c4e234d2dcda7e56747.1597195321.git.mirq-linux@rere.qmqm.pl
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/regulator/core.c |   46 ++++++++++++++++++++++++++--------------------
+ 1 file changed, 26 insertions(+), 20 deletions(-)
+
+--- a/drivers/regulator/core.c
++++ b/drivers/regulator/core.c
+@@ -1191,7 +1191,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)
+@@ -1202,6 +1202,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(&regulator_list_mutex);
+       list_for_each_entry(node, &regulator_map_list, list) {
+               if (node->dev_name && consumer_dev_name) {
+                       if (strcmp(node->dev_name, consumer_dev_name) != 0)
+@@ -1219,26 +1235,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, &regulator_map_list);
++      mutex_unlock(&regulator_list_mutex);
+-      list_add(&node->list, &regulator_map_list);
+       return 0;
++
++fail:
++      mutex_unlock(&regulator_list_mutex);
++      kfree(new_node->dev_name);
++      kfree(new_node);
++      return -EBUSY;
+ }
+ static void unset_regulator_supplies(struct regulator_dev *rdev)
+@@ -4034,19 +4043,16 @@ regulator_register(const struct regulato
+       /* add consumers devices */
+       if (init_data) {
+-              mutex_lock(&regulator_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(&regulator_list_mutex);
+                               dev_err(dev, "Failed to set supply %s\n",
+                                       init_data->consumer_supplies[i].supply);
+                               goto unset_supplies;
+                       }
+               }
+-              mutex_unlock(&regulator_list_mutex);
+       }
+       if (!rdev->desc->ops->get_voltage &&
diff --git a/queue-4.9/scsi-target-iscsi-fix-data-digest-calculation.patch b/queue-4.9/scsi-target-iscsi-fix-data-digest-calculation.patch
new file mode 100644 (file)
index 0000000..35adcef
--- /dev/null
@@ -0,0 +1,57 @@
+From 5528d03183fe5243416c706f64b1faa518b05130 Mon Sep 17 00:00:00 2001
+From: Varun Prakash <varun@chelsio.com>
+Date: Tue, 25 Aug 2020 18:05:10 +0530
+Subject: scsi: target: iscsi: Fix data digest calculation
+
+From: Varun Prakash <varun@chelsio.com>
+
+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: <stable@vger.kernel.org>
+Reviewed-by: Mike Christie <michael.christie@oralce.com>
+Signed-off-by: Varun Prakash <varun@chelsio.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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
+@@ -1396,14 +1396,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-4.9/scsi-target-iscsi-fix-hang-in-iscsit_access_np-when-getting-tpg-np_login_sem.patch b/queue-4.9/scsi-target-iscsi-fix-hang-in-iscsit_access_np-when-getting-tpg-np_login_sem.patch
new file mode 100644 (file)
index 0000000..5de896e
--- /dev/null
@@ -0,0 +1,117 @@
+From ed43ffea78dcc97db3f561da834f1a49c8961e33 Mon Sep 17 00:00:00 2001
+From: Hou Pu <houpu@bytedance.com>
+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 <houpu@bytedance.com>
+
+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 <michael.christie@oracle.com>
+Signed-off-by: Hou Pu <houpu@bytedance.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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
+@@ -1150,7 +1150,7 @@ iscsit_conn_set_transport(struct iscsi_c
+ }
+ 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;
+@@ -1172,7 +1172,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.
+@@ -1432,8 +1431,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
+@@ -14,8 +14,7 @@ extern int iscsit_put_login_tx(struct is
+ extern void iscsit_free_conn(struct iscsi_np *, 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 *);
+ #endif   /*** ISCSI_TARGET_LOGIN_H ***/
+--- a/drivers/target/iscsi/iscsi_target_nego.c
++++ b/drivers/target/iscsi/iscsi_target_nego.c
+@@ -548,12 +548,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);
+ }
+ static void iscsi_target_login_timeout(unsigned long data)
index 7547020d6cf73ae0cb35699e987eeff614962fb6..303b372c7924ffd4ff2421c6f16f0f16231f9c5b 100644 (file)
@@ -27,3 +27,7 @@ iio-accel-mma7455-fix-timestamp-alignment-and-prevent-data-leak.patch
 iio-accel-mma8452-fix-timestamp-alignment-and-prevent-data-leak.patch
 usb-core-add-helpers-to-retrieve-endpoints.patch
 staging-wlan-ng-fix-out-of-bounds-read-in-prism2sta_probe_usb.patch
+btrfs-fix-wrong-address-when-faulting-in-pages-in-the-search-ioctl.patch
+regulator-push-allocation-in-set_consumer_device_supply-out-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