Linux SCSI subsystem development
 help / color / mirror / Atom feed
* [GIT PULL] SCSI fixes for 7.3-rc7+
@ 2026-10-18 14:38 James Bottomley
  2026-10-18 15:01 ` sashiko-bot
  2026-10-18 19:22 ` pr-tracker-bot
  0 siblings, 2 replies; 3+ messages in thread
From: James Bottomley @ 2026-10-18 14:38 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: linux-scsi, linux-kernel

The following changes since commit 469fa055664bfd8717b087a80d59c03055789c17:

  scsi: ufs: core: Decouple CQ sweep from request iterator in MCQ (2026-10-05 22:05:13 -0400)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git/ tags/scsi-fixes

for you to fetch changes up to ec6b083915e8146e147314a5f4f1285d07b57bfc:

  scsi: bsg: Pass reply_len to bsg_setup_queue() to fit UFS ARPMB replies (2026-10-14 22:14:52 -0400)

----------------------------------------------------------------
All fixes in drivers (or the tape ULD) and one core fix to bsg (the
block ioctl equivalent of sg_io).  The biggest is the race in auth
updates fix in iscsi configfs, but the next biggest one is in bsg but
the generic pieces of that are mostly threading reply_len.

----------------------------------------------------------------
Laurence Oberman (2):
      scsi: st: Save the visited block for the partition the drive is in
      scsi: st: Fix use-after-free race between st_remove() and st_open()

Linfeng Sun (1):
      scsi: target: iscsi: Fix race in discovery auth updates

Stanley Jhu (1):
      scsi: bsg: Pass reply_len to bsg_setup_queue() to fit UFS ARPMB replies

Xingui Yang (1):
      scsi: libsas: Fix SMP IO deadlock during HA resume

Yehyeong Lee (4):
      scsi: xen/scsifront: Check for a NULL shadow entry on a backend response
      scsi: libiscsi: Reject a negative task index from parse_pdu_itt
      scsi: libiscsi: Validate the ITT reflected in a Reject PDU
      scsi: libiscsi: Validate the task named by a management response

Yu Zhang (1):
      scsi: target: Disable interrupts while holding delayed_cmd_lock

 block/bsg-lib.c                              | 13 ++++++++++---
 drivers/scsi/libiscsi.c                      | 14 ++++++++------
 drivers/scsi/libsas/sas_expander.c           | 14 ++++++++++++--
 drivers/scsi/mpi3mr/mpi3mr_app.c             |  2 +-
 drivers/scsi/scsi_transport_fc.c             |  6 ++++--
 drivers/scsi/scsi_transport_iscsi.c          |  2 +-
 drivers/scsi/scsi_transport_sas.c            |  6 ++++--
 drivers/scsi/st.c                            | 18 ++++++++++++------
 drivers/scsi/xen-scsifront.c                 |  1 +
 drivers/target/iscsi/iscsi_target_configfs.c | 26 +++++++++++++++++++-------
 drivers/target/target_core_transport.c       |  8 ++++----
 drivers/ufs/core/ufs_bsg.c                   |  2 +-
 include/linux/bsg-lib.h                      |  3 ++-
 13 files changed, 79 insertions(+), 36 deletions(-)

---

