]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.8-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2024 08:52:51 +0000 (10:52 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Apr 2024 08:52:51 +0000 (10:52 +0200)
added patches:
scsi-core-fix-unremoved-procfs-host-directory-regression.patch
scsi-sd-fix-tcg-opal-unlock-on-system-resume.patch
scsi-sg-avoid-sg-device-teardown-race.patch
scsi-ufs-qcom-provide-default-cycles_in_1us-value.patch

queue-6.8/scsi-core-fix-unremoved-procfs-host-directory-regression.patch [new file with mode: 0644]
queue-6.8/scsi-sd-fix-tcg-opal-unlock-on-system-resume.patch [new file with mode: 0644]
queue-6.8/scsi-sg-avoid-sg-device-teardown-race.patch [new file with mode: 0644]
queue-6.8/scsi-ufs-qcom-provide-default-cycles_in_1us-value.patch [new file with mode: 0644]
queue-6.8/series

diff --git a/queue-6.8/scsi-core-fix-unremoved-procfs-host-directory-regression.patch b/queue-6.8/scsi-core-fix-unremoved-procfs-host-directory-regression.patch
new file mode 100644 (file)
index 0000000..376c384
--- /dev/null
@@ -0,0 +1,80 @@
+From f23a4d6e07570826fe95023ca1aa96a011fa9f84 Mon Sep 17 00:00:00 2001
+From: "Guilherme G. Piccoli" <gpiccoli@igalia.com>
+Date: Wed, 13 Mar 2024 08:21:20 -0300
+Subject: scsi: core: Fix unremoved procfs host directory regression
+
+From: Guilherme G. Piccoli <gpiccoli@igalia.com>
+
+commit f23a4d6e07570826fe95023ca1aa96a011fa9f84 upstream.
+
+Commit fc663711b944 ("scsi: core: Remove the /proc/scsi/${proc_name}
+directory earlier") fixed a bug related to modules loading/unloading, by
+adding a call to scsi_proc_hostdir_rm() on scsi_remove_host(). But that led
+to a potential duplicate call to the hostdir_rm() routine, since it's also
+called from scsi_host_dev_release(). That triggered a regression report,
+which was then fixed by commit be03df3d4bfe ("scsi: core: Fix a procfs host
+directory removal regression"). The fix just dropped the hostdir_rm() call
+from dev_release().
+
+But it happens that this proc directory is created on scsi_host_alloc(),
+and that function "pairs" with scsi_host_dev_release(), while
+scsi_remove_host() pairs with scsi_add_host(). In other words, it seems the
+reason for removing the proc directory on dev_release() was meant to cover
+cases in which a SCSI host structure was allocated, but the call to
+scsi_add_host() didn't happen. And that pattern happens to exist in some
+error paths, for example.
+
+Syzkaller causes that by using USB raw gadget device, error'ing on
+usb-storage driver, at usb_stor_probe2(). By checking that path, we can see
+that the BadDevice label leads to a scsi_host_put() after a SCSI host
+allocation, but there's no call to scsi_add_host() in such path. That leads
+to messages like this in dmesg (and a leak of the SCSI host proc
+structure):
+
+usb-storage 4-1:87.51: USB Mass Storage device detected
+proc_dir_entry 'scsi/usb-storage' already registered
+WARNING: CPU: 1 PID: 3519 at fs/proc/generic.c:377 proc_register+0x347/0x4e0 fs/proc/generic.c:376
+
+The proper fix seems to still call scsi_proc_hostdir_rm() on dev_release(),
+but guard that with the state check for SHOST_CREATED; there is even a
+comment in scsi_host_dev_release() detailing that: such conditional is
+meant for cases where the SCSI host was allocated but there was no calls to
+{add,remove}_host(), like the usb-storage case.
+
+This is what we propose here and with that, the error path of usb-storage
+does not trigger the warning anymore.
+
+Reported-by: syzbot+c645abf505ed21f931b5@syzkaller.appspotmail.com
+Fixes: be03df3d4bfe ("scsi: core: Fix a procfs host directory removal regression")
+Cc: stable@vger.kernel.org
+Cc: Bart Van Assche <bvanassche@acm.org>
+Cc: John Garry <john.g.garry@oracle.com>
+Cc: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
+Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
+Link: https://lore.kernel.org/r/20240313113006.2834799-1-gpiccoli@igalia.com
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/hosts.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/scsi/hosts.c
++++ b/drivers/scsi/hosts.c
+@@ -353,12 +353,13 @@ static void scsi_host_dev_release(struct
+       if (shost->shost_state == SHOST_CREATED) {
+               /*
+-               * Free the shost_dev device name here if scsi_host_alloc()
+-               * and scsi_host_put() have been called but neither
++               * Free the shost_dev device name and remove the proc host dir
++               * here if scsi_host_{alloc,put}() have been called but neither
+                * scsi_host_add() nor scsi_remove_host() has been called.
+                * This avoids that the memory allocated for the shost_dev
+-               * name is leaked.
++               * name as well as the proc dir structure are leaked.
+                */
++              scsi_proc_hostdir_rm(shost->hostt);
+               kfree(dev_name(&shost->shost_dev));
+       }
diff --git a/queue-6.8/scsi-sd-fix-tcg-opal-unlock-on-system-resume.patch b/queue-6.8/scsi-sd-fix-tcg-opal-unlock-on-system-resume.patch
new file mode 100644 (file)
index 0000000..b10240d
--- /dev/null
@@ -0,0 +1,230 @@
+From 0c76106cb97548810214def8ee22700bbbb90543 Mon Sep 17 00:00:00 2001
+From: Damien Le Moal <dlemoal@kernel.org>
+Date: Tue, 19 Mar 2024 16:12:09 +0900
+Subject: scsi: sd: Fix TCG OPAL unlock on system resume
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+commit 0c76106cb97548810214def8ee22700bbbb90543 upstream.
+
+Commit 3cc2ffe5c16d ("scsi: sd: Differentiate system and runtime start/stop
+management") introduced the manage_system_start_stop scsi_device flag to
+allow libata to indicate to the SCSI disk driver that nothing should be
+done when resuming a disk on system resume. This change turned the
+execution of sd_resume() into a no-op for ATA devices on system
+resume. While this solved deadlock issues during device resume, this change
+also wrongly removed the execution of opal_unlock_from_suspend().  As a
+result, devices with TCG OPAL locking enabled remain locked and
+inaccessible after a system resume from sleep.
+
+To fix this issue, introduce the SCSI driver resume method and implement it
+with the sd_resume() function calling opal_unlock_from_suspend(). The
+former sd_resume() function is renamed to sd_resume_common() and modified
+to call the new sd_resume() function. For non-ATA devices, this result in
+no functional changes.
+
+In order for libata to explicitly execute sd_resume() when a device is
+resumed during system restart, the function scsi_resume_device() is
+introduced. libata calls this function from the revalidation work executed
+on devie resume, a state that is indicated with the new device flag
+ATA_DFLAG_RESUMING. Doing so, locked TCG OPAL enabled devices are unlocked
+on resume, allowing normal operation.
+
+Fixes: 3cc2ffe5c16d ("scsi: sd: Differentiate system and runtime start/stop management")
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=218538
+Cc: stable@vger.kernel.org
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Link: https://lore.kernel.org/r/20240319071209.1179257-1-dlemoal@kernel.org
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/ata/libata-eh.c    |    5 ++++-
+ drivers/ata/libata-scsi.c  |    9 +++++++++
+ drivers/scsi/scsi_scan.c   |   34 ++++++++++++++++++++++++++++++++++
+ drivers/scsi/sd.c          |   23 +++++++++++++++++++----
+ include/linux/libata.h     |    1 +
+ include/scsi/scsi_driver.h |    1 +
+ include/scsi/scsi_host.h   |    1 +
+ 7 files changed, 69 insertions(+), 5 deletions(-)
+
+--- a/drivers/ata/libata-eh.c
++++ b/drivers/ata/libata-eh.c
+@@ -712,8 +712,10 @@ void ata_scsi_port_error_handler(struct
+                               ehc->saved_ncq_enabled |= 1 << devno;
+                       /* If we are resuming, wake up the device */
+-                      if (ap->pflags & ATA_PFLAG_RESUMING)
++                      if (ap->pflags & ATA_PFLAG_RESUMING) {
++                              dev->flags |= ATA_DFLAG_RESUMING;
+                               ehc->i.dev_action[devno] |= ATA_EH_SET_ACTIVE;
++                      }
+               }
+       }
+@@ -3169,6 +3171,7 @@ static int ata_eh_revalidate_and_attach(
+       return 0;
+  err:
++      dev->flags &= ~ATA_DFLAG_RESUMING;
+       *r_failed_dev = dev;
+       return rc;
+ }
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -4730,6 +4730,7 @@ void ata_scsi_dev_rescan(struct work_str
+       struct ata_link *link;
+       struct ata_device *dev;
+       unsigned long flags;
++      bool do_resume;
+       int ret = 0;
+       mutex_lock(&ap->scsi_scan_mutex);
+@@ -4751,7 +4752,15 @@ void ata_scsi_dev_rescan(struct work_str
+                       if (scsi_device_get(sdev))
+                               continue;
++                      do_resume = dev->flags & ATA_DFLAG_RESUMING;
++
+                       spin_unlock_irqrestore(ap->lock, flags);
++                      if (do_resume) {
++                              ret = scsi_resume_device(sdev);
++                              if (ret == -EWOULDBLOCK)
++                                      goto unlock;
++                              dev->flags &= ~ATA_DFLAG_RESUMING;
++                      }
+                       ret = scsi_rescan_device(sdev);
+                       scsi_device_put(sdev);
+                       spin_lock_irqsave(ap->lock, flags);
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -1619,6 +1619,40 @@ int scsi_add_device(struct Scsi_Host *ho
+ }
+ EXPORT_SYMBOL(scsi_add_device);
++int scsi_resume_device(struct scsi_device *sdev)
++{
++      struct device *dev = &sdev->sdev_gendev;
++      int ret = 0;
++
++      device_lock(dev);
++
++      /*
++       * Bail out if the device or its queue are not running. Otherwise,
++       * the rescan may block waiting for commands to be executed, with us
++       * holding the device lock. This can result in a potential deadlock
++       * in the power management core code when system resume is on-going.
++       */
++      if (sdev->sdev_state != SDEV_RUNNING ||
++          blk_queue_pm_only(sdev->request_queue)) {
++              ret = -EWOULDBLOCK;
++              goto unlock;
++      }
++
++      if (dev->driver && try_module_get(dev->driver->owner)) {
++              struct scsi_driver *drv = to_scsi_driver(dev->driver);
++
++              if (drv->resume)
++                      ret = drv->resume(dev);
++              module_put(dev->driver->owner);
++      }
++
++unlock:
++      device_unlock(dev);
++
++      return ret;
++}
++EXPORT_SYMBOL(scsi_resume_device);
++
+ int scsi_rescan_device(struct scsi_device *sdev)
+ {
+       struct device *dev = &sdev->sdev_gendev;
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -3945,7 +3945,21 @@ static int sd_suspend_runtime(struct dev
+       return sd_suspend_common(dev, true);
+ }
+-static int sd_resume(struct device *dev, bool runtime)
++static int sd_resume(struct device *dev)
++{
++      struct scsi_disk *sdkp = dev_get_drvdata(dev);
++
++      sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
++
++      if (opal_unlock_from_suspend(sdkp->opal_dev)) {
++              sd_printk(KERN_NOTICE, sdkp, "OPAL unlock failed\n");
++              return -EIO;
++      }
++
++      return 0;
++}
++
++static int sd_resume_common(struct device *dev, bool runtime)
+ {
+       struct scsi_disk *sdkp = dev_get_drvdata(dev);
+       int ret;
+@@ -3961,7 +3975,7 @@ static int sd_resume(struct device *dev,
+       sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
+       ret = sd_start_stop_device(sdkp, 1);
+       if (!ret) {
+-              opal_unlock_from_suspend(sdkp->opal_dev);
++              sd_resume(dev);
+               sdkp->suspended = false;
+       }
+@@ -3980,7 +3994,7 @@ static int sd_resume_system(struct devic
+               return 0;
+       }
+-      return sd_resume(dev, false);
++      return sd_resume_common(dev, false);
+ }
+ static int sd_resume_runtime(struct device *dev)
+@@ -4007,7 +4021,7 @@ static int sd_resume_runtime(struct devi
+                                 "Failed to clear sense data\n");
+       }
+-      return sd_resume(dev, true);
++      return sd_resume_common(dev, true);
+ }
+ static const struct dev_pm_ops sd_pm_ops = {
+@@ -4030,6 +4044,7 @@ static struct scsi_driver sd_template =
+               .pm             = &sd_pm_ops,
+       },
+       .rescan                 = sd_rescan,
++      .resume                 = sd_resume,
+       .init_command           = sd_init_command,
+       .uninit_command         = sd_uninit_command,
+       .done                   = sd_done,
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -107,6 +107,7 @@ enum {
+       ATA_DFLAG_NCQ_PRIO_ENABLED = (1 << 20), /* Priority cmds sent to dev */
+       ATA_DFLAG_CDL_ENABLED   = (1 << 21), /* cmd duration limits is enabled */
++      ATA_DFLAG_RESUMING      = (1 << 22),  /* Device is resuming */
+       ATA_DFLAG_DETACH        = (1 << 24),
+       ATA_DFLAG_DETACHED      = (1 << 25),
+       ATA_DFLAG_DA            = (1 << 26), /* device supports Device Attention */
+--- a/include/scsi/scsi_driver.h
++++ b/include/scsi/scsi_driver.h
+@@ -12,6 +12,7 @@ struct request;
+ struct scsi_driver {
+       struct device_driver    gendrv;
++      int (*resume)(struct device *);
+       void (*rescan)(struct device *);
+       blk_status_t (*init_command)(struct scsi_cmnd *);
+       void (*uninit_command)(struct scsi_cmnd *);
+--- a/include/scsi/scsi_host.h
++++ b/include/scsi/scsi_host.h
+@@ -767,6 +767,7 @@ scsi_template_proc_dir(const struct scsi
+ #define scsi_template_proc_dir(sht) NULL
+ #endif
+ extern void scsi_scan_host(struct Scsi_Host *);
++extern int scsi_resume_device(struct scsi_device *sdev);
+ extern int scsi_rescan_device(struct scsi_device *sdev);
+ extern void scsi_remove_host(struct Scsi_Host *);
+ extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *);
diff --git a/queue-6.8/scsi-sg-avoid-sg-device-teardown-race.patch b/queue-6.8/scsi-sg-avoid-sg-device-teardown-race.patch
new file mode 100644 (file)
index 0000000..940437e
--- /dev/null
@@ -0,0 +1,51 @@
+From 27f58c04a8f438078583041468ec60597841284d Mon Sep 17 00:00:00 2001
+From: Alexander Wetzel <Alexander@wetzel-home.de>
+Date: Wed, 20 Mar 2024 22:30:32 +0100
+Subject: scsi: sg: Avoid sg device teardown race
+
+From: Alexander Wetzel <Alexander@wetzel-home.de>
+
+commit 27f58c04a8f438078583041468ec60597841284d upstream.
+
+sg_remove_sfp_usercontext() must not use sg_device_destroy() after calling
+scsi_device_put().
+
+sg_device_destroy() is accessing the parent scsi_device request_queue which
+will already be set to NULL when the preceding call to scsi_device_put()
+removed the last reference to the parent scsi_device.
+
+The resulting NULL pointer exception will then crash the kernel.
+
+Link: https://lore.kernel.org/r/20240305150509.23896-1-Alexander@wetzel-home.de
+Fixes: db59133e9279 ("scsi: sg: fix blktrace debugfs entries leakage")
+Cc: stable@vger.kernel.org
+Signed-off-by: Alexander Wetzel <Alexander@wetzel-home.de>
+Link: https://lore.kernel.org/r/20240320213032.18221-1-Alexander@wetzel-home.de
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/sg.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -2207,6 +2207,7 @@ sg_remove_sfp_usercontext(struct work_st
+ {
+       struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work);
+       struct sg_device *sdp = sfp->parentdp;
++      struct scsi_device *device = sdp->device;
+       Sg_request *srp;
+       unsigned long iflags;
+@@ -2232,8 +2233,9 @@ sg_remove_sfp_usercontext(struct work_st
+                       "sg_remove_sfp: sfp=0x%p\n", sfp));
+       kfree(sfp);
+-      scsi_device_put(sdp->device);
++      WARN_ON_ONCE(kref_read(&sdp->d_ref) != 1);
+       kref_put(&sdp->d_ref, sg_device_destroy);
++      scsi_device_put(device);
+       module_put(THIS_MODULE);
+ }
diff --git a/queue-6.8/scsi-ufs-qcom-provide-default-cycles_in_1us-value.patch b/queue-6.8/scsi-ufs-qcom-provide-default-cycles_in_1us-value.patch
new file mode 100644 (file)
index 0000000..797c644
--- /dev/null
@@ -0,0 +1,41 @@
+From 81e2c1a0f8d3f62f4c9e80b20270aa3481c40524 Mon Sep 17 00:00:00 2001
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Date: Sun, 18 Feb 2024 15:56:34 +0200
+Subject: scsi: ufs: qcom: Provide default cycles_in_1us value
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+commit 81e2c1a0f8d3f62f4c9e80b20270aa3481c40524 upstream.
+
+The MSM8996 DT doesn't provide frequency limits for the core_clk_unipro
+clock, which results in miscalculation of the cycles_in_1us value.  Provide
+the backwards-compatible default to support existing MSM8996 DT files.
+
+Fixes: b4e13e1ae95e ("scsi: ufs: qcom: Add multiple frequency support for MAX_CORE_CLK_1US_CYCLES")
+Cc: Nitin Rawat <quic_nitirawa@quicinc.com>
+Cc: stable@vger.kernel.org # 6.7.x
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20240218-msm8996-fix-ufs-v3-1-40aab49899a3@linaro.org
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/ufs/host/ufs-qcom.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/ufs/host/ufs-qcom.c
++++ b/drivers/ufs/host/ufs-qcom.c
+@@ -1196,8 +1196,10 @@ static int ufs_qcom_set_core_clk_ctrl(st
+       list_for_each_entry(clki, head, list) {
+               if (!IS_ERR_OR_NULL(clki->clk) &&
+-                      !strcmp(clki->name, "core_clk_unipro")) {
+-                      if (is_scale_up)
++                  !strcmp(clki->name, "core_clk_unipro")) {
++                      if (!clki->max_freq)
++                              cycles_in_1us = 150; /* default for backwards compatibility */
++                      else if (is_scale_up)
+                               cycles_in_1us = ceil(clki->max_freq, (1000 * 1000));
+                       else
+                               cycles_in_1us = ceil(clk_get_rate(clki->clk), (1000 * 1000));
index 4bd8237c03feb64fc78290963c6f860d3807f829..b49ecb2bb864a8cd27de1418d82b61a667607f46 100644 (file)
@@ -347,3 +347,7 @@ vfio-pds-make-sure-migration-file-isn-t-accessed-aft.patch
 ring-buffer-make-wake-once-of-ring_buffer_wait-more-.patch
 btrfs-fix-extent-map-leak-in-unexpected-scenario-at-.patch
 alsa-sh-aica-reorder-cleanup-operations-to-avoid-uaf-bugs.patch
+scsi-ufs-qcom-provide-default-cycles_in_1us-value.patch
+scsi-sd-fix-tcg-opal-unlock-on-system-resume.patch
+scsi-sg-avoid-sg-device-teardown-race.patch
+scsi-core-fix-unremoved-procfs-host-directory-regression.patch