linux/kernel/trace
Petr Mladek d5b844a2cf ftrace/x86: Remove possible deadlock between register_kprobe() and ftrace_run_update_code()
The commit 9f255b632b ("module: Fix livepatch/ftrace module text
permissions race") causes a possible deadlock between register_kprobe()
and ftrace_run_update_code() when ftrace is using stop_machine().

The existing dependency chain (in reverse order) is:

-> #1 (text_mutex){+.+.}:
       validate_chain.isra.21+0xb32/0xd70
       __lock_acquire+0x4b8/0x928
       lock_acquire+0x102/0x230
       __mutex_lock+0x88/0x908
       mutex_lock_nested+0x32/0x40
       register_kprobe+0x254/0x658
       init_kprobes+0x11a/0x168
       do_one_initcall+0x70/0x318
       kernel_init_freeable+0x456/0x508
       kernel_init+0x22/0x150
       ret_from_fork+0x30/0x34
       kernel_thread_starter+0x0/0xc

-> #0 (cpu_hotplug_lock.rw_sem){++++}:
       check_prev_add+0x90c/0xde0
       validate_chain.isra.21+0xb32/0xd70
       __lock_acquire+0x4b8/0x928
       lock_acquire+0x102/0x230
       cpus_read_lock+0x62/0xd0
       stop_machine+0x2e/0x60
       arch_ftrace_update_code+0x2e/0x40
       ftrace_run_update_code+0x40/0xa0
       ftrace_startup+0xb2/0x168
       register_ftrace_function+0x64/0x88
       klp_patch_object+0x1a2/0x290
       klp_enable_patch+0x554/0x980
       do_one_initcall+0x70/0x318
       do_init_module+0x6e/0x250
       load_module+0x1782/0x1990
       __s390x_sys_finit_module+0xaa/0xf0
       system_call+0xd8/0x2d0

 Possible unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  lock(text_mutex);
                               lock(cpu_hotplug_lock.rw_sem);
                               lock(text_mutex);
  lock(cpu_hotplug_lock.rw_sem);

It is similar problem that has been solved by the commit 2d1e38f566
("kprobes: Cure hotplug lock ordering issues"). Many locks are involved.
To be on the safe side, text_mutex must become a low level lock taken
after cpu_hotplug_lock.rw_sem.

This can't be achieved easily with the current ftrace design.
For example, arm calls set_all_modules_text_rw() already in
ftrace_arch_code_modify_prepare(), see arch/arm/kernel/ftrace.c.
This functions is called:

  + outside stop_machine() from ftrace_run_update_code()
  + without stop_machine() from ftrace_module_enable()

Fortunately, the problematic fix is needed only on x86_64. It is
the only architecture that calls set_all_modules_text_rw()
in ftrace path and supports livepatching at the same time.

Therefore it is enough to move text_mutex handling from the generic
kernel/trace/ftrace.c into arch/x86/kernel/ftrace.c:

   ftrace_arch_code_modify_prepare()
   ftrace_arch_code_modify_post_process()

This patch basically reverts the ftrace part of the problematic
commit 9f255b632b ("module: Fix livepatch/ftrace module
text permissions race"). And provides x86_64 specific-fix.

Some refactoring of the ftrace code will be needed when livepatching
is implemented for arm or nds32. These architectures call
set_all_modules_text_rw() and use stop_machine() at the same time.

Link: http://lkml.kernel.org/r/20190627081334.12793-1-pmladek@suse.com

Fixes: 9f255b632b ("module: Fix livepatch/ftrace module text permissions race")
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Reported-by: Miroslav Benes <mbenes@suse.cz>
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Petr Mladek <pmladek@suse.com>
[
  As reviewed by Miroslav Benes <mbenes@suse.cz>, removed return value of
  ftrace_run_update_code() as it is a void function.
]
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
2019-06-28 14:20:25 -04:00
..
blktrace.c blkcg: annotate implicit fall through 2019-03-13 14:31:12 -06:00
bpf_trace.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next 2019-05-07 22:03:58 -07:00
fgraph.c tracing: Fix ftrace_graph_get_ret_stack() to use task and not current 2018-12-22 08:21:03 -05:00
ftrace.c ftrace/x86: Remove possible deadlock between register_kprobe() and ftrace_run_update_code() 2019-06-28 14:20:25 -04:00
ftrace_internal.h ftrace: Create new ftrace_internal.h header 2018-12-08 20:54:06 -05:00
Kconfig tracing: stop making gpio tracing configurable 2019-04-08 15:11:48 +02:00
Makefile tracing: Add unified dynamic event framework 2018-12-08 20:54:09 -05:00
power-traces.c
preemptirq_delay_test.c tracing: Use trace_clock_local() for looping in preemptirq_delay_test.c 2018-10-17 15:35:33 -04:00
ring_buffer.c The major changes in this tracing update includes: 2019-05-15 16:05:47 -07:00
ring_buffer_benchmark.c ring-buffer: Fix mispelling of Calculate 2019-05-08 12:15:12 -04:00
rpm-traces.c
trace.c tracing: Make two symbols static 2019-06-14 16:49:26 -04:00
trace.h tracing: Silence GCC 9 array bounds warning 2019-05-25 23:04:30 -04:00
trace_benchmark.c
trace_benchmark.h tracing: Fix SPDX format headers to use C++ style comments 2018-08-16 19:08:06 -04:00
trace_branch.c x86/uaccess, ftrace: Fix ftrace_likely_update() vs. SMAP 2019-04-03 11:02:24 +02:00
trace_clock.c tracing: Add SPDX License format tags to tracing files 2018-08-16 19:08:06 -04:00
trace_dynevent.c tracing: initialize variable in create_dyn_event() 2019-03-26 08:35:36 -04:00
trace_dynevent.h tracing: Add unified dynamic event framework 2018-12-08 20:54:09 -05:00
trace_entries.h tracing: Change the function format to display function names by perf 2019-02-11 14:53:43 -05:00
trace_event_perf.c tracing/perf: Use strndup_user() instead of buggy open-coded version 2019-02-21 10:35:10 -05:00
trace_events.c tracing: Fix partial reading of trace event's id file 2019-05-08 12:15:12 -04:00
trace_events_filter.c tracing: Avoid memory leak in predicate_parse() 2019-05-28 16:27:58 -04:00
trace_events_filter_test.h tracing: Fix SPDX format headers to use C++ style comments 2018-08-16 19:08:06 -04:00
trace_events_hist.c tracing: Add a check_val() check before updating cond_snapshot() track_val 2019-05-21 12:48:07 -04:00
trace_events_trigger.c tracing: Add trace_array parameter to create_event_filter() 2019-04-08 09:22:28 -04:00
trace_export.c
trace_functions.c
trace_functions_graph.c tracing: Put a margin between flags and duration for wakeup tracers 2019-02-06 11:56:19 -05:00
trace_hwlat.c tracing: Add SPDX License format tags to tracing files 2018-08-16 19:08:06 -04:00
trace_irqsoff.c The biggest change for this release is in the histogram code. 2019-03-11 17:01:32 -07:00
trace_kdb.c tracing: Silence GCC 9 array bounds warning 2019-05-25 23:04:30 -04:00
trace_kprobe.c tracing: Use tracing error_log with probe events 2019-04-02 18:24:07 -04:00
trace_kprobe_selftest.c
trace_kprobe_selftest.h tracing: Fix SPDX format headers to use C++ style comments 2018-08-16 19:08:06 -04:00
trace_mmiotrace.c
trace_nop.c
trace_output.c tracing: Fix out-of-range read in trace_stack_print() 2019-06-14 16:28:42 -04:00
trace_output.h tracing: Fix SPDX format headers to use C++ style comments 2018-08-16 19:08:06 -04:00
trace_preemptirq.c kprobes: Prohibit probing on hardirq tracers 2019-02-13 08:16:40 +01:00
trace_printk.c tracing: Trivia spelling fix containerof() -> container_of() 2018-09-26 12:21:00 +03:00
trace_probe.c tracing: Replace kzalloc with kcalloc 2019-05-08 12:15:12 -04:00
trace_probe.h tracing: uprobes: Re-enable $comm support for uprobe events 2019-05-08 12:15:11 -04:00
trace_probe_tmpl.h tracing: probeevent: Do not accumulate on ret variable 2019-05-08 12:15:11 -04:00
trace_sched_switch.c
trace_sched_wakeup.c tracing: Add conditional snapshot 2019-02-20 13:51:06 -05:00
trace_selftest.c function_graph: Have selftest also emulate tr->reset() as it did with tr->init() 2019-04-21 19:46:56 -04:00
trace_selftest_dynamic.c
trace_seq.c tracing: Add SPDX License format tags to tracing files 2018-08-16 19:08:06 -04:00
trace_stack.c tracing: Remove the last struct stack_trace usage 2019-04-29 12:37:56 +02:00
trace_stat.c
trace_stat.h tracing: Fix SPDX format headers to use C++ style comments 2018-08-16 19:08:06 -04:00
trace_syscalls.c syscalls: Remove start and number from syscall_get_arguments() args 2019-04-05 09:26:43 -04:00
trace_uprobe.c tracing/uprobe: Fix obsolete comment on trace_uprobe_create() 2019-06-14 17:00:36 -04:00
tracing_map.c tracing: Add SPDX License format tags to tracing files 2018-08-16 19:08:06 -04:00
tracing_map.h tracing: Fix SPDX format headers to use C++ style comments 2018-08-16 19:08:06 -04:00