diff --git a/lib/nvme/nvme_rdma.c b/lib/nvme/nvme_rdma.c index d1264caf75..af1e5232d9 100644 --- a/lib/nvme/nvme_rdma.c +++ b/lib/nvme/nvme_rdma.c @@ -1634,12 +1634,18 @@ nvme_rdma_build_sgl_request(struct nvme_rdma_qpair *rqpair, * Otherwise, The SGL descriptor embedded in the command must point to the list of * SGL descriptors used to describe the operation. In that case it is a last segment descriptor. */ - rdma_req->send_sgl[0].length = sizeof(struct spdk_nvme_cmd) + sizeof(struct - spdk_nvme_sgl_descriptor) * num_sgl_desc; + uint32_t descriptors_size = sizeof(struct spdk_nvme_sgl_descriptor) * num_sgl_desc; + + if (spdk_unlikely(descriptors_size > rqpair->qpair.ctrlr->ioccsz_bytes)) { + SPDK_ERRLOG("Size of SGL descriptors (%u) exceeds ICD (%u)\n", + descriptors_size, rqpair->qpair.ctrlr->ioccsz_bytes); + return -1; + } + rdma_req->send_sgl[0].length = sizeof(struct spdk_nvme_cmd) + descriptors_size; req->cmd.dptr.sgl1.unkeyed.type = SPDK_NVME_SGL_TYPE_LAST_SEGMENT; req->cmd.dptr.sgl1.unkeyed.subtype = SPDK_NVME_SGL_SUBTYPE_OFFSET; - req->cmd.dptr.sgl1.unkeyed.length = num_sgl_desc * sizeof(struct spdk_nvme_sgl_descriptor); + req->cmd.dptr.sgl1.unkeyed.length = descriptors_size; req->cmd.dptr.sgl1.address = (uint64_t)0; } diff --git a/test/unit/lib/nvme/nvme_rdma.c/nvme_rdma_ut.c b/test/unit/lib/nvme/nvme_rdma.c/nvme_rdma_ut.c index 8342e84d33..18e63a1897 100644 --- a/test/unit/lib/nvme/nvme_rdma.c/nvme_rdma_ut.c +++ b/test/unit/lib/nvme/nvme_rdma.c/nvme_rdma_ut.c @@ -126,6 +126,7 @@ test_nvme_rdma_build_sgl_request(void) ctrlr.max_sges = NVME_RDMA_MAX_SGL_DESCRIPTORS; ctrlr.cdata.nvmf_specific.msdbd = 16; + ctrlr.ioccsz_bytes = 4096; rqpair.mr_map = &rmap; rqpair.qpair.ctrlr = &ctrlr; @@ -208,6 +209,17 @@ test_nvme_rdma_build_sgl_request(void) bio.iovs[1].iov_len = 1 << 24; rc = nvme_rdma_build_sgl_request(&rqpair, &rdma_req); SPDK_CU_ASSERT_FATAL(rc != 0); + + /* Test case 6: 4 SGL descriptors, size of SGL descriptors exceeds ICD. Expected: FAIL */ + ctrlr.ioccsz_bytes = 60; + bio.iovpos = 0; + req.payload_offset = 0; + req.payload_size = 0x4000; + for (i = 0; i < 4; i++) { + bio.iovs[i].iov_len = 0x1000; + } + rc = nvme_rdma_build_sgl_request(&rqpair, &rdma_req); + SPDK_CU_ASSERT_FATAL(rc == -1); } static void