]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
nvme-pci: use sgls for all user requests if possible
authorKeith Busch <kbusch@kernel.org>
Fri, 8 Nov 2024 23:41:08 +0000 (15:41 -0800)
committerKeith Busch <kbusch@kernel.org>
Mon, 18 Nov 2024 17:27:47 +0000 (09:27 -0800)
If the device supports SGLs, use these for all user requests. This
format encodes the expected transfer length so it can catch short buffer
errors in a user command, whether it occurred accidently or maliciously.

For controllers that support SGL data mode, this is a viable mitigation
to CVE-2023-6238. For controllers that don't support SGLs, log a warning
in the passthrough path since not having the capability can corrupt
data if the interface is not used correctly.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
drivers/nvme/host/ioctl.c
drivers/nvme/host/pci.c

index cb7f61e2077d08ab8123aa566700553f18525029..64b5542fb3b795041a54cbf1d46e7da43282d564 100644 (file)
@@ -120,12 +120,20 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
        struct nvme_ns *ns = q->queuedata;
        struct block_device *bdev = ns ? ns->disk->part0 : NULL;
        bool supports_metadata = bdev && blk_get_integrity(bdev->bd_disk);
+       struct nvme_ctrl *ctrl = nvme_req(req)->ctrl;
        bool has_metadata = meta_buffer && meta_len;
        struct bio *bio = NULL;
        int ret;
 
-       if (has_metadata && !supports_metadata)
-               return -EINVAL;
+       if (!nvme_ctrl_sgl_supported(ctrl))
+               dev_warn_once(ctrl->device, "using unchecked data buffer\n");
+       if (has_metadata) {
+               if (!supports_metadata)
+                       return -EINVAL;
+               if (!nvme_ctrl_meta_sgl_supported(ctrl))
+                       dev_warn_once(ctrl->device,
+                                     "using unchecked metadata buffer\n");
+       }
 
        if (ioucmd && (ioucmd->flags & IORING_URING_CMD_FIXED)) {
                struct iov_iter iter;
index c6c3ae3a7c434d9f6a97920b3dbea01c49615926..4c644bb7f069270e72317636d6660beeb24f916d 100644 (file)
@@ -515,7 +515,8 @@ static inline bool nvme_pci_metadata_use_sgls(struct nvme_dev *dev,
 {
        if (!nvme_ctrl_meta_sgl_supported(&dev->ctrl))
                return false;
-       return req->nr_integrity_segments > 1;
+       return req->nr_integrity_segments > 1 ||
+               nvme_req(req)->flags & NVME_REQ_USERCMD;
 }
 
 static inline bool nvme_pci_use_sgls(struct nvme_dev *dev, struct request *req,
@@ -533,7 +534,7 @@ static inline bool nvme_pci_use_sgls(struct nvme_dev *dev, struct request *req,
        if (nvme_pci_metadata_use_sgls(dev, req))
                return true;
        if (!sgl_threshold || avg_seg_size < sgl_threshold)
-               return false;
+               return nvme_req(req)->flags & NVME_REQ_USERCMD;
        return true;
 }