History

mm/alloc_tag: fix the kmemleak false positive issue in the allocation of the percpu variable tag->counters

When loading a module, as long as the module has memory allocation operations, kmemleak produces a false positive report that resembles the following: unreferenced object (percpu) 0x7dfd232a1650 (size 16): comm "modprobe", pid 1301, jiffies 4294940249 hex dump (first 16 bytes on cpu 2): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace (crc 0): kmemleak_alloc_percpu+0xb4/0xd0 pcpu_alloc_noprof+0x700/0x1098 load_module+0xd4/0x348 codetag_module_init+0x20c/0x450 codetag_load_module+0x70/0xb8 load_module+0xef8/0x1608 init_module_from_file+0xec/0x158 idempotent_init_module+0x354/0x608 __arm64_sys_finit_module+0xbc/0x150 invoke_syscall+0xd4/0x258 el0_svc_common.constprop.0+0xb4/0x240 do_el0_svc+0x48/0x68 el0_svc+0x40/0xf8 el0t_64_sync_handler+0x10c/0x138 el0t_64_sync+0x1ac/0x1b0 This is because the module can only indirectly reference alloc_tag_counters through the alloc_tag section, which misleads kmemleak. However, we don't have a kmemleak ignore interface for percpu allocations yet. So let's create one and invoke it for tag->counters. [gehao@kylinos.cn: fix build error when CONFIG_DEBUG_KMEMLEAK=n, s/igonore/ignore/] Link: https://lkml.kernel.org/r/20250620093102.2416767-1-hao.ge@linux.dev Link: https://lkml.kernel.org/r/20250619183154.2122608-1-hao.ge@linux.dev Fixes: 12ca42c23775 ("alloc_tag: allocate percpu counters for module tags dynamically") Signed-off-by: Hao Ge <gehao@kylinos.cn> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Acked-by: Suren Baghdasaryan <surenb@google.com> [lib/alloc_tag.c] Cc: Kent Overstreet <kent.overstreet@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

Hao Ge committed 1 year ago

Commit f5769351 parent df831e93 files · +25 −1Browse files

Showing the changes to include/linux (1 of 3 files). Show all

Unified · Split

include/linux/kmemleak.h+4−0
@@ -28,6 +28,7 @@ extern void kmemleak_update_trace(const void *ptr) __ref; · 27 unmodified lines
2828 extern void kmemleak_not_leak(const void *ptr) __ref;
2929 extern void kmemleak_transient_leak(const void *ptr) __ref;
3030 extern void kmemleak_ignore(const void *ptr) __ref;
31+extern void kmemleak_ignore_percpu(const void __percpu *ptr) __ref;
3132 extern void kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp) __ref;
3233 extern void kmemleak_no_scan(const void *ptr) __ref;
3334 extern void kmemleak_alloc_phys(phys_addr_t phys, size_t size,
@@ -97,6 +98,9 @@ static inline void kmemleak_not_leak(const void *ptr) · 63 unmodified lines
9798 static inline void kmemleak_transient_leak(const void *ptr)
9899 {
99100 }
101+static inline void kmemleak_ignore_percpu(const void __percpu *ptr)
102+{
103+}
100104 static inline void kmemleak_ignore(const void *ptr)
101105 {
102106 }