]> git.hungrycats.org Git - linux/commitdiff
tracing/kprobes: Enforce kprobes teardown after testing
authorThomas Gleixner <tglx@linutronix.de>
Wed, 17 May 2017 08:19:49 +0000 (10:19 +0200)
committerBen Hutchings <ben@decadent.org.uk>
Fri, 15 Sep 2017 17:30:44 +0000 (18:30 +0100)
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>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
include/linux/kprobes.h
kernel/kprobes.c
kernel/trace/trace_kprobe.c

index dce6e4dbeda7639bc87eca49e9102a41c0f01c89..8e44d7305fef91012196b0f73d793b927b47d227 100644 (file)
@@ -292,7 +292,9 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table,
                                             int write, void __user *buffer,
                                             size_t *length, loff_t *ppos);
 #endif
-
+extern void wait_for_kprobe_optimizer(void);
+#else
+static inline void wait_for_kprobe_optimizer(void) { }
 #endif /* CONFIG_OPTPROBES */
 
 /* Get the kprobe at this addr (if any) - called with preemption disabled */
index bc90b875f63a3eb2575944ed9ac6e414dca74176..a4f561a3f27fbbd8d8efe4109ea9168ac10d4ed1 100644 (file)
@@ -598,7 +598,7 @@ static __kprobes void kprobe_optimizer(struct work_struct *work)
 }
 
 /* Wait for completing optimization and unoptimization */
-static __kprobes void wait_for_kprobe_optimizer(void)
+__kprobes void wait_for_kprobe_optimizer(void)
 {
        if (delayed_work_pending(&optimizing_work))
                wait_for_completion(&optimizer_comp);
index 00d527c945a4ceec13f8633ec6a5bf8be4c1debb..bcdff33f78219cfa16152d9f53f200fd23d3c9be 100644 (file)
@@ -2109,6 +2109,11 @@ static __init int kprobe_trace_self_tests_init(void)
 
 end:
        release_all_trace_probes();
+       /*
+        * Wait for the optimizer work to finish. Otherwise it might fiddle
+        * with probes in already freed __init text.
+        */
+       wait_for_kprobe_optimizer();
        if (warn)
                pr_cont("NG: Some tests are failed. Please check them.\n");
        else