| From 79326481f8cc247a09d2aeeb652df34872b350f4 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 4 Oct 2021 16:06:08 -0500 |
| Subject: scsi: iscsi: Fix iscsi_task use after free |
| |
| 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 |
| |