From: Mike Christie michael.christie@oracle.com
mainline inclusion from mainline-v5.14-rc1 commit d39df158518ccc3bf24ee18082b5e100c8f014aa category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9R4O4 CVE: CVE-2021-47427
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
If SCSI midlayer is aborting a task when we are tearing down the conn we could free the conn while the abort thread is accessing the conn. This has the abort handler get a ref to the conn so it won't be freed from under it.
Note: this is not needed for device/target reset because we are holding the eh_mutex when accessing the conn.
Link: https://lore.kernel.org/r/20210525181821.7617-12-michael.christie@oracle.com Reviewed-by: Lee Duncan lduncan@suse.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Li Nan linan122@huawei.com --- drivers/scsi/libiscsi.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 72463874d7b4..fe685178ade7 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2300,6 +2300,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) }
conn = session->leadconn; + iscsi_get_conn(conn->cls_conn); conn->eh_abort_cnt++; age = session->age;
@@ -2310,9 +2311,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) ISCSI_DBG_EH(session, "sc completed while abort in progress\n");
spin_unlock(&session->back_lock); - spin_unlock_bh(&session->frwd_lock); - mutex_unlock(&session->eh_mutex); - return SUCCESS; + goto success; } ISCSI_DBG_EH(session, "aborting [sc %p itt 0x%x]\n", sc, task->itt); __iscsi_get_task(task); @@ -2379,6 +2378,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) ISCSI_DBG_EH(session, "abort success [sc %p itt 0x%x]\n", sc, task->itt); iscsi_put_task(task); + iscsi_put_conn(conn->cls_conn); mutex_unlock(&session->eh_mutex); return SUCCESS;
@@ -2388,6 +2388,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) ISCSI_DBG_EH(session, "abort failed [sc %p itt 0x%x]\n", sc, task ? task->itt : 0); iscsi_put_task(task); + iscsi_put_conn(conn->cls_conn); mutex_unlock(&session->eh_mutex); return FAILED; }