aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2017-05-17 04:19:49 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-25 09:44:47 -0400
commitdd0023d7105c4266adeb14881c479950d6a9ef2a (patch)
tree4d9223d578effdf9c3818e222e3a14fed0cdb56b
parentcc0aa21de47c64f7eb557bd41447a9ebe312c0ab (diff)
tracing/kprobes: Enforce kprobes teardown after testing
commit 30e7d894c1478c88d50ce94ddcdbd7f9763d9cdd 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.home Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Masami Hiramatsu <mhiramat@kernel.org> Fixes: 6274de498 ("kprobes: Support delayed unoptimizing") Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--include/linux/kprobes.h4
-rw-r--r--kernel/kprobes.c2
-rw-r--r--kernel/trace/trace_kprobe.c5
3 files changed, 9 insertions, 2 deletions
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f6849084248..e23392517db9 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -330,7 +330,9 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table,
330 int write, void __user *buffer, 330 int write, void __user *buffer,
331 size_t *length, loff_t *ppos); 331 size_t *length, loff_t *ppos);
332#endif 332#endif
333 333extern void wait_for_kprobe_optimizer(void);
334#else
335static inline void wait_for_kprobe_optimizer(void) { }
334#endif /* CONFIG_OPTPROBES */ 336#endif /* CONFIG_OPTPROBES */
335#ifdef CONFIG_KPROBES_ON_FTRACE 337#ifdef CONFIG_KPROBES_ON_FTRACE
336extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, 338extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index d63095472ea9..a1a07cf1101f 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -563,7 +563,7 @@ static void kprobe_optimizer(struct work_struct *work)
563} 563}
564 564
565/* Wait for completing optimization and unoptimization */ 565/* Wait for completing optimization and unoptimization */
566static void wait_for_kprobe_optimizer(void) 566void wait_for_kprobe_optimizer(void)
567{ 567{
568 mutex_lock(&kprobe_mutex); 568 mutex_lock(&kprobe_mutex);
569 569
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index eb6c9f1d3a93..8d2b4d8fd714 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -1484,6 +1484,11 @@ static __init int kprobe_trace_self_tests_init(void)
1484 1484
1485end: 1485end:
1486 release_all_trace_kprobes(); 1486 release_all_trace_kprobes();
1487 /*
1488 * Wait for the optimizer work to finish. Otherwise it might fiddle
1489 * with probes in already freed __init text.
1490 */
1491 wait_for_kprobe_optimizer();
1487 if (warn) 1492 if (warn)
1488 pr_cont("NG: Some tests are failed. Please check them.\n"); 1493 pr_cont("NG: Some tests are failed. Please check them.\n");
1489 else 1494 else