Skip to content

Commit b716e68

Browse files
sagigrimbergkeithbusch
authored andcommitted
nvmet: fix dsm failure when payload does not match sgl descriptor
The host is allowed to pass the controller an sgl describing a buffer that is larger than the dsm payload itself, allow it when executing dsm. Reported-by: Dakshaja Uppalapati <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]>, Reviewed-by: Max Gurtovoy <[email protected]> Signed-off-by: Sagi Grimberg <[email protected]> Signed-off-by: Keith Busch <[email protected]>
1 parent 4ac7643 commit b716e68

File tree

4 files changed

+14
-2
lines changed

4 files changed

+14
-2
lines changed

drivers/nvme/target/core.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -939,6 +939,17 @@ bool nvmet_check_data_len(struct nvmet_req *req, size_t data_len)
939939
}
940940
EXPORT_SYMBOL_GPL(nvmet_check_data_len);
941941

942+
bool nvmet_check_data_len_lte(struct nvmet_req *req, size_t data_len)
943+
{
944+
if (unlikely(data_len > req->transfer_len)) {
945+
req->error_loc = offsetof(struct nvme_common_command, dptr);
946+
nvmet_req_complete(req, NVME_SC_SGL_INVALID_DATA | NVME_SC_DNR);
947+
return false;
948+
}
949+
950+
return true;
951+
}
952+
942953
int nvmet_req_alloc_sgl(struct nvmet_req *req)
943954
{
944955
struct pci_dev *p2p_dev = NULL;

drivers/nvme/target/io-cmd-bdev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ static void nvmet_bdev_execute_discard(struct nvmet_req *req)
280280

281281
static void nvmet_bdev_execute_dsm(struct nvmet_req *req)
282282
{
283-
if (!nvmet_check_data_len(req, nvmet_dsm_len(req)))
283+
if (!nvmet_check_data_len_lte(req, nvmet_dsm_len(req)))
284284
return;
285285

286286
switch (le32_to_cpu(req->cmd->dsm.attributes)) {

drivers/nvme/target/io-cmd-file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ static void nvmet_file_dsm_work(struct work_struct *w)
336336

337337
static void nvmet_file_execute_dsm(struct nvmet_req *req)
338338
{
339-
if (!nvmet_check_data_len(req, nvmet_dsm_len(req)))
339+
if (!nvmet_check_data_len_lte(req, nvmet_dsm_len(req)))
340340
return;
341341
INIT_WORK(&req->f.work, nvmet_file_dsm_work);
342342
schedule_work(&req->f.work);

drivers/nvme/target/nvmet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
374374
struct nvmet_sq *sq, const struct nvmet_fabrics_ops *ops);
375375
void nvmet_req_uninit(struct nvmet_req *req);
376376
bool nvmet_check_data_len(struct nvmet_req *req, size_t data_len);
377+
bool nvmet_check_data_len_lte(struct nvmet_req *req, size_t data_len);
377378
void nvmet_req_complete(struct nvmet_req *req, u16 status);
378379
int nvmet_req_alloc_sgl(struct nvmet_req *req);
379380
void nvmet_req_free_sgl(struct nvmet_req *req);

0 commit comments

Comments
 (0)