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

