]> xenbits.xensource.com Git - people/pauldu/qemu.git/commitdiff
nvme: Fix NULL ptr dereference nvme-ns
authorPaul Durrant <paul.durrant@citrix.com>
Tue, 24 Sep 2019 10:23:30 +0000 (11:23 +0100)
committerPaul Durrant <paul.durrant@citrix.com>
Tue, 24 Sep 2019 10:23:30 +0000 (11:23 +0100)
For an admin command (get_feature and set_feature) the namespace is not
set in the req. Instead, get it based on the command's nsid.

hw/block/nvme.c

index fda610f166c7186489104dba849185aa82f5f424..4446906177634facc49c91796283cb0a8d280319 100644 (file)
@@ -1454,12 +1454,12 @@ static uint16_t nvme_get_feature_timestamp(NvmeCtrl *n, NvmeCmd *cmd,
 
 static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
 {
-    NvmeNamespace *ns = req->ns;
-
     uint32_t dw10 = le32_to_cpu(cmd->cdw10);
     uint32_t dw11 = le32_to_cpu(cmd->cdw11);
     uint32_t result;
 
+    uint32_t nsid;
+
     trace_nvme_getfeat(dw10);
 
     switch (dw10) {
@@ -1476,7 +1476,13 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
         result = cpu_to_le32(n->features.err_rec);
         break;
     case NVME_VOLATILE_WRITE_CACHE:
-        result = blk_enable_write_cache(ns->conf.blk);
+        nsid = le32_to_cpu(cmd->nsid);
+        if (unlikely(nsid == 0 || nsid > n->num_namespaces)) {
+            trace_nvme_err_invalid_ns(nsid, n->num_namespaces);
+            return NVME_INVALID_NSID | NVME_DNR;
+        }
+
+        result = blk_enable_write_cache(n->namespaces[nsid - 1]->conf.blk);
         trace_nvme_getfeat_vwcache(result ? "enabled" : "disabled");
         break;
     case NVME_NUMBER_OF_QUEUES:
@@ -1530,11 +1536,11 @@ static uint16_t nvme_set_feature_timestamp(NvmeCtrl *n, NvmeCmd *cmd,
 
 static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
 {
-    NvmeNamespace *ns = req->ns;
-
     uint32_t dw10 = le32_to_cpu(cmd->cdw10);
     uint32_t dw11 = le32_to_cpu(cmd->cdw11);
 
+    uint32_t nsid;
+
     trace_nvme_setfeat(dw10, dw11);
 
     switch (dw10) {
@@ -1546,7 +1552,13 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
         }
         break;
     case NVME_VOLATILE_WRITE_CACHE:
-        blk_set_enable_write_cache(ns->conf.blk, dw11 & 1);
+        nsid = le32_to_cpu(cmd->nsid);
+        if (unlikely(nsid == 0 || nsid > n->num_namespaces)) {
+            trace_nvme_err_invalid_ns(nsid, n->num_namespaces);
+            return NVME_INVALID_NSID | NVME_DNR;
+        }
+
+        blk_set_enable_write_cache(n->namespaces[nsid - 1]->conf.blk, dw11 & 1);
         break;
     case NVME_NUMBER_OF_QUEUES:
         if (n->qs_created > 2) {