Commit 11c5620a authored by Daniel Verkamp's avatar Daniel Verkamp
Browse files

nvmf: add bounds checks to RW and DSM commands



Check that the number of blocks/ranges in the command fits within the
length specified by the SGL.

Change-Id: I21aded797dc1f1e752fe0bc9cec27310a4fb106a
Signed-off-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent a1d83c72
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -385,6 +385,7 @@ nvmf_virtual_ctrlr_rw_cmd(struct spdk_bdev *bdev, struct spdk_nvmf_request *req)
{
	uint64_t lba_address;
	uint64_t blockcnt;
	uint64_t io_bytes;
	off_t offset;
	uint64_t llen;
	struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
@@ -403,6 +404,13 @@ nvmf_virtual_ctrlr_rw_cmd(struct spdk_bdev *bdev, struct spdk_nvmf_request *req)
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	io_bytes = llen * bdev->blocklen;
	if (io_bytes > req->length) {
		SPDK_ERRLOG("Read/Write NLB > SGL length\n");
		response->status.sc = SPDK_NVME_SC_DATA_SGL_LENGTH_INVALID;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	if (cmd->opc == SPDK_NVME_OPC_READ) {
		spdk_trace_record(TRACE_NVMF_LIB_READ_START, 0, 0, (uint64_t)req, 0);
		if (spdk_bdev_read(bdev, req->data, req->length, offset, nvmf_virtual_ctrlr_complete_cmd,
@@ -449,6 +457,12 @@ nvmf_virtual_ctrlr_dsm_cmd(struct spdk_bdev *bdev, struct spdk_nvmf_request *req
	bool async = false;

	nr = ((cmd->cdw10 & 0x000000ff) + 1);
	if (nr * sizeof(struct spdk_nvme_dsm_range) > req->length) {
		SPDK_ERRLOG("Dataset Management number of ranges > SGL length\n");
		response->status.sc = SPDK_NVME_SC_DATA_SGL_LENGTH_INVALID;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	attribute = cmd->cdw11 & 0x00000007;
	if (attribute & SPDK_NVME_DSM_ATTR_DEALLOCATE) {
		struct spdk_nvme_dsm_range *dsm_range = (struct spdk_nvme_dsm_range *)req->data;