Commit 972e0093 authored by Maurizio Lombardi's avatar Maurizio Lombardi Committed by sanglipeng
Browse files

scsi: target: iscsi: Prevent login threads from racing between each other

stable inclusion
from stable-v5.10.186
commit 2b43198de03f1694a36b21ec26e26745b2019a3d
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8J4KH

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=2b43198de03f1694a36b21ec26e26745b2019a3d



--------------------------------

[ Upstream commit 2a737d3b ]

The tpg->np_login_sem is a semaphore that is used to serialize the login
process when multiple login threads run concurrently against the same
target portal group.

The iscsi_target_locate_portal() function finds the tpg, calls
iscsit_access_np() against the np_login_sem semaphore and saves the tpg
pointer in conn->tpg;

If iscsi_target_locate_portal() fails, the caller will check for the
conn->tpg pointer and, if it's not NULL, then it will assume that
iscsi_target_locate_portal() called iscsit_access_np() on the semaphore.

Make sure that conn->tpg gets initialized only if iscsit_access_np() was
successful, otherwise iscsit_deaccess_np() may end up being called against
a semaphore we never took, allowing more than one thread to access the same
tpg.

Signed-off-by: default avatarMaurizio Lombardi <mlombard@redhat.com>
Link: https://lore.kernel.org/r/20230508162219.1731964-4-mlombard@redhat.com


Reviewed-by: default avatarMike Christie <michael.christie@oracle.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarsanglipeng <sanglipeng1@jd.com>
parent a4b18c25
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -1079,6 +1079,7 @@ int iscsi_target_locate_portal(
	iscsi_target_set_sock_callbacks(conn);

	login->np = np;
	conn->tpg = NULL;

	login_req = (struct iscsi_login_req *) login->req;
	payload_length = ntoh24(login_req->dlength);
@@ -1148,7 +1149,6 @@ int iscsi_target_locate_portal(
	 */
	sessiontype = strncmp(s_buf, DISCOVERY, 9);
	if (!sessiontype) {
		conn->tpg = iscsit_global->discovery_tpg;
		if (!login->leading_connection)
			goto get_target;

@@ -1165,9 +1165,11 @@ int iscsi_target_locate_portal(
		 * Serialize access across the discovery struct iscsi_portal_group to
		 * process login attempt.
		 */
		conn->tpg = iscsit_global->discovery_tpg;
		if (iscsit_access_np(np, conn->tpg) < 0) {
			iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
				ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE);
			conn->tpg = NULL;
			ret = -1;
			goto out;
		}