Message ID | 20200117203126.4738-1-hmadhani@marvell.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [v3] qla2xxx: Fix unbound NVME response length | expand |
On Fri, 2020-01-17 at 12:31 -0800, Himanshu Madhani wrote: > From: Arun Easi <aeasi@marvell.com> > > On certain cases when response length is less than 32, NVME response data > is supplied inline in IOCB. This is indicated by some combination of state > flags. There was an instance when a high, and incorrect, response length was > indicated causing driver to overrun buffers. Fix this by checking and > limiting the response payload length. > > Fixes: 7401bc18d1ee3 ("scsi: qla2xxx: Add FC-NVMe command handling") > Cc: stable@vger.kernel.org > Signed-off-by: Arun Easi <aeasi@marvell.com> > Signed-off-by: Himanshu Madhani <hmadhani@marvell.com> > --- > Hi Martin, > > We discovered issue with our newer Gen7 adapter when response length > happens to be larger than 32 bytes, could result into crash. > > Please apply this to 5.5/scsi-fixes branch at your earliest convenience. > > Changes from v2 -> v3 > > o Use "sizeof(struct nvme_fc_ersp_iu)" to indicate response payload size. > > Changes from v1 -> v2 > > o Fixed the tag for stable. > o Removed logit which got spilled from other patch to prevent compile failure. > > Thanks, > Himanshu > --- > drivers/scsi/qla2xxx/qla_isr.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > > diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c > index e7bad0bfffda..2f26f8910d0b 100644 > --- a/drivers/scsi/qla2xxx/qla_isr.c > +++ b/drivers/scsi/qla2xxx/qla_isr.c > @@ -1939,6 +1939,15 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, > inbuf = (uint32_t *)&sts->nvme_ersp_data; > outbuf = (uint32_t *)fd->rspaddr; > iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len); > + if (unlikely(iocb->u.nvme.rsp_pyld_len > 32)) { I think this should have been "> sizeof(struct nvme_fc_ersp_iu)" as well. -Ewan > + WARN_ONCE(1, "Unexpected response payload length %u.\n", > + iocb->u.nvme.rsp_pyld_len); > + ql_log(ql_log_warn, fcport->vha, 0x5100, > + "Unexpected response payload length %u.\n", > + iocb->u.nvme.rsp_pyld_len); > + iocb->u.nvme.rsp_pyld_len = > + sizeof(struct nvme_fc_ersp_iu); > + } > iter = iocb->u.nvme.rsp_pyld_len >> 2; > for (; iter; iter--) > *outbuf++ = swab32(*inbuf++);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index e7bad0bfffda..2f26f8910d0b 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1939,6 +1939,15 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, inbuf = (uint32_t *)&sts->nvme_ersp_data; outbuf = (uint32_t *)fd->rspaddr; iocb->u.nvme.rsp_pyld_len = le16_to_cpu(sts->nvme_rsp_pyld_len); + if (unlikely(iocb->u.nvme.rsp_pyld_len > 32)) { + WARN_ONCE(1, "Unexpected response payload length %u.\n", + iocb->u.nvme.rsp_pyld_len); + ql_log(ql_log_warn, fcport->vha, 0x5100, + "Unexpected response payload length %u.\n", + iocb->u.nvme.rsp_pyld_len); + iocb->u.nvme.rsp_pyld_len = + sizeof(struct nvme_fc_ersp_iu); + } iter = iocb->u.nvme.rsp_pyld_len >> 2; for (; iter; iter--) *outbuf++ = swab32(*inbuf++);