[PATCH 5.14 130/151] scsi: iscsi: Fix iscsi_task use after free

Greg Kroah-Hartman
2021-10-11T14:12:07Z

From: Mike Christie <michael.christie@oracle.com>

[ Upstream commit 258aad75c62146453d03028a44f2f1590d58e1f6 ]

Commit d39df158518c ("scsi: iscsi: Have abort handler get ref to conn")
added iscsi_get_conn()/iscsi_put_conn() calls during abort handling but
then also changed the handling of the case where we detect an already
completed task where we now end up doing a goto to the common put/cleanup
code. This results in a iscsi_task use after free, because the common
cleanup code will do a put on the iscsi_task.

This reverts the goto and moves the iscsi_get_conn() to after we've checked
if the iscsi_task is valid.

Link: https://lore.kernel.org/r/20211004210608.9962-1-michael.christie@oracle.com
Fixes: d39df158518c ("scsi: iscsi: Have abort handler get ref to conn")
Signed-off-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/scsi/libiscsi.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 4683c183e9d4..5bc91d34df63 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -2281,11 +2281,6 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
return FAILED;
}

- conn = session->leadconn;
- iscsi_get_conn(conn->cls_conn);
- conn->eh_abort_cnt++;
- age = session->age;
-
spin_lock(&session->back_lock);
task = (struct iscsi_task *)sc->SCp.ptr;
if (!task || !task->sc) {
@@ -2293,8 +2288,16 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
ISCSI_DBG_EH(session, "sc completed while abort in progress\n");

spin_unlock(&session->back_lock);
- goto success;
+ spin_unlock_bh(&session->frwd_lock);
+ mutex_unlock(&session->eh_mutex);
+ return SUCCESS;
}
+
+ conn = session->leadconn;
+ iscsi_get_conn(conn->cls_conn);
+ conn->eh_abort_cnt++;
+ age = session->age;
+
ISCSI_DBG_EH(session, "aborting [sc %p itt 0x%x]\n", sc, task->itt);
__iscsi_get_task(task);
spin_unlock(&session->back_lock);
--
2.33.0