nvmf/vfio-user: fix lookup_io_q & some off-by-ones

lookup_io_q() should return NULL when qid == 0 (admin queue). This
ensures that handle_del_io_q() won't delete the admin queue (which is
prohibited by the spec) and fixes #2172.

Also fixes a few related off-by-one errors.

Signed-off-by: Andreas Economides <andreas.economides@nutanix.com>
Change-Id: I7ab063f25bba45b755d84c9ddde82072cf01f5e8
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9593
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Andreas Economides 2021-09-23 13:22:30 +00:00 committed by Changpeng Liu
parent deb14d9cd2
commit 5cd558f383

View File

@ -906,7 +906,7 @@ lookup_io_q(struct nvmf_vfio_user_ctrlr *ctrlr, const uint16_t qid, const bool i
assert(ctrlr != NULL); assert(ctrlr != NULL);
if (qid > NVMF_VFIO_USER_DEFAULT_MAX_QPAIRS_PER_CTRLR) { if (qid == 0 || qid >= NVMF_VFIO_USER_DEFAULT_MAX_QPAIRS_PER_CTRLR) {
return NULL; return NULL;
} }
@ -1110,7 +1110,7 @@ handle_create_io_q(struct nvmf_vfio_user_ctrlr *ctrlr,
assert(cmd != NULL); assert(cmd != NULL);
qid = cmd->cdw10_bits.create_io_q.qid; qid = cmd->cdw10_bits.create_io_q.qid;
if (qid >= NVMF_VFIO_USER_DEFAULT_MAX_QPAIRS_PER_CTRLR) { if (qid == 0 || qid >= NVMF_VFIO_USER_DEFAULT_MAX_QPAIRS_PER_CTRLR) {
SPDK_ERRLOG("%s: invalid QID=%d, max=%d\n", ctrlr_id(ctrlr), SPDK_ERRLOG("%s: invalid QID=%d, max=%d\n", ctrlr_id(ctrlr),
qid, NVMF_VFIO_USER_DEFAULT_MAX_QPAIRS_PER_CTRLR); qid, NVMF_VFIO_USER_DEFAULT_MAX_QPAIRS_PER_CTRLR);
sct = SPDK_NVME_SCT_COMMAND_SPECIFIC; sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
@ -1263,7 +1263,7 @@ handle_del_io_q(struct nvmf_vfio_user_ctrlr *ctrlr,
cmd->cdw10_bits.delete_io_q.qid); cmd->cdw10_bits.delete_io_q.qid);
if (lookup_io_q(ctrlr, cmd->cdw10_bits.delete_io_q.qid, is_cq) == NULL) { if (lookup_io_q(ctrlr, cmd->cdw10_bits.delete_io_q.qid, is_cq) == NULL) {
SPDK_ERRLOG("%s: %cQ%d does not exist\n", ctrlr_id(ctrlr), SPDK_ERRLOG("%s: I/O %cQ%d does not exist\n", ctrlr_id(ctrlr),
is_cq ? 'C' : 'S', cmd->cdw10_bits.delete_io_q.qid); is_cq ? 'C' : 'S', cmd->cdw10_bits.delete_io_q.qid);
sct = SPDK_NVME_SCT_COMMAND_SPECIFIC; sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
sc = SPDK_NVME_SC_INVALID_QUEUE_IDENTIFIER; sc = SPDK_NVME_SC_INVALID_QUEUE_IDENTIFIER;
@ -1641,7 +1641,7 @@ handle_dbl_access(struct nvmf_vfio_user_ctrlr *ctrlr, uint32_t *buf,
/* convert byte offset to array index */ /* convert byte offset to array index */
pos >>= 2; pos >>= 2;
if (pos > NVMF_VFIO_USER_DEFAULT_MAX_QPAIRS_PER_CTRLR * 2) { if (pos >= NVMF_VFIO_USER_DEFAULT_MAX_QPAIRS_PER_CTRLR * 2) {
SPDK_ERRLOG("%s: bad doorbell index %#lx\n", ctrlr_id(ctrlr), pos); SPDK_ERRLOG("%s: bad doorbell index %#lx\n", ctrlr_id(ctrlr), pos);
errno = EINVAL; errno = EINVAL;
return -1; return -1;