From 3856d82b50f11d59cd151c4eee9dd3b9155e56fe Mon Sep 17 00:00:00 2001 From: Seth Howell Date: Tue, 23 Apr 2019 15:28:54 -0700 Subject: [PATCH] subsystem: check for NULL bufs in reservation ops. At the RDMA level, we allow processing requests that should contain a data transfer, but specify a length of zero to be passed up the stack without a data buffer. See spdk_nvmf_rdma_request_get_xfer. In the case of the reservation requests, we weren't checking whether req->data was NULL before trying to copy into it causing us to segfault if we got a malformed reservation request. Found when using the fuzzer. Change-Id: I320174ec72a8d298ab6ca44ef6a99691631f00ca Signed-off-by: Seth Howell Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/451786 Tested-by: SPDK CI Jenkins Reviewed-by: Changpeng Liu Reviewed-by: Jim Harris --- lib/nvmf/subsystem.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/lib/nvmf/subsystem.c b/lib/nvmf/subsystem.c index 02e2f7902..aa24e9c24 100644 --- a/lib/nvmf/subsystem.c +++ b/lib/nvmf/subsystem.c @@ -1583,7 +1583,14 @@ nvmf_ns_reservation_register(struct spdk_nvmf_ns *ns, rrega = cmd->cdw10 & 0x7u; iekey = (cmd->cdw10 >> 3) & 0x1u; cptpl = (cmd->cdw10 >> 30) & 0x3u; - memcpy(&key, req->data, sizeof(key)); + + if (req->data && req->length >= sizeof(key)) { + memcpy(&key, req->data, sizeof(key)); + } else { + SPDK_ERRLOG("No key provided. Failing request.\n"); + status = SPDK_NVME_SC_INVALID_FIELD; + goto exit; + } SPDK_DEBUGLOG(SPDK_LOG_NVMF, "REGISTER: RREGA %u, IEKEY %u, CPTPL %u, " "NRKEY 0x%"PRIx64", NRKEY 0x%"PRIx64"\n", @@ -1697,7 +1704,14 @@ nvmf_ns_reservation_acquire(struct spdk_nvmf_ns *ns, racqa = cmd->cdw10 & 0x7u; iekey = (cmd->cdw10 >> 3) & 0x1u; rtype = (cmd->cdw10 >> 8) & 0xffu; - memcpy(&key, req->data, sizeof(key)); + + if (req->data && req->length >= sizeof(key)) { + memcpy(&key, req->data, sizeof(key)); + } else { + SPDK_ERRLOG("No key provided. Failing request.\n"); + status = SPDK_NVME_SC_INVALID_FIELD; + goto exit; + } SPDK_DEBUGLOG(SPDK_LOG_NVMF, "ACQUIRE: RACQA %u, IEKEY %u, RTYPE %u, " "NRKEY 0x%"PRIx64", PRKEY 0x%"PRIx64"\n", @@ -1847,7 +1861,14 @@ nvmf_ns_reservation_release(struct spdk_nvmf_ns *ns, rrela = cmd->cdw10 & 0x7u; iekey = (cmd->cdw10 >> 3) & 0x1u; rtype = (cmd->cdw10 >> 8) & 0xffu; - memcpy(&crkey, req->data, sizeof(crkey)); + + if (req->data && req->length >= sizeof(crkey)) { + memcpy(&crkey, req->data, sizeof(crkey)); + } else { + SPDK_ERRLOG("No key provided. Failing request.\n"); + status = SPDK_NVME_SC_INVALID_FIELD; + goto exit; + } SPDK_DEBUGLOG(SPDK_LOG_NVMF, "RELEASE: RRELA %u, IEKEY %u, RTYPE %u, " "CRKEY 0x%"PRIx64"\n", rrela, iekey, rtype, crkey); @@ -1939,6 +1960,13 @@ nvmf_ns_reservation_report(struct spdk_nvmf_ns *ns, uint32_t regctl = 0; uint8_t status = SPDK_NVME_SC_SUCCESS; + if (req->data == NULL) { + SPDK_ERRLOG("No data transfer specified for request. " + " Unable to transfer back response.\n"); + status = SPDK_NVME_SC_INVALID_FIELD; + goto exit; + } + /* NVMeoF uses Extended Data Structure */ if ((cmd->cdw11 & 0x00000001u) == 0) { SPDK_ERRLOG("NVMeoF uses extended controller data structure, "