Revert "scsi: core: Fix a use-after-free"

This reverts commit 5ce8fad941 which is
commit 8fe4ce5836e932f5766317cb651c1ff2a4cd0506 upstream.

It breaks the Android kernel abi and can be brought back in the future
in an abi-safe way if it is really needed.

Bug: 161946584
Change-Id: I939984e199db400ce2107dedaec05c186eae11d8
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman 2024-08-12 15:28:24 +00:00
parent dc67fccdbe
commit c6acc5f079
6 changed files with 5 additions and 23 deletions

View File

@ -182,15 +182,6 @@ void scsi_remove_host(struct Scsi_Host *shost)
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));
@ -249,9 +240,6 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
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
@ -324,7 +312,6 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
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;
}
@ -357,6 +344,9 @@ static void scsi_host_dev_release(struct device *dev)
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);

View File

@ -1921,13 +1921,9 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost)
return blk_mq_alloc_tag_set(tag_set);
}
void scsi_mq_free_tags(struct kref *kref)
void scsi_mq_destroy_tags(struct Scsi_Host *shost)
{
struct Scsi_Host *shost = container_of(kref, typeof(*shost),
tagset_refcnt);
blk_mq_free_tag_set(&shost->tag_set);
complete(&shost->tagset_freed);
}
/**

View File

@ -93,7 +93,7 @@ extern void scsi_requeue_run_queue(struct work_struct *work);
extern struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev);
extern void scsi_start_queue(struct scsi_device *sdev);
extern int scsi_mq_setup_tags(struct Scsi_Host *shost);
extern void scsi_mq_free_tags(struct kref *kref);
extern void scsi_mq_destroy_tags(struct Scsi_Host *shost);
extern void scsi_exit_queue(void);
extern void scsi_evt_thread(struct work_struct *work);
struct request_queue;

View File

@ -273,7 +273,6 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
kfree(sdev);
goto out;
}
kref_get(&sdev->host->tagset_refcnt);
WARN_ON_ONCE(!blk_get_queue(sdev->request_queue));
sdev->request_queue->queuedata = sdev;

View File

@ -1481,7 +1481,6 @@ void __scsi_remove_device(struct scsi_device *sdev)
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)

View File

@ -554,8 +554,6 @@ 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;