diff --git a/block/bsg-lib.c b/block/bsg-lib.c
index 895db30a7033..536cee4430a7 100644
--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -23,11 +23,14 @@ struct bsg_set {
 	struct bsg_device	*bd;
 	bsg_job_fn		*job_fn;
 	bsg_timeout_fn		*timeout_fn;
+	unsigned int		reply_len;
 };
 
 static int bsg_transport_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
 		bool open_for_write, unsigned int timeout)
 {
+	struct bsg_set *bset =
+		container_of(q->tag_set, struct bsg_set, tag_set);
 	struct bsg_job *job;
 	struct request *rq;
 	struct bio *bio;
@@ -50,7 +53,7 @@ static int bsg_transport_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
 	reply = job->reply;
 	memset(job, 0, sizeof(*job));
 	job->reply = reply;
-	job->reply_len = SCSI_SENSE_BUFFERSIZE;
+	job->reply_len = bset->reply_len;
 	job->dd_data = job + 1;
 
 	job->request_len = hdr->request_len;
@@ -301,9 +304,10 @@ static blk_status_t bsg_queue_rq(struct blk_mq_hw_ctx *hctx,
 static int bsg_init_rq(struct blk_mq_tag_set *set, struct request *req,
 		       unsigned int hctx_idx, int numa_node)
 {
+	struct bsg_set *bset = container_of(set, struct bsg_set, tag_set);
 	struct bsg_job *job = blk_mq_rq_to_pdu(req);
 
-	job->reply = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+	job->reply = kzalloc(bset->reply_len, GFP_KERNEL);
 	if (!job->reply)
 		return -ENOMEM;
 	return 0;
@@ -358,10 +362,12 @@ static const struct blk_mq_ops bsg_mq_ops = {
  * @job_fn: bsg job handler
  * @timeout: timeout handler function pointer
  * @dd_job_size: size of LLD data needed for each job
+ * @reply_len: size of the reply buffer needed for each job
  */
 struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
 		struct queue_limits *lim, bsg_job_fn *job_fn,
-		bsg_timeout_fn *timeout, int dd_job_size)
+		bsg_timeout_fn *timeout, int dd_job_size,
+		unsigned int reply_len)
 {
 	struct bsg_set *bset;
 	struct blk_mq_tag_set *set;
@@ -374,6 +380,7 @@ struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
 
 	bset->job_fn = job_fn;
 	bset->timeout_fn = timeout;
+	bset->reply_len = reply_len;
 
 	set = &bset->tag_set;
 	set->ops = &bsg_mq_ops;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 5cbc51899de0..5bfdb30b9088 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1142,13 +1142,15 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
 			spin_unlock(&conn->session->frwd_lock);
 			spin_lock(&conn->session->back_lock);
 		} else {
-			struct iscsi_task *task;
+			struct iscsi_task *task = NULL;
 			/*
 			 * Our nop as ping got dropped. We know the target
 			 * and transport are ok so just clean up
 			 */
-			task = iscsi_itt_to_task(conn, rejected_pdu.itt);
-			if (!task) {
+			if (!iscsi_verify_itt(conn, rejected_pdu.itt))
+				task = iscsi_itt_to_task(conn, rejected_pdu.itt);
+			if (!task || task->state == ISCSI_TASK_FREE ||
+			    task->sc) {
 				iscsi_conn_printk(KERN_ERR, conn,
 						 "Invalid pdu reject. Could "
 						 "not lookup rejected task.\n");
@@ -1191,7 +1193,7 @@ struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt)
 		session->tt->parse_pdu_itt(conn, itt, &i, NULL);
 	else
 		i = get_itt(itt);
-	if (i >= session->cmds_max)
+	if (i < 0 || i >= session->cmds_max)
 		return NULL;
 
 	return session->cmds[i];
@@ -1284,7 +1286,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
 	case ISCSI_OP_SCSI_TMFUNC_RSP:
 	case ISCSI_OP_NOOP_IN:
 		task = iscsi_itt_to_task(conn, hdr->itt);
-		if (!task)
+		if (!task || task->state == ISCSI_TASK_FREE || task->sc)
 			return ISCSI_ERR_BAD_ITT;
 		break;
 	default:
@@ -1384,7 +1386,7 @@ int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt)
 		return ISCSI_ERR_BAD_ITT;
 	}
 
-	if (i >= session->cmds_max) {
+	if (i < 0 || i >= session->cmds_max) {
 		iscsi_conn_printk(KERN_ERR, conn,
 				  "received invalid itt index %u (max cmds "
 				   "%u.\n", i, session->cmds_max);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 811c9eb4fef1..26c2099c28b9 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -62,7 +62,11 @@ static int smp_execute_task_sg(struct domain_device *dev,
 		to_sas_internal(dev->port->ha->shost->transportt);
 	struct sas_ha_struct *ha = dev->port->ha;
 
-	pm_runtime_get_sync(ha->dev);
+	/*
+	 * Non-blocking: a sync resume here would deadlock against
+	 * sas_drain_work() during HA resume.
+	 */
+	pm_runtime_get_noresume(ha->dev);
 	mutex_lock(&dev->ex_dev.cmd_mutex);
 	for (retry = 0; retry < 3; retry++) {
 		if (test_bit(SAS_DEV_GONE, &dev->state)) {
@@ -135,7 +139,7 @@ static int smp_execute_task_sg(struct domain_device *dev,
 		}
 	}
 	mutex_unlock(&dev->ex_dev.cmd_mutex);
-	pm_runtime_put_sync(ha->dev);
+	pm_runtime_put(ha->dev);
 
 	BUG_ON(retry == 3 && task != NULL);
 	sas_free_task(task);
@@ -2222,6 +2226,11 @@ void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
 		goto out;
 	}
 
+	/* The host may have autosuspended, resume it here. */
+	ret = pm_runtime_resume_and_get(dev->port->ha->dev);
+	if (ret)
+		goto out;
+
 	ret = smp_execute_task_sg(dev, job->request_payload.sg_list,
 			job->reply_payload.sg_list);
 	if (ret >= 0) {
@@ -2229,6 +2238,7 @@ void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
 		rcvlen = job->reply_payload.payload_len - ret;
 		ret = 0;
 	}
+	pm_runtime_put(dev->port->ha->dev);
 
 out:
 	bsg_job_done(job, ret, rcvlen);
diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c
index 1353a8ff9c85..094490713d69 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_app.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_app.c
@@ -3053,7 +3053,7 @@ void mpi3mr_bsg_init(struct mpi3mr_ioc *mrioc)
 	}
 
 	q = bsg_setup_queue(bsg_dev, dev_name(bsg_dev), &lim,
-			mpi3mr_bsg_request, NULL, 0);
+			mpi3mr_bsg_request, NULL, 0, SCSI_SENSE_BUFFERSIZE);
 	if (IS_ERR(q)) {
 		ioc_err(mrioc, "%s: bsg registration failed\n",
 		    dev_name(bsg_dev));
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 173ed6373f04..b66365a382c7 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -4345,7 +4345,8 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host)
 	scsi_init_limits(shost, &lim);
 	lim.max_segments = min_not_zero(lim.max_segments, i->f->max_bsg_segments);
 	q = bsg_setup_queue(dev, bsg_name, &lim, fc_bsg_dispatch,
-			fc_bsg_job_timeout, i->f->dd_bsg_size);
+			fc_bsg_job_timeout, i->f->dd_bsg_size,
+			SCSI_SENSE_BUFFERSIZE);
 	if (IS_ERR(q)) {
 		dev_err(dev,
 			"fc_host%d: bsg interface failed to initialize - setup queue\n",
@@ -4378,7 +4379,8 @@ fc_bsg_rportadd(struct Scsi_Host *shost, struct fc_rport *rport)
 	scsi_init_limits(shost, &lim);
 	lim.max_segments = min_not_zero(lim.max_segments, i->f->max_bsg_segments);
 	q = bsg_setup_queue(dev, dev_name(dev), &lim, fc_bsg_dispatch_prep,
-				fc_bsg_job_timeout, i->f->dd_bsg_size);
+				fc_bsg_job_timeout, i->f->dd_bsg_size,
+				SCSI_SENSE_BUFFERSIZE);
 	if (IS_ERR(q)) {
 		dev_err(dev, "failed to setup bsg queue\n");
 		return PTR_ERR(q);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 8aa76f813bcd..b50ff8a1d0a9 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1545,7 +1545,7 @@ iscsi_bsg_host_add(struct Scsi_Host *shost, struct iscsi_cls_host *ihost)
 	snprintf(bsg_name, sizeof(bsg_name), "iscsi_host%d", shost->host_no);
 	scsi_init_limits(shost, &lim);
 	q = bsg_setup_queue(dev, bsg_name, &lim, iscsi_bsg_host_dispatch, NULL,
-			0);
+			0, SCSI_SENSE_BUFFERSIZE);
 	if (IS_ERR(q)) {
 		shost_printk(KERN_ERR, shost, "bsg interface failed to "
 			     "initialize - no request queue\n");
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index d689b9ed08a6..a825966f60e5 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -199,7 +199,8 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
 
 	if (rphy) {
 		q = bsg_setup_queue(&rphy->dev, dev_name(&rphy->dev), NULL,
-				sas_smp_dispatch, NULL, 0);
+				sas_smp_dispatch, NULL, 0,
+				SCSI_SENSE_BUFFERSIZE);
 		if (IS_ERR(q))
 			return PTR_ERR(q);
 		rphy->q = q;
@@ -208,7 +209,8 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
 
 		snprintf(name, sizeof(name), "sas_host%d", shost->host_no);
 		q = bsg_setup_queue(&shost->shost_gendev, name, NULL,
-				sas_smp_dispatch, NULL, 0);
+				sas_smp_dispatch, NULL, 0,
+				SCSI_SENSE_BUFFERSIZE);
 		if (IS_ERR(q))
 			return PTR_ERR(q);
 		to_sas_host_attrs(shost)->q = q;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index f1c3c4946637..a757646c8dc6 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3217,14 +3217,20 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition
 	    partition >= ST_NBR_PARTITIONS)
 		return (-EINVAL);
 	if (partition != STp->partition) {
-		if (get_location(STp, &blk, &p, 1))
+		/*
+		 * Save the location for the partition the drive reports,
+		 * not for STp->partition: after a reset STp->partition may
+		 * not match the partition the drive is in.
+		 */
+		if (get_location(STp, &blk, &p, 1) ||
+		    p < 0 || p >= ST_NBR_PARTITIONS)
 			STps->last_block_valid = 0;
 		else {
-			STps->last_block_valid = 1;
-			STps->last_block_visited = blk;
+			STp->ps[p].last_block_valid = 1;
+			STp->ps[p].last_block_visited = blk;
 			DEBC_printk(STp, "Visited block %d for "
 				    "partition %d saved.\n",
-				    blk, STp->partition);
+				    blk, p);
 		}
 	}
 
@@ -4509,11 +4515,11 @@ static void st_remove(struct scsi_device *SDp)
 	remove_cdevs(tpnt);
 
 	mutex_lock(&st_ref_mutex);
-	kref_put(&tpnt->kref, scsi_tape_release);
-	mutex_unlock(&st_ref_mutex);
 	spin_lock(&st_index_lock);
 	idr_remove(&st_index_idr, index);
 	spin_unlock(&st_index_lock);
+	kref_put(&tpnt->kref, scsi_tape_release);
+	mutex_unlock(&st_ref_mutex);
 }
 
 /**
diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c
index 989bcaee42ca..aa44a233eac8 100644
--- a/drivers/scsi/xen-scsifront.c
+++ b/drivers/scsi/xen-scsifront.c
@@ -367,6 +367,7 @@ static void scsifront_do_response(struct vscsifrnt_info *info,
 	struct vscsifrnt_shadow *shadow;
 
 	if (ring_rsp->rqid >= VSCSIIF_MAX_REQS ||
+	    !info->shadow[ring_rsp->rqid] ||
 	    !info->shadow[ring_rsp->rqid]->inflight) {
 		scsifront_set_error(info, "illegal rqid returned by backend!");
 		return;
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index 704ec94383c3..e1aa0af52c65 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -1306,17 +1306,24 @@ static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item,
 		return -EINVAL;
 	}
 
+	if (iscsit_get_tpg(discovery_tpg) < 0)
+		return -EINVAL;
+
 	param = iscsi_find_param_from_key(AUTHMETHOD,
 				discovery_tpg->param_list);
-	if (!param)
-		return -EINVAL;
+	if (!param) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	if (op) {
 		/*
 		 * Reset the AuthMethod key to CHAP.
 		 */
