From: Praneeth Balasubramanian 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 --- 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