Skip to content

Commit 62c2aa6

Browse files
zhijianli88weiny2
authored andcommitted
nvdimm: Fix devs leaks in scan_labels()
scan_labels() leaks memory when label scanning fails and it falls back to just creating a default "seed" namespace for userspace to configure. Root can force the kernel to leak memory. Allocate the minimum resources unconditionally and release them when unneeded to avoid the memory leak. A kmemleak reports: unreferenced object 0xffff88800dda1980 (size 16): comm "kworker/u10:5", pid 69, jiffies 4294671781 hex dump (first 16 bytes): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace (crc 0): [<00000000c5dea560>] __kmalloc+0x32c/0x470 [<000000009ed43c83>] nd_region_register_namespaces+0x6fb/0x1120 [libnvdimm] [<000000000e07a65c>] nd_region_probe+0xfe/0x210 [libnvdimm] [<000000007b79ce5f>] nvdimm_bus_probe+0x7a/0x1e0 [libnvdimm] [<00000000a5f3da2e>] really_probe+0xc6/0x390 [<00000000129e2a69>] __driver_probe_device+0x78/0x150 [<000000002dfed28b>] driver_probe_device+0x1e/0x90 [<00000000e7048de2>] __device_attach_driver+0x85/0x110 [<0000000032dca295>] bus_for_each_drv+0x85/0xe0 [<00000000391c5a7d>] __device_attach+0xbe/0x1e0 [<0000000026dabec0>] bus_probe_device+0x94/0xb0 [<00000000c590d936>] device_add+0x656/0x870 [<000000003d69bfaa>] nd_async_device_register+0xe/0x50 [libnvdimm] [<000000003f4c52a4>] async_run_entry_fn+0x2e/0x110 [<00000000e201f4b0>] process_one_work+0x1ee/0x600 [<000000006d90d5a9>] worker_thread+0x183/0x350 Cc: Dave Jiang <[email protected]> Cc: Ira Weiny <[email protected]> Fixes: 1b40e09 ("libnvdimm: blk labels and namespace instantiation") Suggested-by: Dan Williams <[email protected]> Signed-off-by: Li Zhijian <[email protected]> Reviewed-by: Dan Williams <[email protected]> Reviewed-by: Ira Weiny <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Ira Weiny <[email protected]>
1 parent 7951918 commit 62c2aa6

File tree

1 file changed

+17
-17
lines changed

1 file changed

+17
-17
lines changed

drivers/nvdimm/namespace_devs.c

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,12 +1937,16 @@ static int cmp_dpa(const void *a, const void *b)
19371937
static struct device **scan_labels(struct nd_region *nd_region)
19381938
{
19391939
int i, count = 0;
1940-
struct device *dev, **devs = NULL;
1940+
struct device *dev, **devs;
19411941
struct nd_label_ent *label_ent, *e;
19421942
struct nd_mapping *nd_mapping = &nd_region->mapping[0];
19431943
struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
19441944
resource_size_t map_end = nd_mapping->start + nd_mapping->size - 1;
19451945

1946+
devs = kcalloc(2, sizeof(dev), GFP_KERNEL);
1947+
if (!devs)
1948+
return NULL;
1949+
19461950
/* "safe" because create_namespace_pmem() might list_move() label_ent */
19471951
list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) {
19481952
struct nd_namespace_label *nd_label = label_ent->label;
@@ -1961,12 +1965,14 @@ static struct device **scan_labels(struct nd_region *nd_region)
19611965
goto err;
19621966
if (i < count)
19631967
continue;
1964-
__devs = kcalloc(count + 2, sizeof(dev), GFP_KERNEL);
1965-
if (!__devs)
1966-
goto err;
1967-
memcpy(__devs, devs, sizeof(dev) * count);
1968-
kfree(devs);
1969-
devs = __devs;
1968+
if (count) {
1969+
__devs = kcalloc(count + 2, sizeof(dev), GFP_KERNEL);
1970+
if (!__devs)
1971+
goto err;
1972+
memcpy(__devs, devs, sizeof(dev) * count);
1973+
kfree(devs);
1974+
devs = __devs;
1975+
}
19701976

19711977
dev = create_namespace_pmem(nd_region, nd_mapping, nd_label);
19721978
if (IS_ERR(dev)) {
@@ -1993,11 +1999,6 @@ static struct device **scan_labels(struct nd_region *nd_region)
19931999

19942000
/* Publish a zero-sized namespace for userspace to configure. */
19952001
nd_mapping_free_labels(nd_mapping);
1996-
1997-
devs = kcalloc(2, sizeof(dev), GFP_KERNEL);
1998-
if (!devs)
1999-
goto err;
2000-
20012002
nspm = kzalloc(sizeof(*nspm), GFP_KERNEL);
20022003
if (!nspm)
20032004
goto err;
@@ -2036,11 +2037,10 @@ static struct device **scan_labels(struct nd_region *nd_region)
20362037
return devs;
20372038

20382039
err:
2039-
if (devs) {
2040-
for (i = 0; devs[i]; i++)
2041-
namespace_pmem_release(devs[i]);
2042-
kfree(devs);
2043-
}
2040+
for (i = 0; devs[i]; i++)
2041+
namespace_pmem_release(devs[i]);
2042+
kfree(devs);
2043+
20442044
return NULL;
20452045
}
20462046

0 commit comments

Comments
 (0)