| From 5f00888c7d3a29a43b95699f2a965f41a17647b5 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 24 Nov 2021 14:08:01 +0000 |
| Subject: tracing: Fix a kmemleak false positive in tracing_map |
| |
| From: Chen Jun <chenjun102@huawei.com> |
| |
| [ Upstream commit f25667e5980a4333729cac3101e5de1bb851f71a ] |
| |
| Doing the command: |
| echo 'hist:key=common_pid.execname,common_timestamp' > /sys/kernel/debug/tracing/events/xxx/trigger |
| |
| Triggers many kmemleak reports: |
| |
| unreferenced object 0xffff0000c7ea4980 (size 128): |
| comm "bash", pid 338, jiffies 4294912626 (age 9339.324s) |
| hex dump (first 32 bytes): |
| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
| backtrace: |
| [<00000000f3469921>] kmem_cache_alloc_trace+0x4c0/0x6f0 |
| [<0000000054ca40c3>] hist_trigger_elt_data_alloc+0x140/0x178 |
| [<00000000633bd154>] tracing_map_init+0x1f8/0x268 |
| [<000000007e814ab9>] event_hist_trigger_func+0xca0/0x1ad0 |
| [<00000000bf8520ed>] trigger_process_regex+0xd4/0x128 |
| [<00000000f549355a>] event_trigger_write+0x7c/0x120 |
| [<00000000b80f898d>] vfs_write+0xc4/0x380 |
| [<00000000823e1055>] ksys_write+0x74/0xf8 |
| [<000000008a9374aa>] __arm64_sys_write+0x24/0x30 |
| [<0000000087124017>] do_el0_svc+0x88/0x1c0 |
| [<00000000efd0dcd1>] el0_svc+0x1c/0x28 |
| [<00000000dbfba9b3>] el0_sync_handler+0x88/0xc0 |
| [<00000000e7399680>] el0_sync+0x148/0x180 |
| unreferenced object 0xffff0000c7ea4980 (size 128): |
| comm "bash", pid 338, jiffies 4294912626 (age 9339.324s) |
| hex dump (first 32 bytes): |
| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
| 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ |
| backtrace: |
| [<00000000f3469921>] kmem_cache_alloc_trace+0x4c0/0x6f0 |
| [<0000000054ca40c3>] hist_trigger_elt_data_alloc+0x140/0x178 |
| [<00000000633bd154>] tracing_map_init+0x1f8/0x268 |
| [<000000007e814ab9>] event_hist_trigger_func+0xca0/0x1ad0 |
| [<00000000bf8520ed>] trigger_process_regex+0xd4/0x128 |
| [<00000000f549355a>] event_trigger_write+0x7c/0x120 |
| [<00000000b80f898d>] vfs_write+0xc4/0x380 |
| [<00000000823e1055>] ksys_write+0x74/0xf8 |
| [<000000008a9374aa>] __arm64_sys_write+0x24/0x30 |
| [<0000000087124017>] do_el0_svc+0x88/0x1c0 |
| [<00000000efd0dcd1>] el0_svc+0x1c/0x28 |
| [<00000000dbfba9b3>] el0_sync_handler+0x88/0xc0 |
| [<00000000e7399680>] el0_sync+0x148/0x180 |
| |
| The reason is elts->pages[i] is alloced by get_zeroed_page. |
| and kmemleak will not scan the area alloced by get_zeroed_page. |
| The address stored in elts->pages will be regarded as leaked. |
| |
| That is, the elts->pages[i] will have pointers loaded onto it as well, and |
| without telling kmemleak about it, those pointers will look like memory |
| without a reference. |
| |
| To fix this, call kmemleak_alloc to tell kmemleak to scan elts->pages[i] |
| |
| Link: https://lkml.kernel.org/r/20211124140801.87121-1-chenjun102@huawei.com |
| |
| Signed-off-by: Chen Jun <chenjun102@huawei.com> |
| Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| kernel/trace/tracing_map.c | 3 +++ |
| 1 file changed, 3 insertions(+) |
| |
| diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c |
| index 39bb56d2dcbef..9628b55718468 100644 |
| --- a/kernel/trace/tracing_map.c |
| +++ b/kernel/trace/tracing_map.c |
| @@ -15,6 +15,7 @@ |
| #include <linux/jhash.h> |
| #include <linux/slab.h> |
| #include <linux/sort.h> |
| +#include <linux/kmemleak.h> |
| |
| #include "tracing_map.h" |
| #include "trace.h" |
| @@ -307,6 +308,7 @@ static void tracing_map_array_free(struct tracing_map_array *a) |
| for (i = 0; i < a->n_pages; i++) { |
| if (!a->pages[i]) |
| break; |
| + kmemleak_free(a->pages[i]); |
| free_page((unsigned long)a->pages[i]); |
| } |
| |
| @@ -342,6 +344,7 @@ static struct tracing_map_array *tracing_map_array_alloc(unsigned int n_elts, |
| a->pages[i] = (void *)get_zeroed_page(GFP_KERNEL); |
| if (!a->pages[i]) |
| goto free; |
| + kmemleak_alloc(a->pages[i], PAGE_SIZE, 1, GFP_KERNEL); |
| } |
| out: |
| return a; |
| -- |
| 2.33.0 |
| |