tracing: Fixes for 5.9
Subsystems (4)
Steven Rostedt
maintainercover tracing: Fixes for 5.9
git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
for-next
Head SHA1: a27026e95b57acbb8df7182e020b099e7f3b5ac3
Adrian Hunter (1):
ftrace: Fix missing synchronize_rcu() removing trampoline from kallsyms
Jason Yan (1):
bootconfig: init: make xbc_namebuf static
Masami Hiramatsu (2):
kprobes: Fix to check probe enabled before disarm_kprobe_ftrace()
kprobes: tracing/kprobes: Fix to kill kprobes on initmem after boot
Miroslav Benes (1):
ftrace: Free the trampoline when ftrace_startup() fails
Sebastian Andrzej Siewior (1):
tracing: Make the space reserved for the pid wider
Tobias Klauser (1):
ftrace: Let ftrace_enable_sysctl take a kernel pointer buffer
Tom Rix (1):
tracing: fix double free
----
include/linux/ftrace.h | 3 +-- include/linux/kprobes.h | 5 +++++ init/main.c | 4 +++- kernel/kprobes.c | 27 +++++++++++++++++++++++++-- kernel/trace/ftrace.c | 6 ++++-- kernel/trace/trace.c | 38 +++++++++++++++++++------------------- kernel/trace/trace_events_hist.c | 1 - kernel/trace/trace_output.c | 12 ++++++------ 8 files changed, 63 insertions(+), 33 deletions(-)
Steven Rostedt
maintainerPATCH 1/8 kprobes: Fix to check probe enabled before disarm_kprobe_ftrace()
From: Masami Hiramatsu <[email protected]>
Commit 0cb2f1372baa ("kprobes: Fix NULL pointer dereference at kprobe_ftrace_handler") fixed one bug but not completely fixed yet. If we run a kprobe_module.tc of ftracetest, kernel showed a warning as below.
# ./ftracetest test.d/kprobe/kprobe_module.tc === Ftrace unit tests === [1] Kprobe dynamic event - probing module ... [ 22.400215] ------------[ cut here ]------------ [ 22.400962] Failed to disarm kprobe-ftrace at trace_printk_irq_work+0x0/0x7e [trace_printk] (-2) [ 22.402139] WARNING: CPU: 7 PID: 200 at kernel/kprobes.c:1091 __disarm_kprobe_ftrace.isra.0+0x7e/0xa0 [ 22.403358] Modules linked in: trace_printk(-) [ 22.404028] CPU: 7 PID: 200 Comm: rmmod Not tainted 5.9.0-rc2+ #66 [ 22.404870] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1 04/01/2014 [ 22.406139] RIP: 0010:__disarm_kprobe_ftrace.isra.0+0x7e/0xa0 [ 22.406947] Code: 30 8b 03 eb c9 80 3d e5 09 1f 01 00 75 dc 49 8b 34 24 89 c2 48 c7 c7 a0 c2 05 82 89 45 e4 c6 05 cc 09 1f 01 01 e8 a9 c7 f0 ff <0f> 0b 8b 45 e4 eb b9 89 c6 48 c7 c7 70 c2 05 82 89 45 e4 e8 91 c7 [ 22.409544] RSP: 0018:ffffc90000237df0 EFLAGS: 00010286 [ 22.410385] RAX: 0000000000000000 RBX: ffffffff83066024 RCX: 0000000000000000 [ 22.411434] RDX: 0000000000000001 RSI: ffffffff810de8d3 RDI: ffffffff810de8d3 [ 22.412687] RBP: ffffc90000237e10 R08: 0000000000000001 R09: 0000000000000001 [ 22.413762] R10: 0000000000000000 R11: 0000000000000001 R12: ffff88807c478640 [ 22.414852] R13: ffffffff8235ebc0 R14: ffffffffa00060c0 R15: 0000000000000000 [ 22.415941] FS: 00000000019d48c0(0000) GS:ffff88807d7c0000(0000) knlGS:0000000000000000 [ 22.417264] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 22.418176] CR2: 00000000005bb7e3 CR3: 0000000078f7a000 CR4: 00000000000006a0 [ 22.419309] Call Trace: [ 22.419990] kill_kprobe+0x94/0x160 [ 22.420652] kprobes_module_callback+0x64/0x230 [ 22.421470] notifier_call_chain+0x4f/0x70 [ 22.422184] blocking_notifier_call_chain+0x49/0x70 [ 22.422979] __x64_sys_delete_module+0x1ac/0x240 [ 22.423733] do_syscall_64+0x38/0x50 [ 22.424366] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 22.425176] RIP: 0033:0x4bb81d [ 22.425741] Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e0 ff ff ff f7 d8 64 89 01 48 [ 22.428726] RSP: 002b:00007ffc70fef008 EFLAGS: 00000246 ORIG_RAX: 00000000000000b0 [ 22.430169] RAX: ffffffffffffffda RBX: 00000000019d48a0 RCX: 00000000004bb81d [ 22.431375] RDX: 0000000000000000 RSI: 0000000000000880 RDI: 00007ffc70fef028 [ 22.432543] RBP: 0000000000000880 R08: 00000000ffffffff R09: 00007ffc70fef320 [ 22.433692] R10: 0000000000656300 R11: 0000000000000246 R12: 00007ffc70fef028 [ 22.434635] R13: 0000000000000000 R14: 0000000000000002 R15: 0000000000000000 [ 22.435682] irq event stamp: 1169 [ 22.436240] hardirqs last enabled at (1179): [<ffffffff810df542>] console_unlock+0x422/0x580 [ 22.437466] hardirqs last disabled at (1188): [<ffffffff810df19b>] console_unlock+0x7b/0x580 [ 22.438608] softirqs last enabled at (866): [<ffffffff81c0038e>] __do_softirq+0x38e/0x490 [ 22.439637] softirqs last disabled at (859): [<ffffffff81a00f42>] asm_call_on_stack+0x12/0x20 [ 22.440690] ---[ end trace 1e7ce7e1e4567276 ]--- [ 22.472832] trace_kprobe: This probe might be able to register after target module is loaded. Continue.
This is because the kill_kprobe() calls disarm_kprobe_ftrace() even if the given probe is not enabled. In that case, ftrace_set_filter_ip() fails because the given probe point is not registered to ftrace.
Fix to check the given (going) probe is enabled before invoking disarm_kprobe_ftrace().
--- kernel/kprobes.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
kernel/kprobes.c +3 -2
@@ -2159,9 +2159,10 @@ static void kill_kprobe(struct kprobe *p)/* * The module is going away. We should disarm the kprobe which -* is using ftrace. +* is using ftrace, because ftrace framework is still available at +* MODULE_STATE_GOING notification. */ -if (kprobe_ftrace (p)) +if (kprobe_ftrace (p) && !kprobe_disabled (p) && !kprobes_all_disarmed)disarm_kprobe_ftrace (p); }
Signature · 1 line
2.28.0
Steven Rostedt
maintainerPATCH 2/8 ftrace: Free the trampoline when ftrace_startup() fails
In reply to Steven RostedtFrom: Miroslav Benes <[email protected]>
Commit fc0ea795f53c ("ftrace: Add symbols for ftrace trampolines") missed to remove ops from new ftrace_ops_trampoline_list in ftrace_startup() if ftrace_hash_ipmodify_enable() fails there. It may lead to BUG if such ops come from a module which may be removed.
Moreover, the trampoline itself is not freed in this case.
Fix it by calling ftrace_trampoline_free() during the rollback.
--- kernel/trace/ftrace.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/trace/ftrace.c +2 -0
@@ -2862,6 +2862,8 @@ int ftrace_startup(struct ftrace_ops *ops, int command)__unregister_ftrace_function (ops); ftrace_start_up--; ops->flags &= ~FTRACE_OPS_FL_ENABLED ; +if (ops->flags &FTRACE_OPS_FL_DYNAMIC ) +ftrace_trampoline_free (ops);return ret; }
Signature · 1 line
2.28.0
Steven Rostedt
maintainerPATCH 3/8 ftrace: Fix missing synchronize_rcu() removing trampoline from kallsyms
In reply to Steven RostedtFrom: Adrian Hunter <[email protected]>
Add synchronize_rcu() after list_del_rcu() in ftrace_remove_trampoline_from_kallsyms() to protect readers of ftrace_ops_trampoline_list (in ftrace_get_trampoline_kallsym) which is used when kallsyms is read.
--- kernel/trace/ftrace.c | 1 + 1 file changed, 1 insertion(+)
kernel/trace/ftrace.c +1 -0
@@ -2782,6 +2782,7 @@ static void ftrace_remove_trampoline_from_kallsyms(struct ftrace_ops *ops) {lockdep_assert_held (&ftrace_lock);list_del_rcu (&ops->list); +synchronize_rcu (); }/*
Signature · 1 line
2.28.0
Steven Rostedt
maintainerPATCH 4/8 tracing: Make the space reserved for the pid wider
In reply to Steven RostedtFrom: Sebastian Andrzej Siewior <[email protected]>
For 64bit CONFIG_BASE_SMALL=0 systems PID_MAX_LIMIT is set by default to 4194304. During boot the kernel sets a new value based on number of CPUs but no lower than 32768. It is 1024 per CPU so with 128 CPUs the default becomes 131072 which needs six digits.
This value can be increased during run time but must not exceed the initial upper limit.
Systemd sometime after v241 sets it to the upper limit during boot. The result is that when the pid exceeds five digits, the trace output is a little hard to read because it is no longer properly padded (same like on big iron with 98+ CPUs).
Increase the pid padding to seven digits.
--- kernel/trace/trace.c | 38 ++++++++++++++++++------------------- kernel/trace/trace_output.c | 12 ++++++------ 2 files changed, 25 insertions(+), 25 deletions(-)
kernel/trace/trace.c +19 -19
@@ -3782,14 +3782,14 @@ unsigned long trace_total_entries(struct trace_array *tr)static void print_lat_help_header (struct seq_file *m) { -seq_puts (m,"# _------=> CPU# \n" -"# / _-----=> irqs-off \n" -"# | / _----=> need-resched \n" -"# || / _---=> hardirq/softirq \n" -"# ||| / _--=> preempt-depth \n" -"# |||| / delay \n" -"# cmd pid ||||| time | caller \n" -"# \\ / ||||| \\ | / \n" ); +seq_puts (m,"# _------=> CPU# \n" +"# / _-----=> irqs-off \n" +"# | / _----=> need-resched \n" +"# || / _---=> hardirq/softirq \n" +"# ||| / _--=> preempt-depth \n" +"# |||| / delay \n" +"# cmd pid ||||| time | caller \n" +"# \\ / ||||| \\ | / \n" ); }static void print_event_info (struct array_buffer *buf,struct seq_file *m)
@@ -3810,26 +3810,26 @@ static void print_func_help_header(struct array_buffer *buf, struct seq_file *m,print_event_info (buf, m); -seq_printf (m,"# TASK-PID %s CPU# TIMESTAMP FUNCTION\n" , tgid ?"TGID " :"" ); -seq_printf (m,"# | | %s | | |\n" , tgid ?" | " :"" ); +seq_printf (m,"# TASK-PID %s CPU# TIMESTAMP FUNCTION\n" , tgid ?" TGID " :"" ); +seq_printf (m,"# | | %s | | |\n" , tgid ?" | " :"" ); }static void print_func_help_header_irq (struct array_buffer *buf,struct seq_file *m,unsigned int flags) {bool tgid = flags &TRACE_ITER_RECORD_TGID ; -const char *space =" " ; -int prec = tgid ?10 :2 ; +const char *space =" " ; +int prec = tgid ?12 :2 ;print_event_info (buf, m); -seq_printf (m,"# %.*s _-----=> irqs-off\n" , prec, space); -seq_printf (m,"# %.*s / _----=> need-resched\n" , prec, space); -seq_printf (m,"# %.*s| / _---=> hardirq/softirq\n" , prec, space); -seq_printf (m,"# %.*s|| / _--=> preempt-depth\n" , prec, space); -seq_printf (m,"# %.*s||| / delay\n" , prec, space); -seq_printf (m,"# TASK-PID %.*sCPU# |||| TIMESTAMP FUNCTION\n" , prec," TGID " ); -seq_printf (m,"# | | %.*s | |||| | |\n" , prec," | " ); +seq_printf (m,"# %.*s _-----=> irqs-off\n" , prec, space); +seq_printf (m,"# %.*s / _----=> need-resched\n" , prec, space); +seq_printf (m,"# %.*s| / _---=> hardirq/softirq\n" , prec, space); +seq_printf (m,"# %.*s|| / _--=> preempt-depth\n" , prec, space); +seq_printf (m,"# %.*s||| / delay\n" , prec, space); +seq_printf (m,"# TASK-PID %.*s CPU# |||| TIMESTAMP FUNCTION\n" , prec," TGID " ); +seq_printf (m,"# | | %.*s | |||| | |\n" , prec," | " ); }void
kernel/trace/trace_output.c +6 -6
@@ -497,7 +497,7 @@ lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)trace_find_cmdline (entry->pid, comm); -trace_seq_printf (s,"%8.8s-%-5d %3d" , +trace_seq_printf (s,"%8.8s-%-7d %3d" , comm, entry->pid, cpu);return trace_print_lat_fmt (s, entry);
@@ -588,15 +588,15 @@ int trace_print_context(struct trace_iterator *iter)trace_find_cmdline (entry->pid, comm); -trace_seq_printf (s,"%16s-%-5d " , comm, entry->pid); +trace_seq_printf (s,"%16s-%-7d " , comm, entry->pid);if (tr->trace_flags &TRACE_ITER_RECORD_TGID ) {unsigned int tgid =trace_find_tgid (entry->pid);if (!tgid) -trace_seq_printf (s,"(-----) " ); +trace_seq_printf (s,"(-------) " );else -trace_seq_printf (s,"(%5d) " , tgid); +trace_seq_printf (s,"(%7d) " , tgid); }trace_seq_printf (s,"[%03d] " , iter->cpu);
@@ -636,7 +636,7 @@ int trace_print_lat_context(struct trace_iterator *iter)trace_find_cmdline (entry->pid, comm);trace_seq_printf ( - s,"%16s %5d %3d %d %08x %08lx " , + s,"%16s %7d %3d %d %08x %08lx " , comm, entry->pid, iter->cpu, entry->flags, entry->preempt_count, iter->idx); }else {
@@ -917,7 +917,7 @@ static enum print_line_t trace_ctxwake_print(struct trace_iterator *iter,S =task_index_to_char (field->prev_state);trace_find_cmdline (field->next_pid, comm); trace_seq_printf(&iter->seq, - " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n", + " %7d:%3d:%c %s [%03d] %7d:%3d:%c %s\n", field->prev_pid, field->prev_prio, S, delim,
Signature · 1 line
2.28.0
Steven Rostedt
maintainerPATCH 5/8 ftrace: Let ftrace_enable_sysctl take a kernel pointer buffer
In reply to Steven RostedtFrom: Tobias Klauser <[email protected]>
Commit 32927393dc1c ("sysctl: pass kernel pointers to ->proc_handler") changed ctl_table.proc_handler to take a kernel pointer. Adjust the signature of ftrace_enable_sysctl to match ctl_table.proc_handler which fixes the following sparse warning:
kernel/trace/ftrace.c:7544:43: warning: incorrect type in argument 3 (different address spaces)kernel/trace/ftrace.c:7544:43: expected void *kernel/trace/ftrace.c:7544:43: got void [noderef] __user *buffer
--- include/linux/ftrace.h | 3 +-- kernel/trace/ftrace.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-)
include/linux/ftrace.h +1 -2
@@ -85,8 +85,7 @@ static inline int ftrace_mod_get_kallsym(unsigned int symnum, unsigned long *valextern int ftrace_enabled;extern int ftrace_enable_sysctl (struct ctl_table *table,int write, -void __user *buffer,size_t *lenp, -loff_t *ppos); +void *buffer,size_t *lenp,loff_t *ppos);struct ftrace_ops ;
kernel/trace/ftrace.c +1 -2
@@ -7534,8 +7534,7 @@ static bool is_permanent_ops_registered(void)int ftrace_enable_sysctl (struct ctl_table *table,int write, -void __user *buffer,size_t *lenp, -loff_t *ppos) +void *buffer,size_t *lenp,loff_t *ppos) {int ret = -ENODEV ;
Signature · 1 line
2.28.0
Steven Rostedt
maintainerPATCH 6/8 tracing: fix double free
In reply to Steven RostedtFrom: Tom Rix <[email protected]>
clang static analyzer reports this problem
trace_events_hist.c:3824:3: warning: Attempt to free
released memory
kfree(hist_data->attrs->var_defs.name[i]);
In parse_var_defs() if there is a problem allocating var_defs.expr, the earlier var_defs.name is freed. This free is duplicated by free_var_defs() which frees the rest of the list.
Because free_var_defs() has to run anyway, remove the second free fom parse_var_defs().
--- kernel/trace/trace_events_hist.c | 1 - 1 file changed, 1 deletion(-)
kernel/trace/trace_events_hist.c +0 -1
@@ -3865,7 +3865,6 @@ static int parse_var_defs(struct hist_trigger_data *hist_data) s =kstrdup (field_str,GFP_KERNEL );if (!s) { -kfree (hist_data->attrs->var_defs.name[n_vars]); ret = -ENOMEM ; goto free; }
Signature · 1 line
2.28.0
Steven Rostedt
maintainerPATCH 7/8 kprobes: tracing/kprobes: Fix to kill kprobes on initmem after boot
In reply to Steven RostedtFrom: Masami Hiramatsu <[email protected]>
Since kprobe_event= cmdline option allows user to put kprobes on the functions in initmem, kprobe has to make such probes gone after boot. Currently the probes on the init functions in modules will be handled by module callback, but the kernel init text isn't handled. Without this, kprobes may access non-exist text area to disable or remove it.
--- include/linux/kprobes.h | 5 +++++ init/main.c | 2 ++ kernel/kprobes.c | 22 ++++++++++++++++++++++ 3 files changed, 29 insertions(+)
include/linux/kprobes.h +5 -0
@@ -373,6 +373,8 @@ void unregister_kretprobes(struct kretprobe **rps, int num);void kprobe_flush_task (struct task_struct *tk);void recycle_rp_inst (struct kretprobe_instance *ri,struct hlist_head *head); +void kprobe_free_init_mem (void ); +int disable_kprobe (struct kprobe *kp);int enable_kprobe (struct kprobe *kp);
@@ -435,6 +437,9 @@ static inline void unregister_kretprobes(struct kretprobe **rps, int num)static inline void kprobe_flush_task (struct task_struct *tk) { } +static inline void kprobe_free_init_mem (void ) +{ +}static inline int disable_kprobe (struct kprobe *kp) {return -ENOSYS ;
init/main.c +2 -0
@@ -33,6 +33,7 @@#include <linux/nmi.h> #include <linux/percpu.h> #include <linux/kmod.h> +#include <linux/kprobes.h> #include <linux/vmalloc.h> #include <linux/kernel_stat.h> #include <linux/start_kernel.h>
@@ -1402,6 +1403,7 @@ static int __ref kernel_init(void *unused)kernel_init_freeable ();/* need to finish all async __init code before freeing the memory */ async_synchronize_full (); +kprobe_free_init_mem ();ftrace_free_init_mem ();free_initmem ();mark_readonly ();
kernel/kprobes.c +22 -0
@@ -2453,6 +2453,28 @@ static struct notifier_block kprobe_module_nb = {extern unsigned long __start_kprobe_blacklist[];extern unsigned long __stop_kprobe_blacklist[]; +void kprobe_free_init_mem (void ) +{ +void *start = (void *)(&__init_begin); +void *end = (void *)(&__init_end); +struct hlist_head *head; +struct kprobe *p; +int i; + +mutex_lock (&kprobe_mutex); + +/* Kill all kprobes on initmem */ +for (i =0 ; i <KPROBE_TABLE_SIZE ; i++) { + head = &kprobe_table[i]; +hlist_for_each_entry (p, head, hlist) { +if (start <= (void *)p->addr && (void *)p->addr < end) +kill_kprobe (p); + } + } + +mutex_unlock (&kprobe_mutex); +} +static int __init init_kprobes (void ) {int i, err =0 ;
Signature · 1 line
2.28.0
Steven Rostedt
maintainerPATCH 8/8 bootconfig: init: make xbc_namebuf static
In reply to Steven RostedtFrom: Jason Yan <[email protected]>
This eliminates the following sparse warning:
init/main.c:306:6: warning: symbol 'xbc_namebuf' was not declared. Should it be static?
--- init/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
init/main.c +1 -1
@@ -304,7 +304,7 @@ static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum)#ifdef CONFIG_BOOT_CONFIG -char xbc_namebuf[XBC_KEYLEN_MAX ]__initdata ; +static char xbc_namebuf[XBC_KEYLEN_MAX ]__initdata ;#define rest (dst, end) ((end) > (dst) ? (end) - (dst) : 0)
Signature · 1 line
2.28.0