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
This commit is contained in:
Jim Harris 2013-06-26 23:32:45 +00:00
parent 8d09e3c400
commit 7b68ae1e5e
2 changed files with 15 additions and 2 deletions

View File

@ -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;

View File

@ -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)