diff options
author | Christoph Hellwig <hch@lst.de> | 2017-11-09 14:29:58 +0100 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2017-11-10 19:53:25 -0700 |
commit | 5e62d5c993e6889cd314d5b5de6b670152109a0e (patch) | |
tree | 381ea84b468c5c5b73aaa796d6ee8549599edf55 /drivers/nvme/target/core.c | |
parent | 03e0f3a65e4da497c3b7b213c68943cbc73a2e34 (diff) | |
download | linux-stable-5e62d5c993e6889cd314d5b5de6b670152109a0e.tar.gz linux-stable-5e62d5c993e6889cd314d5b5de6b670152109a0e.tar.bz2 linux-stable-5e62d5c993e6889cd314d5b5de6b670152109a0e.zip |
nvmet: better data length validation
Currently the NVMe target stores the expexted data length in req->data_len
and uses that for data transfer decisions, but that does not take the
actual transfer length in the SGLs into account. So this adds a new
transfer_len field, into which the transport drivers store the actual
transfer length. We then check the two match before actually executing
the command.
The FC transport driver already had such a field, which is removed in
favour of the common one.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/nvme/target/core.c')
-rw-r--r-- | drivers/nvme/target/core.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index da088293eafc..22a2a2bb40f9 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -501,6 +501,7 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq, req->ops = ops; req->sg = NULL; req->sg_cnt = 0; + req->transfer_len = 0; req->rsp->status = 0; /* no support for fused commands yet */ @@ -550,6 +551,15 @@ void nvmet_req_uninit(struct nvmet_req *req) } EXPORT_SYMBOL_GPL(nvmet_req_uninit); +void nvmet_req_execute(struct nvmet_req *req) +{ + if (unlikely(req->data_len != req->transfer_len)) + nvmet_req_complete(req, NVME_SC_SGL_INVALID_DATA | NVME_SC_DNR); + else + req->execute(req); +} +EXPORT_SYMBOL_GPL(nvmet_req_execute); + static inline bool nvmet_cc_en(u32 cc) { return (cc >> NVME_CC_EN_SHIFT) & 0x1; |