Linux SCSI subsystem development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Yehyeong Lee" <yhlee@isslab.korea.ac.kr>
Cc: linux-scsi@vger.kernel.org
Subject: Re: [PATCH] scsi: libiscsi: only complete a task that has been sent
Date: Fri, 13 Nov 2026 15:10:28 +0000	[thread overview]
Message-ID: <sashiko-outbox-213058@kernel.org> (raw)
In-Reply-To: <20261113145140.282504-1-yhlee@isslab.korea.ac.kr>

Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] scsi: libiscsi: premature ISCSI_TASK_RUNNING store before xmit
  ref acquisition
- [High] scsi: libiscsi: RX completion of RESERVED_ITT tasks marked
  ISCSI_TASK_RUNNING
--

commit 2159be71cf354047db675ef637cf1e1cfec39bbe
Author: Yehyeong Lee <yhlee@isslab.korea.ac.kr>

scsi: libiscsi: only complete a task that has been sent

This commit pairs smp_store_release() when marking a task
ISCSI_TASK_RUNNING with smp_load_acquire() in the RX task lookups so
management responses and Reject PDUs only complete tasks that have been
prepared for transmission.

> diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
> index 2d04448432a77..83d726043d3e8 100644
> --- a/drivers/scsi/libiscsi.c
> +++ b/drivers/scsi/libiscsi.c

[ ... ]

> @@ -702,7 +703,8 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
>  	if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
>  		session->state = ISCSI_STATE_LOGGING_OUT;
>  
> -	task->state = ISCSI_TASK_RUNNING;
> +	/* Pairs with the acquire in the RX task lookups. */
> +	smp_store_release(&task->state, ISCSI_TASK_RUNNING);
>  	ISCSI_DBG_SESSION(session, "mgmtpdu [op 0x%x hdr->itt 0x%x "
>  			  "datalen %d]\n", hdr->opcode & ISCSI_OPCODE_MASK,
>  			  hdr->itt, task->data_count);

[Severity: High]
Can the RX path still complete and free task after smp_store_release() here
before the transmit path takes its reference?

A management task dequeued in iscsi_data_xmit() has refcount 1 under
session->frwd_lock and only acquires its transmit reference later in
iscsi_xmit_task() via iscsi_get_task():

CPU0 (kworker)                    CPU1 (softirq)
iscsi_data_xmit()
  spin_lock_bh(&session->frwd_lock)
  iscsi_prep_mgmt_task()
    smp_store_release(&task->state,
                      ISCSI_TASK_RUNNING)
                                  __iscsi_complete_pdu()
                                    spin_lock(&session->back_lock)
                                    smp_load_acquire(&task->state)
                                    iscsi_complete_task(task, ...)
                                      __iscsi_put_task()
                                        iscsi_free_task()
  iscsi_xmit_task()
    iscsi_get_task(task)
      WARN_ON_ONCE(1)             <-- refcount already 0

On transports without ihost->workq, iscsi_send_mgmt_task() calls
iscsi_prep_mgmt_task() and session->tt->xmit_task(task) with refcount 1, so
an RX completion in that window frees task during xmit_task() and causes
the caller's error-path iscsi_put_task() to underflow refcount and double
free the slot.

> @@ -1174,7 +1176,8 @@ static int iscsi_handle_reject(struct iscsi_session *session,
>  			if (!iscsi_verify_itt(conn, rejected_pdu.itt))
>  				task = iscsi_itt_to_task(session, conn,
>  							 rejected_pdu.itt);
> -			if (!task || task->state == ISCSI_TASK_FREE ||
> +			/* Pairs with the release when the task is prepared. */
> +			if (!task || smp_load_acquire(&task->state) != ISCSI_TASK_RUNNING ||
>  			    task->sc) {
>  				iscsi_conn_printk(KERN_ERR, conn,
>  						 "Invalid pdu reject. Could "
> @@ -1314,7 +1317,9 @@ int __iscsi_complete_pdu(struct iscsi_session *session, struct iscsi_conn *conn,
>  	case ISCSI_OP_SCSI_TMFUNC_RSP:
>  	case ISCSI_OP_NOOP_IN:
>  		task = iscsi_itt_to_task(session, conn, hdr->itt);
> -		if (!task || task->state == ISCSI_TASK_FREE || task->sc)
> +		/* Pairs with the release when the task is prepared. */
> +		if (!task || smp_load_acquire(&task->state) != ISCSI_TASK_RUNNING ||
> +		    task->sc)
>  			return ISCSI_ERR_BAD_ITT;
>  		break;
>  	default:

[Severity: High]
Can an incoming management response or Reject PDU complete a management
task that was sent with task->hdr->itt == RESERVED_ITT?

When replying to a target NOP-In, iscsi_send_nopout() allocates a task from
session->cmdpool with hdr->itt = RESERVED_ITT, and iscsi_prep_mgmt_task()
still sets task->state to ISCSI_TASK_RUNNING.  Transports free RESERVED_ITT
tasks on transmit because no response is expected:

drivers/scsi/libiscsi_tcp.c:iscsi_tcp_task_xmit() {
    ...
	/* mgmt command */
	if (!task->sc) {
		if (task->hdr->itt == RESERVED_ITT)
			iscsi_put_task(task);
		return 0;
	}
    ...
}

Because iscsi_itt_to_task() indexes session->cmds[] by the pool index in the
received PDU's ITT without checking task->hdr->itt, a PDU naming that pool
index while iscsi_xmit_task() holds its transmit reference (or while the
task is requeued after -EAGAIN) will pass the ISCSI_TASK_RUNNING check and
call iscsi_complete_task(), dropping a reference that the transport also
drops and causing a refcount underflow and use-after-free.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261113145140.282504-1-yhlee@isslab.korea.ac.kr?part=1

      reply	other threads:[~2026-11-13 15:10 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-13 14:51 [PATCH] scsi: libiscsi: only complete a task that has been sent Yehyeong Lee
2026-11-13 15:10 ` sashiko-bot [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-213058@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=yhlee@isslab.korea.ac.kr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox