From c374b472050e566f9ba9f82084c24d2ee9e9d639 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 23 Jul 2024 15:33:05 +0200 Subject: [PATCH] 5.15-stable patches added patches: scsi-core-fix-a-use-after-free.patch --- .../scsi-core-fix-a-use-after-free.patch | 190 ++++++++++++++++++ queue-5.15/series | 1 + 2 files changed, 191 insertions(+) create mode 100644 queue-5.15/scsi-core-fix-a-use-after-free.patch diff --git a/queue-5.15/scsi-core-fix-a-use-after-free.patch b/queue-5.15/scsi-core-fix-a-use-after-free.patch new file mode 100644 index 00000000000..78f86d53f42 --- /dev/null +++ b/queue-5.15/scsi-core-fix-a-use-after-free.patch @@ -0,0 +1,190 @@ +From 8fe4ce5836e932f5766317cb651c1ff2a4cd0506 Mon Sep 17 00:00:00 2001 +From: Bart Van Assche +Date: Thu, 25 Aug 2022 17:26:34 -0700 +Subject: scsi: core: Fix a use-after-free + +From: Bart Van Assche + +commit 8fe4ce5836e932f5766317cb651c1ff2a4cd0506 upstream. + +There are two .exit_cmd_priv implementations. Both implementations use +resources associated with the SCSI host. Make sure that these resources are +still available when .exit_cmd_priv is called by waiting inside +scsi_remove_host() until the tag set has been freed. + +This commit fixes the following use-after-free: + +================================================================== +BUG: KASAN: use-after-free in srp_exit_cmd_priv+0x27/0xd0 [ib_srp] +Read of size 8 at addr ffff888100337000 by task multipathd/16727 +Call Trace: + + dump_stack_lvl+0x34/0x44 + print_report.cold+0x5e/0x5db + kasan_report+0xab/0x120 + srp_exit_cmd_priv+0x27/0xd0 [ib_srp] + scsi_mq_exit_request+0x4d/0x70 + blk_mq_free_rqs+0x143/0x410 + __blk_mq_free_map_and_rqs+0x6e/0x100 + blk_mq_free_tag_set+0x2b/0x160 + scsi_host_dev_release+0xf3/0x1a0 + device_release+0x54/0xe0 + kobject_put+0xa5/0x120 + device_release+0x54/0xe0 + kobject_put+0xa5/0x120 + scsi_device_dev_release_usercontext+0x4c1/0x4e0 + execute_in_process_context+0x23/0x90 + device_release+0x54/0xe0 + kobject_put+0xa5/0x120 + scsi_disk_release+0x3f/0x50 + device_release+0x54/0xe0 + kobject_put+0xa5/0x120 + disk_release+0x17f/0x1b0 + device_release+0x54/0xe0 + kobject_put+0xa5/0x120 + dm_put_table_device+0xa3/0x160 [dm_mod] + dm_put_device+0xd0/0x140 [dm_mod] + free_priority_group+0xd8/0x110 [dm_multipath] + free_multipath+0x94/0xe0 [dm_multipath] + dm_table_destroy+0xa2/0x1e0 [dm_mod] + __dm_destroy+0x196/0x350 [dm_mod] + dev_remove+0x10c/0x160 [dm_mod] + ctl_ioctl+0x2c2/0x590 [dm_mod] + dm_ctl_ioctl+0x5/0x10 [dm_mod] + __x64_sys_ioctl+0xb4/0xf0 + dm_ctl_ioctl+0x5/0x10 [dm_mod] + __x64_sys_ioctl+0xb4/0xf0 + do_syscall_64+0x3b/0x90 + entry_SYSCALL_64_after_hwframe+0x46/0xb0 + +Link: https://lore.kernel.org/r/20220826002635.919423-1-bvanassche@acm.org +Fixes: 65ca846a5314 ("scsi: core: Introduce {init,exit}_cmd_priv()") +Cc: Ming Lei +Cc: Christoph Hellwig +Cc: Mike Christie +Cc: Hannes Reinecke +Cc: John Garry +Cc: Li Zhijian +Reported-by: Li Zhijian +Tested-by: Li Zhijian +Signed-off-by: Bart Van Assche +Signed-off-by: Martin K. Petersen +[mheyne: fixed contextual conflicts: + - drivers/scsi/hosts.c: due to missing commit 973dac8a8a14 ("scsi: core: Refine how we set tag_set NUMA node") + - drivers/scsi/scsi_sysfs.c: due to missing commit 6f8191fdf41d ("block: simplify disk shutdown")] +Signed-off-by: Maximilian Heyne +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/hosts.c | 16 +++++++++++++--- + drivers/scsi/scsi_lib.c | 6 +++++- + drivers/scsi/scsi_priv.h | 2 +- + drivers/scsi/scsi_scan.c | 1 + + drivers/scsi/scsi_sysfs.c | 1 + + include/scsi/scsi_host.h | 2 ++ + 6 files changed, 23 insertions(+), 5 deletions(-) + +--- a/drivers/scsi/hosts.c ++++ b/drivers/scsi/hosts.c +@@ -182,6 +182,15 @@ void scsi_remove_host(struct Scsi_Host * + scsi_proc_host_rm(shost); + scsi_proc_hostdir_rm(shost->hostt); + ++ /* ++ * New SCSI devices cannot be attached anymore because of the SCSI host ++ * state so drop the tag set refcnt. Wait until the tag set refcnt drops ++ * to zero because .exit_cmd_priv implementations may need the host ++ * pointer. ++ */ ++ kref_put(&shost->tagset_refcnt, scsi_mq_free_tags); ++ wait_for_completion(&shost->tagset_freed); ++ + spin_lock_irqsave(shost->host_lock, flags); + if (scsi_host_set_state(shost, SHOST_DEL)) + BUG_ON(scsi_host_set_state(shost, SHOST_DEL_RECOVERY)); +@@ -240,6 +249,9 @@ int scsi_add_host_with_dma(struct Scsi_H + + shost->dma_dev = dma_dev; + ++ kref_init(&shost->tagset_refcnt); ++ init_completion(&shost->tagset_freed); ++ + /* + * Increase usage count temporarily here so that calling + * scsi_autopm_put_host() will trigger runtime idle if there is +@@ -312,6 +324,7 @@ int scsi_add_host_with_dma(struct Scsi_H + pm_runtime_disable(&shost->shost_gendev); + pm_runtime_set_suspended(&shost->shost_gendev); + pm_runtime_put_noidle(&shost->shost_gendev); ++ kref_put(&shost->tagset_refcnt, scsi_mq_free_tags); + fail: + return error; + } +@@ -344,9 +357,6 @@ static void scsi_host_dev_release(struct + kfree(dev_name(&shost->shost_dev)); + } + +- if (shost->tag_set.tags) +- scsi_mq_destroy_tags(shost); +- + kfree(shost->shost_data); + + ida_simple_remove(&host_index_ida, shost->host_no); +--- a/drivers/scsi/scsi_lib.c ++++ b/drivers/scsi/scsi_lib.c +@@ -1949,9 +1949,13 @@ int scsi_mq_setup_tags(struct Scsi_Host + return blk_mq_alloc_tag_set(tag_set); + } + +-void scsi_mq_destroy_tags(struct Scsi_Host *shost) ++void scsi_mq_free_tags(struct kref *kref) + { ++ struct Scsi_Host *shost = container_of(kref, typeof(*shost), ++ tagset_refcnt); ++ + blk_mq_free_tag_set(&shost->tag_set); ++ complete(&shost->tagset_freed); + } + + /** +--- a/drivers/scsi/scsi_priv.h ++++ b/drivers/scsi/scsi_priv.h +@@ -95,7 +95,7 @@ extern void scsi_run_host_queues(struct + extern void scsi_requeue_run_queue(struct work_struct *work); + extern void scsi_start_queue(struct scsi_device *sdev); + extern int scsi_mq_setup_tags(struct Scsi_Host *shost); +-extern void scsi_mq_destroy_tags(struct Scsi_Host *shost); ++extern void scsi_mq_free_tags(struct kref *kref); + extern void scsi_exit_queue(void); + extern void scsi_evt_thread(struct work_struct *work); + +--- a/drivers/scsi/scsi_scan.c ++++ b/drivers/scsi/scsi_scan.c +@@ -324,6 +324,7 @@ static struct scsi_device *scsi_alloc_sd + kfree(sdev); + goto out; + } ++ kref_get(&sdev->host->tagset_refcnt); + sdev->request_queue = q; + q->queuedata = sdev; + __scsi_init_queue(sdev->host, q); +--- a/drivers/scsi/scsi_sysfs.c ++++ b/drivers/scsi/scsi_sysfs.c +@@ -1490,6 +1490,7 @@ void __scsi_remove_device(struct scsi_de + mutex_unlock(&sdev->state_mutex); + + blk_cleanup_queue(sdev->request_queue); ++ kref_put(&sdev->host->tagset_refcnt, scsi_mq_free_tags); + cancel_work_sync(&sdev->requeue_work); + + if (sdev->host->hostt->slave_destroy) +--- a/include/scsi/scsi_host.h ++++ b/include/scsi/scsi_host.h +@@ -565,6 +565,8 @@ struct Scsi_Host { + struct scsi_host_template *hostt; + struct scsi_transport_template *transportt; + ++ struct kref tagset_refcnt; ++ struct completion tagset_freed; + /* Area to keep a shared tag map */ + struct blk_mq_tag_set tag_set; + diff --git a/queue-5.15/series b/queue-5.15/series index 324a13706ee..80c2e65e837 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -3,6 +3,7 @@ filelock-remove-locks-reliably-when-fcntl-close-race-is-detected.patch arm-9324-1-fix-get_user-broken-with-veneer.patch acpi-processor_idle-fix-invalid-comparison-with-insertion-sort-for-latency.patch bpf-fix-overrunning-reservations-in-ringbuf.patch +scsi-core-fix-a-use-after-free.patch scsi-core-alua-i-o-errors-for-alua-state-transitions.patch scsi-qedf-don-t-process-stag-work-during-unload-and-.patch scsi-qedf-wait-for-stag-work-during-unload.patch -- 2.47.3