From 22cd4fe2ceca0b114ef909298f530c8ab0e7b20e Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Fri, 20 Sep 2019 14:19:28 +0900 Subject: [PATCH] nvmf: Check buffer array overflow in spdk_nvmf_request_get_buffers() This patch makes multi SGL case possible to call spdk_nvmf_request_get_buffers() per WR. Signed-off-by: Shuhei Matsumoto Change-Id: I977ebb0c6b2a67218c9b6fc20dc26a93a6ec770b Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/468943 Tested-by: SPDK CI Jenkins Reviewed-by: Alexey Marchuk Reviewed-by: Ben Walker Reviewed-by: Jim Harris Reviewed-by: Seth Howell --- lib/nvmf/rdma.c | 12 ++++-------- lib/nvmf/transport.c | 7 +++++++ test/unit/lib/nvmf/rdma.c/rdma_ut.c | 7 +++++++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/nvmf/rdma.c b/lib/nvmf/rdma.c index ff798a9c0..e8ad4416a 100644 --- a/lib/nvmf/rdma.c +++ b/lib/nvmf/rdma.c @@ -1754,15 +1754,11 @@ nvmf_rdma_request_fill_iovs_multi_sgl(struct spdk_nvmf_rdma_transport *rtranspor num_buffers += SPDK_CEIL_DIV(desc->keyed.length, rtransport->transport.opts.io_unit_size); desc++; } - /* If the number of buffers is too large, then we know the I/O is larger than allowed. Fail it. */ - if (num_buffers > NVMF_REQ_MAX_BUFFERS) { + rc = spdk_nvmf_request_get_buffers(req, &rgroup->group, &rtransport->transport, + num_buffers); + if (rc != 0) { nvmf_rdma_request_free_data(rdma_req, rtransport); - return -EINVAL; - } - if (spdk_nvmf_request_get_buffers(req, &rgroup->group, &rtransport->transport, - num_buffers) != 0) { - nvmf_rdma_request_free_data(rdma_req, rtransport); - return -ENOMEM; + return rc; } /* The first WR must always be the embedded data WR. This is how we unwind them later. */ diff --git a/lib/nvmf/transport.c b/lib/nvmf/transport.c index 3f852a350..8611e2f57 100644 --- a/lib/nvmf/transport.c +++ b/lib/nvmf/transport.c @@ -397,6 +397,13 @@ spdk_nvmf_request_get_buffers(struct spdk_nvmf_request *req, { uint32_t i = 0; + /* If the number of buffers is too large, then we know the I/O is larger than allowed. + * Fail it. + */ + if (num_buffers + req->num_buffers > NVMF_REQ_MAX_BUFFERS) { + return -EINVAL; + } + while (i < num_buffers) { if (!(STAILQ_EMPTY(&group->buf_cache))) { group->buf_cache_count--; diff --git a/test/unit/lib/nvmf/rdma.c/rdma_ut.c b/test/unit/lib/nvmf/rdma.c/rdma_ut.c index 4d8dc4a04..359ee5e39 100644 --- a/test/unit/lib/nvmf/rdma.c/rdma_ut.c +++ b/test/unit/lib/nvmf/rdma.c/rdma_ut.c @@ -111,6 +111,13 @@ spdk_nvmf_request_get_buffers(struct spdk_nvmf_request *req, { uint32_t i = 0; + /* If the number of buffers is too large, then we know the I/O is larger than allowed. + * Fail it. + */ + if (num_buffers + req->num_buffers > NVMF_REQ_MAX_BUFFERS) { + return -EINVAL; + } + while (i < num_buffers) { if (!(STAILQ_EMPTY(&group->buf_cache))) { group->buf_cache_count--;