kernel-fxtec-pro1x/kernel/trace
Petr Mladek c854d9b6ef ftrace/x86: Remove possible deadlock between register_kprobe() and ftrace_run_update_code()
commit d5b844a2cf507fc7642c9ae80a9d585db3065c28 upstream.

The commit 9f255b632bf12c4dd7 ("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 9f255b632bf12c4dd7 ("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: 9f255b632bf12c4dd7 ("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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2019-07-10 09:53:44 +02:00
..
blktrace.c
bpf_trace.c bpf: fix nested bpf tracepoints with per-cpu data 2019-07-03 13:14:48 +02:00
ftrace.c ftrace/x86: Remove possible deadlock between register_kprobe() and ftrace_run_update_code() 2019-07-10 09:53:44 +02:00
Kconfig
Makefile
power-traces.c
preemptirq_delay_test.c
ring_buffer.c trace: Fix preempt_enable_no_resched() abuse 2019-05-02 09:58:54 +02:00
ring_buffer_benchmark.c
rpm-traces.c
trace.c tracing/snapshot: Resize spare buffer if size changed 2019-07-10 09:53:43 +02:00
trace.h tracing: Silence GCC 9 array bounds warning 2019-06-25 11:35:52 +08:00
trace_benchmark.c
trace_benchmark.h
trace_branch.c Revert "x86/uaccess, ftrace: Fix ftrace_likely_update() vs. SMAP" 2019-07-03 13:14:41 +02:00
trace_clock.c
trace_entries.h
trace_event_perf.c tracing/perf: Use strndup_user() instead of buggy open-coded version 2019-03-23 20:09:56 +01:00
trace_events.c tracing: Fix partial reading of trace event's id file 2019-05-25 18:23:32 +02:00
trace_events_filter.c tracing: Avoid memory leak in predicate_parse() 2019-06-09 09:17:14 +02:00
trace_events_filter_test.h
trace_events_hist.c tracing: Prevent hist_field_var_ref() from accessing NULL tracing_map_elts 2019-06-19 08:18:04 +02:00
trace_events_trigger.c
trace_export.c
trace_functions.c
trace_functions_graph.c
trace_hwlat.c
trace_irqsoff.c
trace_kdb.c tracing: Silence GCC 9 array bounds warning 2019-06-25 11:35:52 +08:00
trace_kprobe.c
trace_kprobe_selftest.c
trace_kprobe_selftest.h
trace_mmiotrace.c
trace_nop.c
trace_output.c
trace_output.h
trace_preemptirq.c
trace_printk.c
trace_probe.c
trace_probe.h
trace_sched_switch.c
trace_sched_wakeup.c
trace_selftest.c
trace_selftest_dynamic.c
trace_seq.c
trace_stack.c
trace_stat.c
trace_stat.h
trace_syscalls.c
trace_uprobe.c
tracing_map.c
tracing_map.h