-		if (iscsi_update_param_value(param, CHAP) < 0)
-			return -EINVAL;
+		if (iscsi_update_param_value(param, CHAP) < 0) {
+			err = -EINVAL;
+			goto out;
+		}
 
 		discovery_tpg->tpg_attrib.authentication = 1;
 		iscsit_global->discovery_acl.node_auth.enforce_discovery_auth = 1;
@@ -1327,8 +1334,10 @@ static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item,
 		/*
 		 * Reset the AuthMethod key to CHAP,None
 		 */
-		if (iscsi_update_param_value(param, "CHAP,None") < 0)
-			return -EINVAL;
+		if (iscsi_update_param_value(param, "CHAP,None") < 0) {
+			err = -EINVAL;
+			goto out;
+		}
 
 		discovery_tpg->tpg_attrib.authentication = 0;
 		iscsit_global->discovery_acl.node_auth.enforce_discovery_auth = 0;
@@ -1337,7 +1346,10 @@ static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item,
 			" Discovery TPG\n");
 	}
 
-	return count;
+	err = count;
+out:
+	iscsit_put_tpg(discovery_tpg);
+	return err;
 }
 
 CONFIGFS_ATTR(iscsi_disc_, enforce_discovery_auth);
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index dcfe94594916..67c046549192 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -2359,7 +2359,7 @@ void target_do_delayed_work(struct work_struct *work)
 	struct se_device *dev = container_of(work, struct se_device,
 					     delayed_cmd_work);
 
