Commit 63ab09e3 authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Greg Kroah-Hartman

tracing/kprobes: Enforce kprobes teardown after testing

commit 30e7d894 upstream.

Enabling the tracer selftest triggers occasionally the warning in
text_poke(), which warns when the to be modified page is not marked
reserved.

The reason is that the tracer selftest installs kprobes on functions marked
__init for testing. These probes are removed after the tests, but that
removal schedules the delayed kprobes_optimizer work, which will do the
actual text poke. If the work is executed after the init text is freed,
then the warning triggers. The bug can be reproduced reliably when the work
delay is increased.

Flush the optimizer work and wait for the optimizing/unoptimizing lists to
become empty before returning from the kprobes tracer selftest. That
ensures that all operations which were queued due to the probes removal
have completed.

Link: http://lkml.kernel.org/r/20170516094802.76a468bb@gandalf.local.homeSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Acked-by: default avatarMasami Hiramatsu <mhiramat@kernel.org>
Fixes: 6274de49 ("kprobes: Support delayed unoptimizing")
Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 18b4b0ab
...@@ -347,6 +347,9 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table, ...@@ -347,6 +347,9 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table,
int write, void __user *buffer, int write, void __user *buffer,
size_t *length, loff_t *ppos); size_t *length, loff_t *ppos);
#endif #endif
extern void wait_for_kprobe_optimizer(void);
#else
static inline void wait_for_kprobe_optimizer(void) { }
#endif /* CONFIG_OPTPROBES */ #endif /* CONFIG_OPTPROBES */
#ifdef CONFIG_KPROBES_ON_FTRACE #ifdef CONFIG_KPROBES_ON_FTRACE
extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
......
...@@ -598,7 +598,7 @@ static void kprobe_optimizer(struct work_struct *work) ...@@ -598,7 +598,7 @@ static void kprobe_optimizer(struct work_struct *work)
} }
/* Wait for completing optimization and unoptimization */ /* Wait for completing optimization and unoptimization */
static void wait_for_kprobe_optimizer(void) void wait_for_kprobe_optimizer(void)
{ {
mutex_lock(&kprobe_mutex); mutex_lock(&kprobe_mutex);
......
...@@ -1511,6 +1511,11 @@ static __init int kprobe_trace_self_tests_init(void) ...@@ -1511,6 +1511,11 @@ static __init int kprobe_trace_self_tests_init(void)
end: end:
release_all_trace_kprobes(); release_all_trace_kprobes();
/*
* Wait for the optimizer work to finish. Otherwise it might fiddle
* with probes in already freed __init text.
*/
wait_for_kprobe_optimizer();
if (warn) if (warn)
pr_cont("NG: Some tests are failed. Please check them.\n"); pr_cont("NG: Some tests are failed. Please check them.\n");
else else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment