1 From 6018b585e8c6fa7d85d4b38d9ce49a5b67be7078 Mon Sep 17 00:00:00 2001
2 From: Mohamed Khalfella <mkhalfella@purestorage.com>
3 Date: Wed, 12 Jul 2023 22:30:21 +0000
4 Subject: tracing/histograms: Add histograms to hist_vars if they have referenced variables
6 From: Mohamed Khalfella <mkhalfella@purestorage.com>
8 commit 6018b585e8c6fa7d85d4b38d9ce49a5b67be7078 upstream.
10 Hist triggers can have referenced variables without having direct
11 variables fields. This can be the case if referenced variables are added
12 for trigger actions. In this case the newly added references will not
13 have field variables. Not taking such referenced variables into
14 consideration can result in a bug where it would be possible to remove
15 hist trigger with variables being refenced. This will result in a bug
16 that is easily reproducable like so
18 $ cd /sys/kernel/tracing
19 $ echo 'synthetic_sys_enter char[] comm; long id' >> synthetic_events
20 $ echo 'hist:keys=common_pid.execname,id.syscall:vals=hitcount:comm=common_pid.execname' >> events/raw_syscalls/sys_enter/trigger
21 $ echo 'hist:keys=common_pid.execname,id.syscall:onmatch(raw_syscalls.sys_enter).synthetic_sys_enter($comm, id)' >> events/raw_syscalls/sys_enter/trigger
22 $ echo '!hist:keys=common_pid.execname,id.syscall:vals=hitcount:comm=common_pid.execname' >> events/raw_syscalls/sys_enter/trigger
24 [ 100.263533] ==================================================================
25 [ 100.264634] BUG: KASAN: slab-use-after-free in resolve_var_refs+0xc7/0x180
26 [ 100.265520] Read of size 8 at addr ffff88810375d0f0 by task bash/439
28 [ 100.266533] CPU: 2 PID: 439 Comm: bash Not tainted 6.5.0-rc1 #4
29 [ 100.267277] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-20220807_005459-localhost 04/01/2014
30 [ 100.268561] Call Trace:
32 [ 100.269189] dump_stack_lvl+0x4c/0x70
33 [ 100.269680] print_report+0xc5/0x600
34 [ 100.270165] ? resolve_var_refs+0xc7/0x180
35 [ 100.270697] ? kasan_complete_mode_report_info+0x80/0x1f0
36 [ 100.271389] ? resolve_var_refs+0xc7/0x180
37 [ 100.271913] kasan_report+0xbd/0x100
38 [ 100.272380] ? resolve_var_refs+0xc7/0x180
39 [ 100.272920] __asan_load8+0x71/0xa0
40 [ 100.273377] resolve_var_refs+0xc7/0x180
41 [ 100.273888] event_hist_trigger+0x749/0x860
42 [ 100.274505] ? kasan_save_stack+0x2a/0x50
43 [ 100.275024] ? kasan_set_track+0x29/0x40
44 [ 100.275536] ? __pfx_event_hist_trigger+0x10/0x10
45 [ 100.276138] ? ksys_write+0xd1/0x170
46 [ 100.276607] ? do_syscall_64+0x3c/0x90
47 [ 100.277099] ? entry_SYSCALL_64_after_hwframe+0x6e/0xd8
48 [ 100.277771] ? destroy_hist_data+0x446/0x470
49 [ 100.278324] ? event_hist_trigger_parse+0xa6c/0x3860
50 [ 100.278962] ? __pfx_event_hist_trigger_parse+0x10/0x10
51 [ 100.279627] ? __kasan_check_write+0x18/0x20
52 [ 100.280177] ? mutex_unlock+0x85/0xd0
53 [ 100.280660] ? __pfx_mutex_unlock+0x10/0x10
54 [ 100.281200] ? kfree+0x7b/0x120
55 [ 100.281619] ? ____kasan_slab_free+0x15d/0x1d0
56 [ 100.282197] ? event_trigger_write+0xac/0x100
57 [ 100.282764] ? __kasan_slab_free+0x16/0x20
58 [ 100.283293] ? __kmem_cache_free+0x153/0x2f0
59 [ 100.283844] ? sched_mm_cid_remote_clear+0xb1/0x250
60 [ 100.284550] ? __pfx_sched_mm_cid_remote_clear+0x10/0x10
61 [ 100.285221] ? event_trigger_write+0xbc/0x100
62 [ 100.285781] ? __kasan_check_read+0x15/0x20
63 [ 100.286321] ? __bitmap_weight+0x66/0xa0
64 [ 100.286833] ? _find_next_bit+0x46/0xe0
65 [ 100.287334] ? task_mm_cid_work+0x37f/0x450
66 [ 100.287872] event_triggers_call+0x84/0x150
67 [ 100.288408] trace_event_buffer_commit+0x339/0x430
68 [ 100.289073] ? ring_buffer_event_data+0x3f/0x60
69 [ 100.292189] trace_event_raw_event_sys_enter+0x8b/0xe0
70 [ 100.295434] syscall_trace_enter.constprop.0+0x18f/0x1b0
71 [ 100.298653] syscall_enter_from_user_mode+0x32/0x40
72 [ 100.301808] do_syscall_64+0x1a/0x90
73 [ 100.304748] entry_SYSCALL_64_after_hwframe+0x6e/0xd8
74 [ 100.307775] RIP: 0033:0x7f686c75c1cb
75 [ 100.310617] Code: 73 01 c3 48 8b 0d 65 3c 10 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 21 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 35 3c 10 00 f7 d8 64 89 01 48
76 [ 100.317847] RSP: 002b:00007ffc60137a38 EFLAGS: 00000246 ORIG_RAX: 0000000000000021
77 [ 100.321200] RAX: ffffffffffffffda RBX: 000055f566469ea0 RCX: 00007f686c75c1cb
78 [ 100.324631] RDX: 0000000000000001 RSI: 0000000000000001 RDI: 000000000000000a
79 [ 100.328104] RBP: 00007ffc60137ac0 R08: 00007f686c818460 R09: 000000000000000a
80 [ 100.331509] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000009
81 [ 100.334992] R13: 0000000000000007 R14: 000000000000000a R15: 0000000000000007
84 We hit the bug because when second hist trigger has was created
85 has_hist_vars() returned false because hist trigger did not have
86 variables. As a result of that save_hist_vars() was not called to add
87 the trigger to trace_array->hist_vars. Later on when we attempted to
88 remove the first histogram find_any_var_ref() failed to detect it is
89 being used because it did not find the second trigger in hist_vars list.
91 With this change we wait until trigger actions are created so we can take
92 into consideration if hist trigger has variable references. Also, now we
93 check the return value of save_hist_vars() and fail trigger creation if
94 save_hist_vars() fails.
96 Link: https://lore.kernel.org/linux-trace-kernel/20230712223021.636335-1-mkhalfella@purestorage.com
98 Cc: stable@vger.kernel.org
99 Fixes: 067fe038e70f6 ("tracing: Add variable reference handling to hist triggers")
100 Signed-off-by: Mohamed Khalfella <mkhalfella@purestorage.com>
101 Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
102 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
104 kernel/trace/trace_events_hist.c | 8 +++++---
105 1 file changed, 5 insertions(+), 3 deletions(-)
107 --- a/kernel/trace/trace_events_hist.c
108 +++ b/kernel/trace/trace_events_hist.c
109 @@ -5787,13 +5787,15 @@ static int event_hist_trigger_func(struc
110 if (get_named_trigger_data(trigger_data))
113 - if (has_hist_vars(hist_data))
114 - save_hist_vars(hist_data);
116 ret = create_actions(hist_data, file);
120 + if (has_hist_vars(hist_data) || hist_data->n_var_refs) {
121 + if (save_hist_vars(hist_data))
125 ret = tracing_map_init(hist_data->map);