-	spin_lock(&dev->delayed_cmd_lock);
+	spin_lock_irq(&dev->delayed_cmd_lock);
 	while (!dev->ordered_sync_in_progress) {
 		struct se_cmd *cmd;
 
@@ -2380,12 +2380,12 @@ void target_do_delayed_work(struct work_struct *work)
 		dev->ordered_sync_in_progress = true;
 
 		list_del(&cmd->se_delayed_node);
-		spin_unlock(&dev->delayed_cmd_lock);
+		spin_unlock_irq(&dev->delayed_cmd_lock);
 
 		__target_execute_cmd(cmd, true);
-		spin_lock(&dev->delayed_cmd_lock);
+		spin_lock_irq(&dev->delayed_cmd_lock);
 	}
-	spin_unlock(&dev->delayed_cmd_lock);
+	spin_unlock_irq(&dev->delayed_cmd_lock);
 }
 
 static void transport_complete_ordered_sync(struct se_cmd *cmd)
diff --git a/drivers/ufs/core/ufs_bsg.c b/drivers/ufs/core/ufs_bsg.c
index 7a66917b3fc0..156637dd76c8 100644
--- a/drivers/ufs/core/ufs_bsg.c
+++ b/drivers/ufs/core/ufs_bsg.c
@@ -258,7 +258,7 @@ int ufs_bsg_probe(struct ufs_hba *hba)
 		goto out;
 
 	q = bsg_setup_queue(bsg_dev, dev_name(bsg_dev), NULL, ufs_bsg_request,
-			NULL, 0);
+			NULL, 0, sizeof(struct ufs_rpmb_reply));
 	if (IS_ERR(q)) {
 		ret = PTR_ERR(q);
 		device_del(bsg_dev);
diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h
index 14fa93268630..a697246feeac 100644
--- a/include/linux/bsg-lib.h
+++ b/include/linux/bsg-lib.h
@@ -66,7 +66,8 @@ void bsg_job_done(struct bsg_job *job, int result,
 		  unsigned int reply_payload_rcv_len);
 struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
 		struct queue_limits *lim, bsg_job_fn *job_fn,
-		bsg_timeout_fn *timeout, int dd_job_size);
+		bsg_timeout_fn *timeout, int dd_job_size,
+		unsigned int reply_len);
 void bsg_remove_queue(struct request_queue *q);
 void bsg_job_put(struct bsg_job *job);
 int __must_check bsg_job_get(struct bsg_job *job);

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [GIT PULL] SCSI fixes for 7.3-rc7+
  2026-10-18 14:38 [GIT PULL] SCSI fixes for 7.3-rc7+ James Bottomley
