[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250516051318.509064-1-lizhijian@fujitsu.com>
Date: Fri, 16 May 2025 13:13:17 +0800
From: Li Zhijian <lizhijian@...itsu.com>
To: nvdimm@...ts.linux.dev
Cc: dan.j.williams@...el.com,
vishal.l.verma@...el.com,
dave.jiang@...el.com,
ira.weiny@...el.com,
linux-kernel@...r.kernel.org,
Li Zhijian <lizhijian@...itsu.com>
Subject: [PATCH 1/2] nvdimm/btt: Fix memleaks in discover_arenas()
kmemleak reported a memleak after the ndctl_test
unreferenced object 0xffff88800e6cf2c0 (size 32):
comm "modprobe", pid 969, jiffies 4294698691
hex dump (first 32 bytes):
03 00 00 00 a0 0a 00 00 00 b0 b4 00 00 c9 ff ff ................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace (crc 807f3e24):
__kmalloc_cache_noprof+0x331/0x410
nvdimm_namespace_attach_btt+0xa9b/0xcc0 [nd_btt]
platform_probe+0x45/0xa0
...
load_module+0x21f9/0x22f0
faddr2line tells that (based on v6.15-rc4):
$ ./scripts/faddr2line drivers/nvdimm/nd_btt.o nvdimm_namespace_attach_btt+0xa9
nvdimm_namespace_attach_btt+0xa9b/0xcc0:
log_set_indices at linux/drivers/nvdimm/btt.c:719
(inlined by) discover_arenas at linux/drivers/nvdimm/btt.c:888
(inlined by) btt_init at linux/drivers/nvdimm/btt.c:1583
(inlined by) nvdimm_namespace_attach_btt at linux/drivers/nvdimm/btt.c:1680
It's believed that this was a false positive because the leaking size
didn't match any instance in an arena.
However during looking into this issue, it's noticed that it does not
release an initializing arena instance and instances in btt->arena_list
in some error paths.
Signed-off-by: Li Zhijian <lizhijian@...itsu.com>
---
drivers/nvdimm/btt.c | 26 +++++++++++++++++---------
1 file changed, 17 insertions(+), 9 deletions(-)
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index 423dcd190906..a11e4e7e9a52 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -801,17 +801,22 @@ static struct arena_info *alloc_arena(struct btt *btt, size_t size,
return arena;
}
+static void free_arena(struct arena_info *arena)
+{
+ kfree(arena->rtt);
+ kfree(arena->map_locks);
+ kfree(arena->freelist);
+ debugfs_remove_recursive(arena->debugfs_dir);
+ kfree(arena);
+}
+
static void free_arenas(struct btt *btt)
{
struct arena_info *arena, *next;
list_for_each_entry_safe(arena, next, &btt->arena_list, list) {
list_del(&arena->list);
- kfree(arena->rtt);
- kfree(arena->map_locks);
- kfree(arena->freelist);
- debugfs_remove_recursive(arena->debugfs_dir);
- kfree(arena);
+ free_arena(arena);
}
}
@@ -848,7 +853,7 @@ static void parse_arena_meta(struct arena_info *arena, struct btt_sb *super,
static int discover_arenas(struct btt *btt)
{
int ret = 0;
- struct arena_info *arena;
+ struct arena_info *arena = NULL;
size_t remaining = btt->rawsize;
u64 cur_nlba = 0;
size_t cur_off = 0;
@@ -861,8 +866,10 @@ static int discover_arenas(struct btt *btt)
while (remaining) {
/* Alloc memory for arena */
arena = alloc_arena(btt, 0, 0, 0);
- if (!arena)
- return -ENOMEM;
+ if (!arena) {
+ ret = -ENOMEM;
+ goto out;
+ }
arena->infooff = cur_off;
ret = btt_info_read(arena, super);
@@ -921,7 +928,8 @@ static int discover_arenas(struct btt *btt)
return ret;
out:
- kfree(arena);
+ if (arena)
+ free_arena(arena);
free_arenas(btt);
return ret;
}
--
2.47.0
Powered by blists - more mailing lists