From: Dmitry Bogdanov <d.bogdanov@yadro.com>
To: <sashiko-reviews@lists.linux.dev>
Cc: <target-devel@vger.kernel.org>, <linux-scsi@vger.kernel.org>
Subject: Re: [PATCH 2/2] scsi: target: iscsi: fix hanging WRITE_PENDING commands
Date: Wed, 28 Oct 2026 01:55:45 +0300 [thread overview]
Message-ID: <20261027225545.GA32229@yadro.com> (raw)
In-Reply-To: <sashiko-outbox-187009@kernel.org>
On Tue, Oct 27, 2026 at 06:18:12PM +0000, sashiko-bot@kernel.org wrote:
>
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] scsi: target: iscsi: double completion in iscsit_release_commands_from_conn()
> --
>
> commit 31a87057639fce26dc0f2f4bbcd6ddacf96b85a5
> Author: Dmitry Bogdanov <d.bogdanov@yadro.com>
>
> scsi: target: iscsi: fix hanging WRITE_PENDING commands
>
> This commit removes early CMD_T_ABORTED checks in the iSCSI Data-Out and
> command execution paths so that aborted WRITE commands in WRITE_PENDING state
> are passed to the target core once all Data-Out PDUs have been received.
>
> > diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
> > index 62ada3a52210e..03d618cd76721 100644
> > --- a/drivers/target/iscsi/iscsi_target.c
> > +++ b/drivers/target/iscsi/iscsi_target.c
> > @@ -1518,23 +1518,6 @@ __iscsit_check_dataout_hdr(struct iscsit_conn *conn, void *buf,
> > if (hdr->flags & ISCSI_FLAG_CMD_FINAL)
> > iscsit_stop_dataout_timer(cmd);
> >
> > - return iscsit_dump_data_payload(conn, payload_length, 1);
> > - }
> > - } else {
> > - /*
> > - * For the normal solicited data path:
> > - *
> > - * Check for a delayed TASK_ABORTED status and dump any
> > - * incoming data out payload if one exists. Also, when the
> > - * ISCSI_FLAG_CMD_FINAL is set to denote the end of the current
> > - * data out sequence, we decrement outstanding_r2ts. Once
> > - * outstanding_r2ts reaches zero, go ahead and send the delayed
> > - * TASK_ABORTED status.
> > - */
> > - if (se_cmd->transport_state & CMD_T_ABORTED) {
> > - if (hdr->flags & ISCSI_FLAG_CMD_FINAL &&
> > - --cmd->outstanding_r2ts < 1)
> > - iscsit_stop_dataout_timer(cmd);
>
> [Severity: High]
> Could passing an aborted WRITE_PENDING command to target_execute_cmd() cause
> a double abort completion and use-after-free if the connection closes afterward
> in iscsit_release_commands_from_conn()?
Yes, it can cause. But my patch neither was intended to address that
problem neither increases its probability. WRITE_PENDING always may be
aborted, in parallel from other session, right
before target_cmd_interrupted() in target_execute_cmd().
And that is easily fixed by changing cmd->t_state in
target_execute_cmd() before target_cmd_interrupted() to take the
cmd ownership by the target core:
-----------------
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 2c9f4b58c024f..14ea1a9d7fa40 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -2561,6 +2561,10 @@ static bool target_handle_task_attr(struct se_cmd *cmd)
void target_execute_cmd(struct se_cmd *cmd)
{
trace_target_execute_cmd(cmd);
+
+ spin_lock_irq(&cmd->t_state_lock);
+ cmd->t_state = TRANSPORT_PROCESSING;
+ spin_unlock_irq(&cmd->t_state_lock);
/*
* Determine if frontend context caller is requesting the stopping of
* this command for frontend exceptions.
@@ -2571,7 +2575,6 @@ void target_execute_cmd(struct se_cmd *cmd)
return;
spin_lock_irq(&cmd->t_state_lock);
- cmd->t_state = TRANSPORT_PROCESSING;
cmd->transport_state |= CMD_T_ACTIVE | CMD_T_SENT;
spin_unlock_irq(&cmd->t_state_lock);
---------------
>
> With this check removed in __iscsit_check_dataout_hdr(), an aborted WRITE
> command in TRANSPORT_WRITE_PENDING state receives its remaining Data-Out PDUs
> and calls target_execute_cmd() in iscsit_check_dataout_payload() (or in
> iscsit_execute_cmd() for out-of-order CmdSNs):
>
> drivers/target/iscsi/iscsi_target.c:iscsit_check_dataout_payload() {
> ...
> iscsit_stop_dataout_timer(cmd);
> if (ooo_cmdsn)
> return 0;
> target_execute_cmd(&cmd->se_cmd);
> return 0;
> ...
> }
>
> In target_execute_cmd(), target_cmd_interrupted() is called before
> cmd->t_state is updated to TRANSPORT_PROCESSING:
>
> drivers/target/target_core_transport.c:target_execute_cmd() {
> if (target_cmd_interrupted(cmd))
> return;
>
> spin_lock_irq(&cmd->t_state_lock);
> cmd->t_state = TRANSPORT_PROCESSING;
> cmd->transport_state |= CMD_T_ACTIVE | CMD_T_SENT;
> spin_unlock_irq(&cmd->t_state_lock);
> ...
> }
>
> Because CMD_T_ABORTED is set, target_cmd_interrupted() queues
> target_abort_work on target_completion_wq and returns true without changing
> cmd->t_state:
>
> drivers/target/target_core_transport.c:target_cmd_interrupted() {
> ...
> if (cmd->transport_state & CMD_T_ABORTED) {
> if (cmd->transport_complete_callback)
> cmd->transport_complete_callback(cmd, false, &post_ret);
> INIT_WORK(&cmd->work, target_abort_work);
> queue_work(target_completion_wq, &cmd->work);
> return true;
> }
> ...
> }
>
> As a result, cmd->se_cmd.t_state remains TRANSPORT_WRITE_PENDING. When
> CMD_T_TAS is set (for example, when aborted by a LUN_RESET on another session
> with emulate_tas enabled), target_handle_abort() queues SAM_STAT_TASK_ABORTED
> status and drops one cmd_kref reference via
> transport_cmd_check_stop_to_fabric(), leaving the command on
> conn->conn_cmd_list in TRANSPORT_WRITE_PENDING state until ExpStatSN
> acknowledges the status (or, when CMD_T_TAS is not set, until
> target_abort_work runs iscsit_aborted_task()).
>
> If the connection closes while the command is still on conn->conn_cmd_list,
> iscsit_release_commands_from_conn() checks for TRANSPORT_WRITE_PENDING:
>
> drivers/target/iscsi/iscsi_target.c:iscsit_release_commands_from_conn() {
> ...
> if (cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING) {
> /*
> * We never submitted the cmd to LIO core, so we have
> * to tell LIO to perform the completion process.
> */
> spin_unlock_irq(&se_cmd->t_state_lock);
> target_complete_cmd(&cmd->se_cmd, SAM_STAT_TASK_ABORTED);
> continue;
> }
> ...
> }
>
> Wouldn't this call target_complete_cmd() -> target_cmd_interrupted() a second
> time on the same command, re-initializing and re-queueing cmd->work for
> target_abort_work while iscsit_release_commands_from_conn() also frees the
> command via iscsit_free_cmd(), leading to workqueue corruption, cmd_kref
> underflow, and use-after-free of struct iscsit_cmd?
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20261027180123.13163-1-d.bogdanov@yadro.com?part=2
next prev parent reply other threads:[~2026-10-27 22:55 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-27 18:01 [PATCH 0/2] target: iscsi: fix hanged WRITE_PENDING commands Dmitry Bogdanov
2026-10-27 18:01 ` [PATCH 1/2] Revert "scsi: target: iscsi: Fix hang for aborted WRITE_PENDING commands" Dmitry Bogdanov
2026-10-27 18:01 ` [PATCH 2/2] scsi: target: iscsi: fix hanging WRITE_PENDING commands Dmitry Bogdanov
2026-10-27 18:18 ` sashiko-bot
2026-10-27 22:55 ` Dmitry Bogdanov [this message]
2026-10-27 20:08 ` [PATCH 0/2] target: iscsi: fix hanged " Laurence Oberman
2026-10-28 14:02 ` Dmitry Bogdanov
2026-10-28 14:30 ` Laurence Oberman
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=20261027225545.GA32229@yadro.com \
--to=d.bogdanov@yadro.com \
--cc=linux-scsi@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=target-devel@vger.kernel.org \
/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