From d1776c0202aac8251e6b4cbe096ad2950ed6c506 Mon Sep 17 00:00:00 2001 From: Rafael Mendonca Date: Fri, 18 Nov 2022 10:15:34 +0900 Subject: tracing/eprobe: Fix memory leak of filter string The filter string doesn't get freed when a dynamic event is deleted. If a filter is set, then memory is leaked: root@localhost:/sys/kernel/tracing# echo 'e:egroup/stat_runtime_4core \ sched/sched_stat_runtime runtime=$runtime:u32 if cpu < 4' >> dynamic_events root@localhost:/sys/kernel/tracing# echo "-:egroup/stat_runtime_4core" >> dynamic_events root@localhost:/sys/kernel/tracing# echo scan > /sys/kernel/debug/kmemleak [ 224.416373] kmemleak: 1 new suspected memory leaks (see /sys/kernel/debug/kmemleak) root@localhost:/sys/kernel/tracing# cat /sys/kernel/debug/kmemleak unreferenced object 0xffff88810156f1b8 (size 8): comm "bash", pid 224, jiffies 4294935612 (age 55.800s) hex dump (first 8 bytes): 63 70 75 20 3c 20 34 00 cpu < 4. backtrace: [<000000009f880725>] __kmem_cache_alloc_node+0x18e/0x720 [<0000000042492946>] __kmalloc+0x57/0x240 [<0000000034ea7995>] __trace_eprobe_create+0x1214/0x1d30 [<00000000d70ef730>] trace_probe_create+0xf6/0x110 [<00000000915c7b16>] eprobe_dyn_event_create+0x21/0x30 [<000000000d894386>] create_dyn_event+0xf3/0x1a0 [<00000000e9af57d5>] trace_parse_run_command+0x1a9/0x2e0 [<0000000080777f18>] dyn_event_write+0x39/0x50 [<0000000089f0ec73>] vfs_write+0x311/0xe50 [<000000003da1bdda>] ksys_write+0x158/0x2a0 [<00000000bb1e616e>] __x64_sys_write+0x7c/0xc0 [<00000000e8aef1f7>] do_syscall_64+0x60/0x90 [<00000000fe7fe8ba>] entry_SYSCALL_64_after_hwframe+0x63/0xcd Additionally, in __trace_eprobe_create() function, if an error occurs after the call to trace_eprobe_parse_filter(), which allocates the filter string, then memory is also leaked. That can be reproduced by creating the same event probe twice: root@localhost:/sys/kernel/tracing# echo 'e:egroup/stat_runtime_4core \ sched/sched_stat_runtime runtime=$runtime:u32 if cpu < 4' >> dynamic_events root@localhost:/sys/kernel/tracing# echo 'e:egroup/stat_runtime_4core \ sched/sched_stat_runtime runtime=$runtime:u32 if cpu < 4' >> dynamic_events -bash: echo: write error: File exists root@localhost:/sys/kernel/tracing# echo scan > /sys/kernel/debug/kmemleak [ 207.871584] kmemleak: 1 new suspected memory leaks (see /sys/kernel/debug/kmemleak) root@localhost:/sys/kernel/tracing# cat /sys/kernel/debug/kmemleak unreferenced object 0xffff8881020d17a8 (size 8): comm "bash", pid 223, jiffies 4294938308 (age 31.000s) hex dump (first 8 bytes): 63 70 75 20 3c 20 34 00 cpu < 4. backtrace: [<000000000e4f5f31>] __kmem_cache_alloc_node+0x18e/0x720 [<0000000024f0534b>] __kmalloc+0x57/0x240 [<000000002930a28e>] __trace_eprobe_create+0x1214/0x1d30 [<0000000028387903>] trace_probe_create+0xf6/0x110 [<00000000a80d6a9f>] eprobe_dyn_event_create+0x21/0x30 [<000000007168698c>] create_dyn_event+0xf3/0x1a0 [<00000000f036bf6a>] trace_parse_run_command+0x1a9/0x2e0 [<00000000014bde8b>] dyn_event_write+0x39/0x50 [<0000000078a097f7>] vfs_write+0x311/0xe50 [<00000000996cb208>] ksys_write+0x158/0x2a0 [<00000000a3c2acb0>] __x64_sys_write+0x7c/0xc0 [<0000000006b5d698>] do_syscall_64+0x60/0x90 [<00000000780e8ecf>] entry_SYSCALL_64_after_hwframe+0x63/0xcd Fix both issues by releasing the filter string in trace_event_probe_cleanup(). Link: https://lore.kernel.org/all/20221108235738.1021467-1-rafaelmendsr@gmail.com/ Fixes: 752be5c5c910 ("tracing/eprobe: Add eprobe filter support") Signed-off-by: Rafael Mendonca Acked-by: Masami Hiramatsu (Google) Signed-off-by: Masami Hiramatsu (Google) --- kernel/trace/trace_eprobe.c | 1 + 1 file changed, 1 insertion(+) (limited to 'kernel/trace/trace_eprobe.c') diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index 5dd0617e5df6..fe4833a7b7b3 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -52,6 +52,7 @@ static void trace_event_probe_cleanup(struct trace_eprobe *ep) kfree(ep->event_system); if (ep->event) trace_event_put_ref(ep->event); + kfree(ep->filter_str); kfree(ep); } -- cgit v1.2.3 From 342a4a2f99431ee3c72ef5cfff6449ccf2abd346 Mon Sep 17 00:00:00 2001 From: Rafael Mendonca Date: Fri, 18 Nov 2022 10:15:34 +0900 Subject: tracing/eprobe: Fix warning in filter creation The filter pointer (filterp) passed to create_filter() function must be a pointer that references a NULL pointer, otherwise, we get a warning when adding a filter option to the event probe: root@localhost:/sys/kernel/tracing# echo 'e:egroup/stat_runtime_4core sched/sched_stat_runtime \ runtime=$runtime:u32 if cpu < 4' >> dynamic_events [ 5034.340439] ------------[ cut here ]------------ [ 5034.341258] WARNING: CPU: 0 PID: 223 at kernel/trace/trace_events_filter.c:1939 create_filter+0x1db/0x250 [...] stripped [ 5034.345518] RIP: 0010:create_filter+0x1db/0x250 [...] stripped [ 5034.351604] Call Trace: [ 5034.351803] [ 5034.351959] ? process_preds+0x1b40/0x1b40 [ 5034.352241] ? rcu_read_lock_bh_held+0xd0/0xd0 [ 5034.352604] ? kasan_set_track+0x29/0x40 [ 5034.352904] ? kasan_save_alloc_info+0x1f/0x30 [ 5034.353264] create_event_filter+0x38/0x50 [ 5034.353573] __trace_eprobe_create+0x16f4/0x1d20 [ 5034.353964] ? eprobe_dyn_event_release+0x360/0x360 [ 5034.354363] ? mark_held_locks+0xa6/0xf0 [ 5034.354684] ? _raw_spin_unlock_irqrestore+0x35/0x60 [ 5034.355105] ? trace_hardirqs_on+0x41/0x120 [ 5034.355417] ? _raw_spin_unlock_irqrestore+0x35/0x60 [ 5034.355751] ? __create_object+0x5b7/0xcf0 [ 5034.356027] ? lock_is_held_type+0xaf/0x120 [ 5034.356362] ? rcu_read_lock_bh_held+0xb0/0xd0 [ 5034.356716] ? rcu_read_lock_bh_held+0xd0/0xd0 [ 5034.357084] ? kasan_set_track+0x29/0x40 [ 5034.357411] ? kasan_save_alloc_info+0x1f/0x30 [ 5034.357715] ? __kasan_kmalloc+0xb8/0xc0 [ 5034.357985] ? write_comp_data+0x2f/0x90 [ 5034.358302] ? __sanitizer_cov_trace_pc+0x25/0x60 [ 5034.358691] ? argv_split+0x381/0x460 [ 5034.358949] ? write_comp_data+0x2f/0x90 [ 5034.359240] ? eprobe_dyn_event_release+0x360/0x360 [ 5034.359620] trace_probe_create+0xf6/0x110 [ 5034.359940] ? trace_probe_match_command_args+0x240/0x240 [ 5034.360376] eprobe_dyn_event_create+0x21/0x30 [ 5034.360709] create_dyn_event+0xf3/0x1a0 [ 5034.360983] trace_parse_run_command+0x1a9/0x2e0 [ 5034.361297] ? dyn_event_release+0x500/0x500 [ 5034.361591] dyn_event_write+0x39/0x50 [ 5034.361851] vfs_write+0x311/0xe50 [ 5034.362091] ? dyn_event_seq_next+0x40/0x40 [ 5034.362376] ? kernel_write+0x5b0/0x5b0 [ 5034.362637] ? write_comp_data+0x2f/0x90 [ 5034.362937] ? __sanitizer_cov_trace_pc+0x25/0x60 [ 5034.363258] ? ftrace_syscall_enter+0x544/0x840 [ 5034.363563] ? write_comp_data+0x2f/0x90 [ 5034.363837] ? __sanitizer_cov_trace_pc+0x25/0x60 [ 5034.364156] ? write_comp_data+0x2f/0x90 [ 5034.364468] ? write_comp_data+0x2f/0x90 [ 5034.364770] ksys_write+0x158/0x2a0 [ 5034.365022] ? __ia32_sys_read+0xc0/0xc0 [ 5034.365344] __x64_sys_write+0x7c/0xc0 [ 5034.365669] ? syscall_enter_from_user_mode+0x53/0x70 [ 5034.366084] do_syscall_64+0x60/0x90 [ 5034.366356] entry_SYSCALL_64_after_hwframe+0x63/0xcd [ 5034.366767] RIP: 0033:0x7ff0b43938f3 [...] stripped [ 5034.371892] [ 5034.374720] ---[ end trace 0000000000000000 ]--- Link: https://lore.kernel.org/all/20221108202148.1020111-1-rafaelmendsr@gmail.com/ Fixes: 752be5c5c910 ("tracing/eprobe: Add eprobe filter support") Signed-off-by: Rafael Mendonca Acked-by: Masami Hiramatsu (Google) Signed-off-by: Masami Hiramatsu (Google) --- kernel/trace/trace_eprobe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/trace/trace_eprobe.c') diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index fe4833a7b7b3..e888446d80fa 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -901,7 +901,7 @@ static int trace_eprobe_tp_update_arg(struct trace_eprobe *ep, const char *argv[ static int trace_eprobe_parse_filter(struct trace_eprobe *ep, int argc, const char *argv[]) { - struct event_filter *dummy; + struct event_filter *dummy = NULL; int i, ret, len = 0; char *p; -- cgit v1.2.3 From 40adaf51cb318131073d1ba8233d473cc105ecbf Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Fri, 18 Nov 2022 10:15:34 +0900 Subject: tracing/eprobe: Fix eprobe filter to make a filter correctly Since the eprobe filter was defined based on the eprobe's trace event itself, it doesn't work correctly. Use the original trace event of the eprobe when making the filter so that the filter works correctly. Without this fix: # echo 'e syscalls/sys_enter_openat \ flags_rename=$flags:u32 if flags < 1000' >> dynamic_events # echo 1 > events/eprobes/sys_enter_openat/enable [ 114.551550] event trace: Could not enable event sys_enter_openat -bash: echo: write error: Invalid argument With this fix: # echo 'e syscalls/sys_enter_openat \ flags_rename=$flags:u32 if flags < 1000' >> dynamic_events # echo 1 > events/eprobes/sys_enter_openat/enable # tail trace cat-241 [000] ...1. 266.498449: sys_enter_openat: (syscalls.sys_enter_openat) flags_rename=0 cat-242 [000] ...1. 266.977640: sys_enter_openat: (syscalls.sys_enter_openat) flags_rename=0 Link: https://lore.kernel.org/all/166823166395.1385292.8931770640212414483.stgit@devnote3/ Fixes: 752be5c5c910 ("tracing/eprobe: Add eprobe filter support") Reported-by: Rafael Mendonca Tested-by: Rafael Mendonca Signed-off-by: Masami Hiramatsu (Google) --- kernel/trace/trace_eprobe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/trace/trace_eprobe.c') diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index e888446d80fa..123d2c0a6b68 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -643,7 +643,7 @@ new_eprobe_trigger(struct trace_eprobe *ep, struct trace_event_file *file) INIT_LIST_HEAD(&trigger->list); if (ep->filter_str) { - ret = create_event_filter(file->tr, file->event_call, + ret = create_event_filter(file->tr, ep->event, ep->filter_str, false, &filter); if (ret) goto error; -- cgit v1.2.3 From 94eedf3dded5fb472ce97bfaf3ac1c6c29c35d26 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Thu, 17 Nov 2022 21:42:49 -0500 Subject: tracing: Fix race where eprobes can be called before the event The flag that tells the event to call its triggers after reading the event is set for eprobes after the eprobe is enabled. This leads to a race where the eprobe may be triggered at the beginning of the event where the record information is NULL. The eprobe then dereferences the NULL record causing a NULL kernel pointer bug. Test for a NULL record to keep this from happening. Link: https://lore.kernel.org/linux-trace-kernel/20221116192552.1066630-1-rafaelmendsr@gmail.com/ Link: https://lore.kernel.org/linux-trace-kernel/20221117214249.2addbe10@gandalf.local.home Cc: Linux Trace Kernel Cc: Tzvetomir Stoyanov Cc: Tom Zanussi Cc: stable@vger.kernel.org Fixes: 7491e2c442781 ("tracing: Add a probe that attaches to trace events") Acked-by: Masami Hiramatsu (Google) Reported-by: Rafael Mendonca Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_eprobe.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'kernel/trace/trace_eprobe.c') diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index 5dd0617e5df6..9cda9a38422c 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -563,6 +563,9 @@ static void eprobe_trigger_func(struct event_trigger_data *data, { struct eprobe_data *edata = data->private_data; + if (unlikely(!rec)) + return; + __eprobe_trace_func(edata, rec); } -- cgit v1.2.3