Linux SCSI subsystem development
 help / color / mirror / Atom feed
From: Praneeth Balasubramanian <praneethb2002@gmail.com>
To: "Martin K . Petersen" <mkp@kernel.org>
Cc: target-devel@vger.kernel.org, linux-scsi@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Praneeth Balasubramanian <praneeth@ucsb.edu>,
	stable@vger.kernel.org
Subject: [PATCH] scsi: target: iscsi: Check for existing sessions only after authentication
Date: Thu, 29 Oct 2026 13:54:56 -0700	[thread overview]
Message-ID: <20261029205456.1211532-1-praneethb2002@gmail.com> (raw)

From: Praneeth Balasubramanian <praneeth@ucsb.edu>

In the operational-negotiation path (CSG=1),
iscsi_target_handle_csg_one() calls
iscsi_target_check_for_existing_instances() before
iscsi_conn_authenticated(). An initiator can therefore send a first
Login PDU with CSG=1, TSIH=0 and no CHAP exchange, carrying the
InitiatorName and ISID of an existing session. The target reinstates
that session, which tears down the legitimate initiator's connection.
Only afterwards does it reject the login with AUTH_FAILED.

iscsi_check_for_session_reinstatement() matches on ISID, InitiatorName
and SessionType only. The InitiatorName is not secret, and open-iscsi
ISIDs are a fixed OUI followed by a small session counter. A remote
peer with no credentials can thus repeatedly disconnect a
CHAP-authenticated session and keep its I/O failing.

The comment above iscsi_target_check_for_existing_instances() already
states the intended invariant:

  NOTE: We check for existing sessions or connections AFTER the initiator
  has been successfully authenticated in order to protect against faked
  ISID/TSIH combinations.

The security-negotiation path (CSG=0) honours this, calling the check
only once authentication completes. Move the CSG=1 call below the
authentication check so both paths behave the same. When
authentication is not required, iscsi_conn_authenticated() returns
true and behaviour is unchanged.

Fixes: e48354ce078c ("iscsi-target: Add iSCSI fabric support for target v4.1")
Cc: stable@vger.kernel.org
Signed-off-by: Praneeth Balasubramanian <praneeth@ucsb.edu>
---
Found by an LLM-based static analysis that checks kernel code against
the rules stated in its comments, as part of research at UCSB SecLab.
The analysis was done with LLM assistance, and this patch was written
with it. I reviewed the patch and tested it as described below.

Testing: two QEMU VMs on linux-next next-20261023 (20a33c6b6cbe). The
target VM runs LIO with a CHAP-required node ACL (generate_node_acls=0,
authentication=1). The victim VM runs open-iscsi with correct CHAP
credentials and continuous direct I/O. From the victim's network, a
script sent 5 credential-free CSG=1/TSIH=0 Login PDUs with the
victim's InitiatorName and ISID.

  Without this patch: 5/5 logged "Normal iSCSI Session SID N is still
  active ... performing session reinstatement" before "Initiator is
  requesting CSG: 1, has not been successfully authenticated ...
  login failed". The victim recorded 79 failed I/O iterations.

  With this patch: 5/5 were rejected with AUTH_FAILED, there were no
  reinstatements, the victim session stayed up, and 63 I/O iterations
  ran with 0 failures.

The code is unchanged in mainline 9ba46df34488 and the patch applies
there. Legitimate reinstatement after successful CHAP still goes through
the CSG=0 path. I have not tested the TSIH != 0 (connection
reinstatement) branch, which is reached from the same call. The
reproducer is available on request.

 drivers/target/iscsi/iscsi_target_nego.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index b03ed154ca34..ccd468e26fb9 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -982,9 +982,6 @@ static int iscsi_target_handle_csg_one(struct iscsit_conn *conn, struct iscsi_lo
 		if (iscsi_target_check_first_request(conn, login) < 0)
 			return -1;
 
-	if (iscsi_target_check_for_existing_instances(conn, login) < 0)
-		return -1;
-
 	ret = iscsi_encode_text_output(
 			PHASE_OPERATIONAL|PHASE_DECLARATIVE,
 			SENDER_TARGET,
@@ -1008,6 +1005,9 @@ static int iscsi_target_handle_csg_one(struct iscsit_conn *conn, struct iscsi_lo
 		return -1;
 	}
 
+	if (iscsi_target_check_for_existing_instances(conn, login) < 0)
+		return -1;
+
 	if (!iscsi_check_negotiated_keys(conn->param_list))
 		if ((login_req->flags & ISCSI_FLAG_LOGIN_NEXT_STAGE3) &&
 		    (login_req->flags & ISCSI_FLAG_LOGIN_TRANSIT))
-- 
2.25.1


                 reply	other threads:[~2026-10-29 20:55 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20261029205456.1211532-1-praneethb2002@gmail.com \
    --to=praneethb2002@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=mkp@kernel.org \
    --cc=praneeth@ucsb.edu \
    --cc=stable@vger.kernel.org \
    --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