From: James Smart Date: Tue, 26 Jun 2018 15:24:29 +0000 (-0700) Subject: scsi: lpfc: devloss timeout race condition caused null pointer reference X-Git-Tag: v4.1.12-124.31.3~440 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=31d475899607993be2e615fd31ec5f2a703c95c8;p=users%2Fjedix%2Flinux-maple.git scsi: lpfc: devloss timeout race condition caused null pointer reference Orabug: 27994179 A race condition between the context of devloss timeout handler and I/O completion caused devloss timeout handler de-referencing pointer that had been released. Added the check in lpfc_sli_validate_fcp_iocb() on LPFC_IO_ON_TXCMPLQ to capture the race condition of I/O completion and devloss timeout handler attemption for aborting the I/O. Also, added check on lpfc_cmd->rdata pointer before de-referenceing lpfc_cmd->rdata->pnode. Also, added protection in lpfc_sli_abort_iocb() routine on driver performed FCP I/O FLUSHING already under way before proceeding to aborting I/Os. Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen (cherry picked from commit b0e830125b669570d8096b8ba22eb00f659fc05e) Signed-off-by: Dan Duval Reviewed-by: Brian Maly Signed-off-by: Brian Maly --- diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 4f32e67dfc2bc..13e49e29dc533 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -4526,6 +4526,11 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) int err; rdata = lpfc_rport_data_from_scsi_device(cmnd->device); + + /* sanity check on references */ + if (unlikely(!rdata) || unlikely(!rport)) + goto out_fail_command; + err = fc_remote_port_chkready(rport); if (err) { cmnd->result = err; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 9dfe292228a61..c7467de53dcf5 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -10186,10 +10186,11 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd; int rc = 1; - if (!(iocbq->iocb_flag & LPFC_IO_FCP)) + if (iocbq->vport != vport) return rc; - if (iocbq->vport != vport) + if (!(iocbq->iocb_flag & LPFC_IO_FCP) || + !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ)) return rc; lpfc_cmd = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq); @@ -10199,13 +10200,13 @@ lpfc_sli_validate_fcp_iocb(struct lpfc_iocbq *iocbq, struct lpfc_vport *vport, switch (ctx_cmd) { case LPFC_CTX_LUN: - if ((lpfc_cmd->rdata->pnode) && + if ((lpfc_cmd->rdata) && (lpfc_cmd->rdata->pnode) && (lpfc_cmd->rdata->pnode->nlp_sid == tgt_id) && (scsilun_to_int(&lpfc_cmd->fcp_cmnd->fcp_lun) == lun_id)) rc = 0; break; case LPFC_CTX_TGT: - if ((lpfc_cmd->rdata->pnode) && + if ((lpfc_cmd->rdata) && (lpfc_cmd->rdata->pnode) && (lpfc_cmd->rdata->pnode->nlp_sid == tgt_id)) rc = 0; break; @@ -10319,6 +10320,10 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, int errcnt = 0, ret_val = 0; int i; + /* all I/Os are in process of being flushed */ + if (phba->hba_flag & HBA_FCP_IOQ_FLUSH) + return errcnt; + for (i = 1; i <= phba->sli.last_iotag; i++) { iocbq = phba->sli.iocbq_lookup[i];