From: Bryam Vargas <[email protected]>

Even with the bound evaluated in 64-bit, nslot is constrained only by
config_size, which nvdimm_init_nsarea() takes verbatim from the dimm's
ND_CMD_GET_CONFIG_SIZE response with no upper sanity check.  A firmware
or emulated device reporting a large config_size would let a
correspondingly large on-media nslot pass validation and drive a large
allocation and memset loop in nd_label_data_init().

Reject an nslot above NSINDEX_NSLOT_MAX (64K).  The largest legitimate
count is config_size / label_size -- about 1K on a real ~128K label area
-- so this cannot affect a conforming device, and it bounds the slot loop
independently of the firmware-reported config_size.

Suggested-by: David Laight <[email protected]>
Signed-off-by: Bryam Vargas <[email protected]>
---
 drivers/nvdimm/label.c | 4 ++++
 drivers/nvdimm/label.h | 7 +++++++
 2 files changed, 11 insertions(+)

diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index ec12ce72cfe2..ce1e43d67bab 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -202,6 +202,10 @@ static int __nd_label_validate(struct nvdimm_drvdata *ndd)
                }
 
                nslot = __le32_to_cpu(nsindex[i]->nslot);
+               if (nslot > NSINDEX_NSLOT_MAX) {
+                       dev_dbg(dev, "nsindex%d nslot: %u implausibly large\n", 
i, nslot);
+                       continue;
+               }
                if ((u64)nslot * sizeof_namespace_label(ndd)
                                + 2 * sizeof_namespace_index(ndd)
                                > ndd->nsarea.config_size) {
diff --git a/drivers/nvdimm/label.h b/drivers/nvdimm/label.h
index 0650fb4b9821..74d7c1cc7476 100644
--- a/drivers/nvdimm/label.h
+++ b/drivers/nvdimm/label.h
@@ -28,6 +28,13 @@ enum {
        ND_LABEL_MIN_SIZE = 256 * 4, /* see sizeof_namespace_index() */
        ND_LABEL_ID_SIZE = 50,
        ND_NSINDEX_INIT = 0x1,
+       /*
+        * A sane ceiling on the on-media slot count.  The largest legitimate
+        * value is config_size / label_size -- about 1K on a real ~128K label
+        * area.  A count this large cannot describe a real device; it would
+        * only drive a large allocation in nd_label_data_init(), so reject it.
+        */
+       NSINDEX_NSLOT_MAX = 64 * 1024,
 };
 
 /**

-- 
2.43.0



Reply via email to