@ 2026-10-18 15:01 ` sashiko-bot
  2026-10-18 19:22 ` pr-tracker-bot
  1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-10-18 15:01 UTC (permalink / raw)
  To: James Bottomley; +Cc: linux-scsi

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Critical] scsi: libiscsi: premature mgmt response frees pending task on conn->mgmtqueue
- [High] scsi: libsas: smp_execute_task_sg() skips runtime resume for sysfs callers
- [High] scsi: libsas: sas_smp_handler() fails with -EACCES when runtime PM is disabled
- [High] scsi: target: iscsi: UAF race on discovery_tpg param_list during login
--

commit f682ddc340c78ec7c00ca8f8ce335b1612f00410
Author: James Bottomley <James.Bottomley@HansenPartnership.com>

SCSI fixes for 7.3-rc7+

This pull request contains SCSI fixes for libiscsi, libsas, st, xen-scsifront,
target, and bsg.

> diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
> index 5cbc51899de00..5bfdb30b9088d 100644
> --- a/drivers/scsi/libiscsi.c
> +++ b/drivers/scsi/libiscsi.c
> @@ -1142,13 +1142,15 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
>  			spin_unlock(&conn->session->frwd_lock);
>  			spin_lock(&conn->session->back_lock);
>  		} else {
> -			struct iscsi_task *task;
> +			struct iscsi_task *task = NULL;
>  			/*
>  			 * Our nop as ping got dropped. We know the target
>  			 * and transport are ok so just clean up
>  			 */
> -			task = iscsi_itt_to_task(conn, rejected_pdu.itt);
> -			if (!task) {
> +			if (!iscsi_verify_itt(conn, rejected_pdu.itt))
> +				task = iscsi_itt_to_task(conn, rejected_pdu.itt);
> +			if (!task || task->state == ISCSI_TASK_FREE ||
> +			    task->sc) {
>  				iscsi_conn_printk(KERN_ERR, conn,
>  						 "Invalid pdu reject. Could "
>  						 "not lookup rejected task.\n");

[ ... ]

> @@ -1284,7 +1286,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
>  	case ISCSI_OP_SCSI_TMFUNC_RSP:
>  	case ISCSI_OP_NOOP_IN:
>  		task = iscsi_itt_to_task(conn, hdr->itt);
> -		if (!task)
> +		if (!task || task->state == ISCSI_TASK_FREE || task->sc)
>  			return ISCSI_ERR_BAD_ITT;
>  		break;
>  	default:

[Severity: Critical]
Can an unsolicited or premature management response PDU or Reject PDU free a
task while it is still queued on conn->mgmtqueue in ISCSI_TASK_PENDING state?

In drivers/scsi/libiscsi.c, iscsi_alloc_mgmt_task() initializes a management
task under session->frwd_lock with refcount = 1, task->sc = NULL, and
task->state = ISCSI_TASK_PENDING:

drivers/scsi/libiscsi.c:iscsi_alloc_mgmt_task() {
	...
	refcount_set(&task->refcount, 1);
	task->conn = conn;
	task->sc = NULL;
	INIT_LIST_HEAD(&task->running);
	task->state = ISCSI_TASK_PENDING;
}

When ihost->workq is used, iscsi_send_mgmt_task() adds task->running to
conn->mgmtqueue while task->state is still ISCSI_TASK_PENDING and refcount is
still 1:

drivers/scsi/libiscsi.c:iscsi_send_mgmt_task() {
	...
	} else {
		list_add_tail(&task->running, &conn->mgmtqueue);
		iscsi_conn_queue_xmit(conn);
	}
}

The task only transitions to ISCSI_TASK_RUNNING later when iscsi_data_xmit()
dequeues task->running from conn->mgmtqueue and calls iscsi_prep_mgmt_task().
In addition, iscsi_alloc_task() for SCSI commands runs under
session->frwd_lock (not session->back_lock) and sets task->state =
ISCSI_TASK_PENDING before assigning task->sc = sc.

Because both iscsi_handle_reject() and __iscsi_complete_pdu() only check for
task->state == ISCSI_TASK_FREE || task->sc under session->back_lock, a target
response (ISCSI_OP_NOOP_IN, ISCSI_OP_LOGOUT_RSP, ISCSI_OP_LOGIN_RSP,
ISCSI_OP_TEXT_RSP, ISCSI_OP_SCSI_TMFUNC_RSP, or ISCSI_OP_REJECT with
ISCSI_REASON_IMM_CMD_REJECT for ISCSI_OP_NOOP_OUT) naming the ITT of a task in
ISCSI_TASK_PENDING passes this check.

That calls iscsi_complete_task() -> __iscsi_put_task() -> iscsi_free_task(),
which drops task->refcount from 1 to 0 and returns the task to
session->cmdpool.queue via kfifo_in() without unlinking task->running from
conn->mgmtqueue:

drivers/scsi/libiscsi.c:iscsi_free_task() {
	...
	session->tt->cleanup_task(task);
	task->state = ISCSI_TASK_FREE;
	task->sc = NULL;
	if (conn->login_task == task)
		return;

	kfifo_in(&session->cmdpool.queue, (void*)&task, sizeof(void*));
}

When iscsi_data_xmit() subsequently processes conn->mgmtqueue or the task is
reallocated from cmdpool.queue, wouldn't this cause a use-after-free and
conn->mgmtqueue list corruption? Should both checks require task->state !=
ISCSI_TASK_RUNNING instead of task->state == ISCSI_TASK_FREE?

> diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
> index 811c9eb4fef11..26c2099c28b97 100644
> --- a/drivers/scsi/libsas/sas_expander.c
> +++ b/drivers/scsi/libsas/sas_expander.c
> @@ -62,7 +62,11 @@ static int smp_execute_task_sg(struct domain_device *dev,
>  		to_sas_internal(dev->port->ha->shost->transportt);
>  	struct sas_ha_struct *ha = dev->port->ha;
>  
> -	pm_runtime_get_sync(ha->dev);
> +	/*
> +	 * Non-blocking: a sync resume here would deadlock against
> +	 * sas_drain_work() during HA resume.
> +	 */
> +	pm_runtime_get_noresume(ha->dev);
>  	mutex_lock(&dev->ex_dev.cmd_mutex);
>  	for (retry = 0; retry < 3; retry++) {
>  		if (test_bit(SAS_DEV_GONE, &dev->state)) {
> @@ -135,7 +139,7 @@ static int smp_execute_task_sg(struct domain_device *dev,
>  		}
>  	}
>  	mutex_unlock(&dev->ex_dev.cmd_mutex);
> -	pm_runtime_put_sync(ha->dev);
> +	pm_runtime_put(ha->dev);
>  
>  	BUG_ON(retry == 3 && task != NULL);
>  	sas_free_task(task);

[Severity: High]
Does replacing pm_runtime_get_sync(ha->dev) with
pm_runtime_get_noresume(ha->dev) in smp_execute_task_sg() leave sysfs and
exported PHY management callers executing SMP tasks while the SAS host is
runtime-suspended?

Only sas_smp_handler() was updated to resume ha->dev before calling
smp_execute_task_sg(), but three other non-discovery paths invoke
smp_execute_task() -> smp_execute_task_sg() on expander PHYs
(!scsi_is_sas_phy_local(phy)) without waking ha->dev:

1. Reading expander PHY link error sysfs attributes
   (show_sas_phy_invalid_dword_count,
   show_sas_phy_running_disparity_error_count,
   show_sas_phy_loss_of_dword_sync_count, and
   show_sas_phy_phy_reset_problem_count in drivers/scsi/scsi_transport_sas.c)
   calls sas_get_linkerrors() -> sas_smp_get_phy_events() ->
   smp_execute_task() -> smp_execute_task_sg():

drivers/scsi/libsas/sas_init.c:sas_get_linkerrors() {
	if (scsi_is_sas_phy_local(phy)) {
		...
	}

	return sas_smp_get_phy_events(phy);
}

2. Writing expander PHY linkrate sysfs attributes
   (store_sas_phy_minimum_linkrate and store_sas_phy_maximum_linkrate in
   drivers/scsi/scsi_transport_sas.c) calls sas_set_phy_speed() ->
   sas_smp_phy_control() -> smp_execute_task() -> smp_execute_task_sg():

drivers/scsi/libsas/sas_init.c:sas_set_phy_speed() {
	...
	} else {
		struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
		struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
		ret = sas_smp_phy_control(ddev, phy->number,
					  PHY_FUNC_LINK_RESET, rates);
	}
}

3. Calling the exported sas_phy_reset() on an expander PHY calls
   sas_smp_phy_control() -> smp_execute_task() -> smp_execute_task_sg()
   without resuming ha->dev (unlike the sysfs workqueue wrappers
   queue_phy_reset() and queue_phy_enable() in drivers/scsi/libsas/sas_init.c,
   which call pm_runtime_get_sync(ha->dev)).

When the controller is runtime-suspended (for example on hisi_sas_v3_hw where
sas_suspend_devices() clears dev->lldd_dev and powers down the hardware),
won't these expander PHY operations fail with -ECOMM or access a suspended
HBA?

> @@ -2222,6 +2226,11 @@ void sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
>  		goto out;
>  	}
>  
> +	/* The host may have autosuspended, resume it here. */
> +	ret = pm_runtime_resume_and_get(dev->port->ha->dev);
> +	if (ret)
> +		goto out;
> +
>  	ret = smp_execute_task_sg(dev, job->request_payload.sg_list,
>  			job->reply_payload.sg_list);
>  	if (ret >= 0) {

[Severity: High]
Won't pm_runtime_resume_and_get(dev->port->ha->dev) fail with -EACCES on
platform-bus libsas controllers that do not enable runtime PM, such as
hisi_sas_v1_hw and hisi_sas_v2_hw?

Previously, smp_execute_task_sg() called pm_runtime_get_sync(ha->dev) and did
not check its return value. In drivers/base/power/runtime.c:rpm_resume(), when
dev->power.disable_depth > 0 and !(rpmflags & RPM_TRANSPARENT), it returns 1
only if runtime_status and last_status are both RPM_ACTIVE, and returns
-EACCES otherwise:

drivers/base/power/runtime.c:rpm_resume() {
	if (dev->power.runtime_error) {
		retval = -EINVAL;
	} else if (dev->power.disable_depth > 0) {
		if (dev->power.runtime_status == RPM_ACTIVE &&
		    dev->power.last_status == RPM_ACTIVE)
			retval = 1;
		else if (rpmflags & RPM_TRANSPARENT)
			goto out;
		else
			retval = -EACCES;
	}
}

Unlike PCI devices (where pci_pm_init() calls pm_runtime_set_active()),
platform devices are initialized by pm_runtime_init() with disable_depth = 1,
runtime_status = RPM_SUSPENDED, and last_status = RPM_INVALID. In
drivers/scsi/hisi_sas/hisi_sas_main.c:hisi_sas_probe(), platform controllers
set sha->dev = hisi_hba->dev (&pdev->dev) without calling
pm_runtime_set_active() or pm_runtime_enable(), so every expander BSG request
in sas_smp_handler() will abort at if (ret) goto out with -EACCES when
CONFIG_PM=y.

> diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
> index 704ec94383c3c..e1aa0af52c658 100644
> --- a/drivers/target/iscsi/iscsi_target_configfs.c
> +++ b/drivers/target/iscsi/iscsi_target_configfs.c
> @@ -1306,17 +1306,24 @@ static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item,
>  		return -EINVAL;
>  	}
>  
> +	if (iscsit_get_tpg(discovery_tpg) < 0)
> +		return -EINVAL;
> +
>  	param = iscsi_find_param_from_key(AUTHMETHOD,
>  				discovery_tpg->param_list);
> -	if (!param)
> -		return -EINVAL;
> +	if (!param) {
> +		err = -EINVAL;
> +		goto out;
> +	}
>  
>  	if (op) {
>  		/*
>  		 * Reset the AuthMethod key to CHAP.
>  		 */
> -		if (iscsi_update_param_value(param, CHAP) < 0)
> -			return -EINVAL;
> +		if (iscsi_update_param_value(param, CHAP) < 0) {
> +			err = -EINVAL;
> +			goto out;
> +		}
>  
>  		discovery_tpg->tpg_attrib.authentication = 1;
>  		iscsit_global->discovery_acl.node_auth.enforce_discovery_auth = 1;

[Severity: High]
Does acquiring discovery_tpg->tpg_access_lock via iscsit_get_tpg() prevent the
use-after-free race against concurrent discovery logins?

In drivers/target/iscsi/iscsi_target_parameters.c, iscsi_update_param_value()
frees param->value and reallocates it in place:

drivers/target/iscsi/iscsi_target_parameters.c:iscsi_update_param_value() {
	kfree(param->value);

	param->value = kstrdup(value, GFP_KERNEL);
	...
}

However, the discovery login path does not acquire
discovery_tpg->tpg_access_lock. When an initiator logs into a discovery
session, iscsi_target_locate_portal() in
drivers/target/iscsi/iscsi_target_nego.c sets conn->tpg =
iscsit_global->discovery_tpg and calls iscsit_access_np(np, conn->tpg), which
only takes discovery_tpg->np_login_sem:

drivers/target/iscsi/iscsi_target_nego.c:iscsi_target_locate_portal() {
	...
		conn->tpg = iscsit_global->discovery_tpg;
		if (iscsit_access_np(np, conn->tpg) < 0) {
	...
}

Then iscsi_login_zero_tsih_s2() in drivers/target/iscsi/iscsi_target_login.c
calls iscsi_copy_param_list(), which reads param->value while holding only
discovery_tpg->np_login_sem:

drivers/target/iscsi/iscsi_target_login.c:iscsi_login_zero_tsih_s2() {
	...
	if (iscsi_copy_param_list(&conn->param_list,
				conn->tpg->param_list, 1) < 0) {
	...
}

drivers/target/iscsi/iscsi_target_parameters.c:iscsi_copy_param_list() {
	...
		new_param->name = kstrdup(param->name, GFP_KERNEL);
		new_param->value = kstrdup(param->value, GFP_KERNEL);
	...
}

Since iscsi_disc_enforce_discovery_auth_store() holds only tpg_access_lock and
discovery login holds only np_login_sem, can kfree(param->value) in
iscsi_update_param_value() still race with kstrdup(param->value, GFP_KERNEL)
in iscsi_copy_param_list()?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/6a4bfcdc8e60669d95abb70bdaa07b87154c9a95.camel@HansenPartnership.com?part=1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [GIT PULL] SCSI fixes for 7.3-rc7+
  2026-10-18 14:38 [GIT PULL] SCSI fixes for 7.3-rc7+ James Bottomley
  2026-10-18 15:01 ` sashiko-bot
@ 2026-10-18 19:22 ` pr-tracker-bot
  1 sibling, 0 replies; 3+ messages in thread
From: pr-tracker-bot @ 2026-10-18 19:22 UTC (permalink / raw)
  To: James Bottomley; +Cc: Andrew Morton, Linus Torvalds, linux-scsi, linux-kernel

The pull request you sent on Sun, 18 Oct 2026 10:38:55 -0400:

> https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git/ tags/scsi-fixes

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/f909e534f5e34feb2ea2701d54df63e21aa506fc

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-10-18 19:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-18 14:38 [GIT PULL] SCSI fixes for 7.3-rc7+ James Bottomley
2026-10-18 15:01 ` sashiko-bot
2026-10-18 19:22 ` pr-tracker-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox