| From 00fe717ee1ea3c2979db4f94b1533c57aed8dea9 Mon Sep 17 00:00:00 2001 |
| From: Arun Easi <aeasi@marvell.com> |
| Date: Thu, 23 Jan 2020 20:50:14 -0800 |
| Subject: scsi: qla2xxx: Fix unbound NVME response length |
| |
| From: Arun Easi <aeasi@marvell.com> |
| |
| commit 00fe717ee1ea3c2979db4f94b1533c57aed8dea9 upstream. |
| |
| 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 |
| Link: https://lore.kernel.org/r/20200124045014.23554-1-hmadhani@marvell.com |
| Signed-off-by: Arun Easi <aeasi@marvell.com> |
| Signed-off-by: Himanshu Madhani <hmadhani@marvell.com> |
| Reviewed-by: Ewan D. Milne <emilne@redhat.com> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/scsi/qla2xxx/qla_dbg.c | 6 ------ |
| drivers/scsi/qla2xxx/qla_dbg.h | 6 ++++++ |
| drivers/scsi/qla2xxx/qla_isr.c | 12 ++++++++++++ |
| 3 files changed, 18 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/scsi/qla2xxx/qla_dbg.c |
| +++ b/drivers/scsi/qla2xxx/qla_dbg.c |
| @@ -2520,12 +2520,6 @@ qla83xx_fw_dump_failed: |
| /* Driver Debug Functions. */ |
| /****************************************************************************/ |
| |
| -static inline int |
| -ql_mask_match(uint32_t level) |
| -{ |
| - return (level & ql2xextended_error_logging) == level; |
| -} |
| - |
| /* |
| * This function is for formatting and logging debug information. |
| * It is to be used when vha is available. It formats the message |
| --- a/drivers/scsi/qla2xxx/qla_dbg.h |
| +++ b/drivers/scsi/qla2xxx/qla_dbg.h |
| @@ -374,3 +374,9 @@ extern int qla24xx_dump_ram(struct qla_h |
| extern void qla24xx_pause_risc(struct device_reg_24xx __iomem *, |
| struct qla_hw_data *); |
| extern int qla24xx_soft_reset(struct qla_hw_data *); |
| + |
| +static inline int |
| +ql_mask_match(uint level) |
| +{ |
| + return (level & ql2xextended_error_logging) == level; |
| +} |
| --- a/drivers/scsi/qla2xxx/qla_isr.c |
| +++ b/drivers/scsi/qla2xxx/qla_isr.c |
| @@ -1876,6 +1876,18 @@ static void qla24xx_nvme_iocb_entry(scsi |
| 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 > |
| + sizeof(struct nvme_fc_ersp_iu))) { |
| + if (ql_mask_match(ql_dbg_io)) { |
| + 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++); |