From 7b68ae1e5ee05da00b99211be59049edafa32a11 Mon Sep 17 00:00:00 2001 From: Jim Harris Date: Wed, 26 Jun 2013 23:32:45 +0000 Subject: [PATCH] Fail any passthrough command whose transfer size exceeds the controller's max transfer size. This guards against rogue commands coming in from userspace. Also add KASSERTS for the virtual address and unmapped bio cases, if the transfer size exceeds the controller's max transfer size. Sponsored by: Intel MFC after: 3 days --- sys/dev/nvme/nvme_ctrlr.c | 10 ++++++++-- sys/dev/nvme/nvme_qpair.c | 7 +++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c index 917a93315737..b27a84ecf5dc 100644 --- a/sys/dev/nvme/nvme_ctrlr.c +++ b/sys/dev/nvme/nvme_ctrlr.c @@ -895,7 +895,13 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr, struct buf *buf = NULL; int ret = 0; - if (pt->len > 0) + if (pt->len > 0) { + if (pt->len > ctrlr->max_xfer_size) { + nvme_printf(ctrlr, "pt->len (%d) " + "exceeds max_xfer_size (%d)\n", pt->len, + ctrlr->max_xfer_size); + return EIO; + } if (is_user_buffer) { /* * Ensure the user buffer is wired for the duration of @@ -920,7 +926,7 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr, } else req = nvme_allocate_request_vaddr(pt->buf, pt->len, nvme_pt_done, pt); - else + } else req = nvme_allocate_request_null(nvme_pt_done, pt); req->cmd.opc = pt->cmd.opc; diff --git a/sys/dev/nvme/nvme_qpair.c b/sys/dev/nvme/nvme_qpair.c index 53e5c1e56d46..39377187dd81 100644 --- a/sys/dev/nvme/nvme_qpair.c +++ b/sys/dev/nvme/nvme_qpair.c @@ -786,6 +786,9 @@ _nvme_qpair_submit_request(struct nvme_qpair *qpair, struct nvme_request *req) switch (req->type) { case NVME_REQUEST_VADDR: + KASSERT(req->payload_size <= qpair->ctrlr->max_xfer_size, + ("payload_size (%d) exceeds max_xfer_size (%d)\n", + req->payload_size, qpair->ctrlr->max_xfer_size)); err = bus_dmamap_load(tr->qpair->dma_tag, tr->payload_dma_map, req->u.payload, req->payload_size, nvme_payload_map, tr, 0); if (err != 0) @@ -805,6 +808,10 @@ _nvme_qpair_submit_request(struct nvme_qpair *qpair, struct nvme_request *req) break; #ifdef NVME_UNMAPPED_BIO_SUPPORT case NVME_REQUEST_BIO: + KASSERT(req->u.bio->bio_bcount <= qpair->ctrlr->max_xfer_size, + ("bio->bio_bcount (%jd) exceeds max_xfer_size (%d)\n", + (intmax_t)req->u.bio->bio_bcount, + qpair->ctrlr->max_xfer_size)); err = bus_dmamap_load_bio(tr->qpair->dma_tag, tr->payload_dma_map, req->u.bio, nvme_payload_map, tr, 0); if (err != 0)