mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-22 12:33:59 +08:00
[SCSI] qla2xxx: Correct use-after-free oops seen during EH-abort.
Hold a reference to the srb (sp) while aborting an I/O -- as the I/O can/will complete from within the interrupt-context. 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:
parent
7e2b895b93
commit
083a469db4
@ -202,6 +202,7 @@ struct sd_dif_tuple {
|
|||||||
* SCSI Request Block
|
* SCSI Request Block
|
||||||
*/
|
*/
|
||||||
typedef struct srb {
|
typedef struct srb {
|
||||||
|
atomic_t ref_count;
|
||||||
struct fc_port *fcport;
|
struct fc_port *fcport;
|
||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
|
|
||||||
|
@ -517,6 +517,7 @@ qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
|
|||||||
if (!sp)
|
if (!sp)
|
||||||
return sp;
|
return sp;
|
||||||
|
|
||||||
|
atomic_set(&sp->ref_count, 1);
|
||||||
sp->fcport = fcport;
|
sp->fcport = fcport;
|
||||||
sp->cmd = cmd;
|
sp->cmd = cmd;
|
||||||
sp->flags = 0;
|
sp->flags = 0;
|
||||||
@ -797,6 +798,12 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha)
|
|||||||
return (return_status);
|
return (return_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sp_get(struct srb *sp)
|
||||||
|
{
|
||||||
|
atomic_inc(&sp->ref_count);
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* qla2xxx_eh_abort
|
* qla2xxx_eh_abort
|
||||||
*
|
*
|
||||||
@ -825,6 +832,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
|||||||
struct qla_hw_data *ha = vha->hw;
|
struct qla_hw_data *ha = vha->hw;
|
||||||
struct req_que *req = vha->req;
|
struct req_que *req = vha->req;
|
||||||
srb_t *spt;
|
srb_t *spt;
|
||||||
|
int got_ref = 0;
|
||||||
|
|
||||||
fc_block_scsi_eh(cmd);
|
fc_block_scsi_eh(cmd);
|
||||||
|
|
||||||
@ -856,6 +864,10 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
|||||||
DEBUG2(printk("%s(%ld): aborting sp %p from RISC."
|
DEBUG2(printk("%s(%ld): aborting sp %p from RISC."
|
||||||
" pid=%ld.\n", __func__, vha->host_no, sp, serial));
|
" pid=%ld.\n", __func__, vha->host_no, sp, serial));
|
||||||
|
|
||||||
|
/* Get a reference to the sp and drop the lock.*/
|
||||||
|
sp_get(sp);
|
||||||
|
got_ref++;
|
||||||
|
|
||||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
if (ha->isp_ops->abort_command(sp)) {
|
if (ha->isp_ops->abort_command(sp)) {
|
||||||
DEBUG2(printk("%s(%ld): abort_command "
|
DEBUG2(printk("%s(%ld): abort_command "
|
||||||
@ -881,6 +893,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (got_ref)
|
||||||
|
qla2x00_sp_compl(ha, sp);
|
||||||
|
|
||||||
qla_printk(KERN_INFO, ha,
|
qla_printk(KERN_INFO, ha,
|
||||||
"scsi(%ld:%d:%d): Abort command issued -- %d %lx %x.\n",
|
"scsi(%ld:%d:%d): Abort command issued -- %d %lx %x.\n",
|
||||||
vha->host_no, id, lun, wait, serial, ret);
|
vha->host_no, id, lun, wait, serial, ret);
|
||||||
@ -3468,7 +3483,7 @@ qla2x00_sp_free_dma(srb_t *sp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp)
|
qla2x00_sp_final_compl(struct qla_hw_data *ha, srb_t *sp)
|
||||||
{
|
{
|
||||||
struct scsi_cmnd *cmd = sp->cmd;
|
struct scsi_cmnd *cmd = sp->cmd;
|
||||||
|
|
||||||
@ -3489,6 +3504,20 @@ qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp)
|
|||||||
cmd->scsi_done(cmd);
|
cmd->scsi_done(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
qla2x00_sp_compl(struct qla_hw_data *ha, srb_t *sp)
|
||||||
|
{
|
||||||
|
if (atomic_read(&sp->ref_count) == 0) {
|
||||||
|
DEBUG2(qla_printk(KERN_WARNING, ha,
|
||||||
|
"SP reference-count to ZERO -- sp=%p\n", sp));
|
||||||
|
DEBUG2(BUG());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!atomic_dec_and_test(&sp->ref_count))
|
||||||
|
return;
|
||||||
|
qla2x00_sp_final_compl(ha, sp);
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* qla2x00_timer
|
* qla2x00_timer
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user