[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>
This commit is contained in:
Andrew Vasquez 2010-02-18 10:07:26 -08:00 коммит произвёл James Bottomley
Родитель 55e5ed273d
Коммит 715848ca6f
3 изменённых файлов: 0 добавлений и 41 удалений

Просмотреть файл

@ -1531,8 +1531,6 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
fcport->vha->hw->isp_ops->fabric_logout(fcport->vha,
fcport->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa);
qla2x00_abort_fcport_cmds(fcport);
}
static int

Просмотреть файл

@ -96,7 +96,6 @@ extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32);
extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *);
extern void qla2x00_abort_fcport_cmds(fc_port_t *);
extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *,
struct qla_hw_data *);
extern void qla2x00_free_host(struct scsi_qla_host *);

Просмотреть файл

@ -682,44 +682,6 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha)
return (return_status);
}
void
qla2x00_abort_fcport_cmds(fc_port_t *fcport)
{
int cnt;
unsigned long flags;
srb_t *sp;
scsi_qla_host_t *vha = fcport->vha;
struct qla_hw_data *ha = vha->hw;
struct req_que *req;
spin_lock_irqsave(&ha->hardware_lock, flags);
req = vha->req;
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
sp = req->outstanding_cmds[cnt];
if (!sp)
continue;
if (sp->fcport != fcport)
continue;
if (sp->ctx)
continue;
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (ha->isp_ops->abort_command(sp)) {
DEBUG2(qla_printk(KERN_WARNING, ha,
"Abort failed -- %lx\n",
sp->cmd->serial_number));
} else {
if (qla2x00_eh_wait_on_command(sp->cmd) !=
QLA_SUCCESS)
DEBUG2(qla_printk(KERN_WARNING, ha,
"Abort failed while waiting -- %lx\n",
sp->cmd->serial_number));
}
spin_lock_irqsave(&ha->hardware_lock, flags);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
/**************************************************************************
* qla2xxx_eh_abort
*