Received: by 2002:ac0:946b:0:0:0:0:0 with SMTP id j40csp3852258imj; Tue, 19 Feb 2019 10:32:23 -0800 (PST) X-Google-Smtp-Source: AHgI3IZ++XdlIBp048WnedtiS5bNVP84y4wy8dHFw4IlumG+XQObkusXcO9o0nalNrYQzP7m2C6w X-Received: by 2002:a65:5cc7:: with SMTP id b7mr5848375pgt.396.1550601143347; Tue, 19 Feb 2019 10:32:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1550601143; cv=none; d=google.com; s=arc-20160816; b=XMWZdCLIAH87992bxL0PeIYTatp8wH0H2EHxKCMfj/rJyqT59ERKz2SpDwqmuJEcXZ v5PSiVbZahQgCNQ9zHhXc83hnIPKiBabZc7clmwUyQjTe1pA1d8Y/qxdLMRlvh5UScCP nEBtKgEt3pFCRDTv+mYE3u806shoTwuBfHT81MInN7ZJwERm2BVBnyKGDLnCO4q6DKI9 e+x/qjwBmozwnQcnwusoRya/puBs0gLuT0K1L+YU0DgsIJ/l0ZuoLgMgfbihyEsaNRR6 jbZP18DY5SodqXsMk5n3zl1DmobBEQ3D+Fk9/Hmsnv6FMJ+L8+sqFvKuD9d9+C6H22VO FZTw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from; bh=mlK1G34lScJ4EIMVXw+NhGg7k0uSfORTk0Lq/TmF46s=; b=0k2v4xOlcgPZfzINu8op9WBvfv3GXyAt6kRytcbv5OiQnqHsOPYZoTdZwRgYTHzXTj Zr7JZgFzWVPANAy3UbqKIM55V25nJIN2QnkW+RnALrGrEh0NBF4dNj0YD6BVSCjf1vvP mItYVWm/7y5juomH1JzE28fmkIaFcdrClI4G2n1vA7Y/g6wIOQx/fkXYju2mvSTBtKJ4 Cl4SbyLPwoaq62hEC5PKh3k0nM2lEnLesnUA0rn8rgL0RXtTnNJfhrmMD0PZqrDkz+5P tlyIGoxzQTqZyqeoinNHdETmx/JkDl82oTnUDHbrubbSR8k0CV5UBGSwavjd7PNDNx8f 7lMw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 62si15417198pgb.298.2019.02.19.10.32.07; Tue, 19 Feb 2019 10:32:23 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727470AbfBSS3p (ORCPT + 99 others); Tue, 19 Feb 2019 13:29:45 -0500 Received: from mx2.suse.de ([195.135.220.15]:47744 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726605AbfBSS3p (ORCPT ); Tue, 19 Feb 2019 13:29:45 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 57D80AC89; Tue, 19 Feb 2019 18:29:44 +0000 (UTC) Received: by localhost (Postfix, from userid 1000) id A7EF31057D9; Tue, 19 Feb 2019 10:29:42 -0800 (PST) From: Lee Duncan To: Linux SCSI , Linux Kernel , Chris Leech Cc: hare@suse.de, Lee Duncan Subject: [PATCH] Hold back_lock when calling iscsi_complete_task Date: Tue, 19 Feb 2019 10:29:14 -0800 Message-Id: <20190219182914.3173-1-leeman.duncan@gmail.com> X-Mailer: git-send-email 2.16.4 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Lee Duncan If there is an error queueing an iscsi command in iscsi_queuecommand(), for example if the transport fails to take the command in sessuin->tt->xmit_task(), then the error path can call iscsi_complete_task() without first aquiring the back_lock as required. This can lead to things like ITT pool can get corrupt, resulting in duplicate ITTs being sent out. The solution is to hold the back_lock around iscsi_complete_task() calls, and to add a little commenting to help others understand when back_lock must be held. --- drivers/scsi/libiscsi.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index b8d325ce8754..ef7871e8c6bd 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -838,7 +838,7 @@ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); * @datalen: len of buffer * * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and - * then completes the command and task. + * then completes the command and task. called under back_lock **/ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, struct iscsi_task *task, char *data, @@ -941,6 +941,9 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, * @conn: iscsi connection * @hdr: iscsi pdu * @task: scsi command task + * + * iscsi_data_in_rsp sets up the scsi_cmnd fields based on the data received + * then completes the command and task. called under back_lock **/ static void iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, @@ -1025,6 +1028,16 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) return 0; } +/** + * iscsi_nop_out_rsp - SCSI NOP Response processing + * @task: scsi command task + * @nop: the nop structure + * @data: where to put the data + * @datalen: length of data + * + * iscsi_nop_out_rsp handles nop response from use or + * from user space. called under back_lock + **/ static int iscsi_nop_out_rsp(struct iscsi_task *task, struct iscsi_nopin *nop, char *data, int datalen) { @@ -1791,7 +1804,9 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) return 0; prepd_reject: + spin_lock_bh(&session->back_lock); iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ); + spin_unlock_bh(&session->back_lock); reject: spin_unlock_bh(&session->frwd_lock); ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", @@ -1799,7 +1814,9 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) return SCSI_MLQUEUE_TARGET_BUSY; prepd_fault: + spin_lock_bh(&session->back_lock); iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ); + spin_unlock_bh(&session->back_lock); fault: spin_unlock_bh(&session->frwd_lock); ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", @@ -3121,8 +3138,9 @@ fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn) state = ISCSI_TASK_ABRT_SESS_RECOV; if (task->state == ISCSI_TASK_PENDING) state = ISCSI_TASK_COMPLETED; + spin_lock_bh(&session->back_lock); iscsi_complete_task(task, state); - + spin_unlock_bh(&session->back_lock); } } -- 2.16.4