diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2010-02-18 13:07:26 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-02-19 11:46:35 -0500 |
commit | 715848ca6fffeb6362a50887d9c26245bd5dfba9 (patch) | |
tree | 36ac766a39b039402f948b092f771bf00fbf3cf3 /drivers/scsi | |
parent | 55e5ed273d758c62d2f1fad47c73716039f7c01c (diff) |
[SCSI] qla2xxx: Correct use-after-free issue in terminate_rport_io callback.
The explicit logout (LOGO) issued at the end of the callback will
flush (via normal scsi_cmnd->done()) any outstanding commands
(FCP2) the firmware is holding. While iterating through the
outstanding_cmnd array in qla2x00_abort_fcport_cmds(), locking
and unlocking of the hardware spinlock, opens-up the driver to
cases where the processed SRB (sp) could be used after the
command completed from interrupt context.
Cc: stable@kernel.org
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 38 |
3 files changed, 0 insertions, 41 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 25596feea162..90d1e062ec4f 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -1531,8 +1531,6 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) | |||
1531 | fcport->vha->hw->isp_ops->fabric_logout(fcport->vha, | 1531 | fcport->vha->hw->isp_ops->fabric_logout(fcport->vha, |
1532 | fcport->loop_id, fcport->d_id.b.domain, | 1532 | fcport->loop_id, fcport->d_id.b.domain, |
1533 | fcport->d_id.b.area, fcport->d_id.b.al_pa); | 1533 | fcport->d_id.b.area, fcport->d_id.b.al_pa); |
1534 | |||
1535 | qla2x00_abort_fcport_cmds(fcport); | ||
1536 | } | 1534 | } |
1537 | 1535 | ||
1538 | static int | 1536 | static int |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index b42e704bdca9..238f353b6b42 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -96,7 +96,6 @@ extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32); | |||
96 | 96 | ||
97 | extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); | 97 | extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); |
98 | 98 | ||
99 | extern void qla2x00_abort_fcport_cmds(fc_port_t *); | ||
100 | extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *, | 99 | extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *, |
101 | struct qla_hw_data *); | 100 | struct qla_hw_data *); |
102 | extern void qla2x00_free_host(struct scsi_qla_host *); | 101 | extern void qla2x00_free_host(struct scsi_qla_host *); |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index d01daa3866f8..7964a11cca26 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -682,44 +682,6 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha) | |||
682 | return (return_status); | 682 | return (return_status); |
683 | } | 683 | } |
684 | 684 | ||
685 | void | ||
686 | qla2x00_abort_fcport_cmds(fc_port_t *fcport) | ||
687 | { | ||
688 | int cnt; | ||
689 | unsigned long flags; | ||
690 | srb_t *sp; | ||
691 | scsi_qla_host_t *vha = fcport->vha; | ||
692 | struct qla_hw_data *ha = vha->hw; | ||
693 | struct req_que *req; | ||
694 | |||
695 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
696 | req = vha->req; | ||
697 | for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { | ||
698 | sp = req->outstanding_cmds[cnt]; | ||
699 | if (!sp) | ||
700 | continue; | ||
701 | if (sp->fcport != fcport) | ||
702 | continue; | ||
703 | if (sp->ctx) | ||
704 | continue; | ||
705 | |||
706 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
707 | if (ha->isp_ops->abort_command(sp)) { | ||
708 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
709 | "Abort failed -- %lx\n", | ||
710 | sp->cmd->serial_number)); | ||
711 | } else { | ||
712 | if (qla2x00_eh_wait_on_command(sp->cmd) != | ||
713 | QLA_SUCCESS) | ||
714 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
715 | "Abort failed while waiting -- %lx\n", | ||
716 | sp->cmd->serial_number)); | ||
717 | } | ||
718 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
719 | } | ||
720 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
721 | } | ||
722 | |||
723 | /************************************************************************** | 685 | /************************************************************************** |
724 | * qla2xxx_eh_abort | 686 | * qla2xxx_eh_abort |
725 | * | 687 | * |