提交 625d7a43 编写于 作者: L Lee Duncan 提交者: Xie XiuQi

scsi: libiscsi: Hold back_lock when calling iscsi_complete_task

mainline inclusion
from mainline-5.1-rc1
commit a656183e
category: bugfix
bugzilla: 12855
CVE: NA

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

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.
Signed-off-by: NLee Duncan <lduncan@suse.com>
Acked-by: NChris Leech <cleech@redhat.com>
Signed-off-by: NMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Nzheng liang <zhengliang6@huawei.com>
Reviewed-by: NJason Yan <yanaijie@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 db330491
...@@ -828,7 +828,7 @@ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); ...@@ -828,7 +828,7 @@ EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
* @datalen: len of buffer * @datalen: len of buffer
* *
* iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and * 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, static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
struct iscsi_task *task, char *data, struct iscsi_task *task, char *data,
...@@ -931,6 +931,9 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, ...@@ -931,6 +931,9 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
* @conn: iscsi connection * @conn: iscsi connection
* @hdr: iscsi pdu * @hdr: iscsi pdu
* @task: scsi command task * @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 static void
iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
...@@ -1015,6 +1018,16 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) ...@@ -1015,6 +1018,16 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
return 0; 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, static int iscsi_nop_out_rsp(struct iscsi_task *task,
struct iscsi_nopin *nop, char *data, int datalen) struct iscsi_nopin *nop, char *data, int datalen)
{ {
...@@ -1787,7 +1800,9 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) ...@@ -1787,7 +1800,9 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
return 0; return 0;
prepd_reject: prepd_reject:
spin_lock_bh(&session->back_lock);
iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ); iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
spin_unlock_bh(&session->back_lock);
reject: reject:
spin_unlock_bh(&session->frwd_lock); spin_unlock_bh(&session->frwd_lock);
ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
...@@ -1795,7 +1810,9 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) ...@@ -1795,7 +1810,9 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc)
return SCSI_MLQUEUE_TARGET_BUSY; return SCSI_MLQUEUE_TARGET_BUSY;
prepd_fault: prepd_fault:
spin_lock_bh(&session->back_lock);
iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ); iscsi_complete_task(task, ISCSI_TASK_REQUEUE_SCSIQ);
spin_unlock_bh(&session->back_lock);
fault: fault:
spin_unlock_bh(&session->frwd_lock); spin_unlock_bh(&session->frwd_lock);
ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
...@@ -3117,8 +3134,9 @@ fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn) ...@@ -3117,8 +3134,9 @@ fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn)
state = ISCSI_TASK_ABRT_SESS_RECOV; state = ISCSI_TASK_ABRT_SESS_RECOV;
if (task->state == ISCSI_TASK_PENDING) if (task->state == ISCSI_TASK_PENDING)
state = ISCSI_TASK_COMPLETED; state = ISCSI_TASK_COMPLETED;
spin_lock_bh(&session->back_lock);
iscsi_complete_task(task, state); iscsi_complete_task(task, state);
spin_unlock_bh(&session->back_lock);
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册