From: Masami Hiramatsu <mhiramat@kernel.org>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: LKML <linux-kernel@vger.kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@kernel.org>,
Steven Rostedt <rostedt@goodmis.org>,
Sebastian Siewior <bigeasy@linutronix.de>,
Paul McKenney <paulmck@linux.vnet.ibm.com>,
Masami Hiramatsu <mhiramat@kernel.org>
Subject: Re: [patch V3 25/32] kprobes: Cure hotplug lock ordering issues
Date: Thu, 25 May 2017 00:54:10 +0900 [thread overview]
Message-ID: <20170525005410.f7142f05cd5d248600c61f96@kernel.org> (raw)
In-Reply-To: <20170524081549.104864779@linutronix.de>
On Wed, 24 May 2017 10:15:36 +0200
Thomas Gleixner <tglx@linutronix.de> wrote:
> Converting the cpu hotplug locking to a percpu rwsem unearthed hidden lock
> ordering problems.
>
> There is a wide range of locks involved in this: kprobe_mutex,
> jump_label_mutex, ftrace_lock, text_mutex, event_mutex,
> func_hash->regex_lock and a gazillion of lock order permutations with
> nested get_online_cpus() calls.
And module_mutex too ;-)
>
> Some of those permutations are potential deadlocks even with the current
> nesting hotplug locking scheme, but they can't be discovered by lockdep.
>
> The conversion of the hotplug locking to a percpu rwsem requires to prevent
> nested locking, so it's required to take the hotplug rwsem early in the
> call chain and establish a proper lock order.
>
> After quite some analysis and going down the wrong road severa times the
> following lock order has been chosen:
>
> kprobe_mutex -> cpus_rwsem -> jump_label_mutex -> text_mutex
This seems only change the locking order of module_mutex and
cpus_rwsem. Previously module_mutex -> cpus_rwsem, now
cpus_rwsem -> module_mutex. and it seems OK to me.
(checked in module.c and other use cases of module_mutex)
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Thank you,
>
> For kprobes which hook on an ftrace function trace point, it's required to
> drop cpus_rwsem before calling into the ftrace code to avoid a deadlock on
> the func_hash->regex_lock.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> [ Steven: Ftrace interaction fixes ]
> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Masami Hiramatsu <mhiramat@kernel.org>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>
> ---
>
> Note: The above SOB chain is actually correct as Steven and me bounced the
> patch series back and forth, but the result has to be a single patch.
>
> kernel/kprobes.c | 59 +++++++++++++++++++++++++++++--------------------------
> 1 file changed, 32 insertions(+), 27 deletions(-)
>
> Index: b/kernel/kprobes.c
> ===================================================================
> --- a/kernel/kprobes.c
> +++ b/kernel/kprobes.c
> @@ -483,11 +483,6 @@ static DECLARE_DELAYED_WORK(optimizing_w
> */
> static void do_optimize_kprobes(void)
> {
> - /* Optimization never be done when disarmed */
> - if (kprobes_all_disarmed || !kprobes_allow_optimization ||
> - list_empty(&optimizing_list))
> - return;
> -
> /*
> * The optimization/unoptimization refers online_cpus via
> * stop_machine() and cpu-hotplug modifies online_cpus.
> @@ -495,14 +490,19 @@ static void do_optimize_kprobes(void)
> * This combination can cause a deadlock (cpu-hotplug try to lock
> * text_mutex but stop_machine can not be done because online_cpus
> * has been changed)
> - * To avoid this deadlock, we need to call get_online_cpus()
> + * To avoid this deadlock, caller must have locked cpu hotplug
> * for preventing cpu-hotplug outside of text_mutex locking.
> */
> - get_online_cpus();
> + lockdep_assert_cpus_held();
> +
> + /* Optimization never be done when disarmed */
> + if (kprobes_all_disarmed || !kprobes_allow_optimization ||
> + list_empty(&optimizing_list))
> + return;
> +
> mutex_lock(&text_mutex);
> arch_optimize_kprobes(&optimizing_list);
> mutex_unlock(&text_mutex);
> - put_online_cpus();
> }
>
> /*
> @@ -513,12 +513,13 @@ static void do_unoptimize_kprobes(void)
> {
> struct optimized_kprobe *op, *tmp;
>
> + /* See comment in do_optimize_kprobes() */
> + lockdep_assert_cpus_held();
> +
> /* Unoptimization must be done anytime */
> if (list_empty(&unoptimizing_list))
> return;
>
> - /* Ditto to do_optimize_kprobes */
> - get_online_cpus();
> mutex_lock(&text_mutex);
> arch_unoptimize_kprobes(&unoptimizing_list, &freeing_list);
> /* Loop free_list for disarming */
> @@ -537,7 +538,6 @@ static void do_unoptimize_kprobes(void)
> list_del_init(&op->list);
> }
> mutex_unlock(&text_mutex);
> - put_online_cpus();
> }
>
> /* Reclaim all kprobes on the free_list */
> @@ -562,6 +562,7 @@ static void kick_kprobe_optimizer(void)
> static void kprobe_optimizer(struct work_struct *work)
> {
> mutex_lock(&kprobe_mutex);
> + cpus_read_lock();
> /* Lock modules while optimizing kprobes */
> mutex_lock(&module_mutex);
>
> @@ -587,6 +588,7 @@ static void kprobe_optimizer(struct work
> do_free_cleaned_kprobes();
>
> mutex_unlock(&module_mutex);
> + cpus_read_unlock();
> mutex_unlock(&kprobe_mutex);
>
> /* Step 5: Kick optimizer again if needed */
> @@ -650,9 +652,8 @@ static void optimize_kprobe(struct kprob
> /* Short cut to direct unoptimizing */
> static void force_unoptimize_kprobe(struct optimized_kprobe *op)
> {
> - get_online_cpus();
> + lockdep_assert_cpus_held();
> arch_unoptimize_kprobe(op);
> - put_online_cpus();
> if (kprobe_disabled(&op->kp))
> arch_disarm_kprobe(&op->kp);
> }
> @@ -791,6 +792,7 @@ static void try_to_optimize_kprobe(struc
> return;
>
> /* For preparing optimization, jump_label_text_reserved() is called */
> + cpus_read_lock();
> jump_label_lock();
> mutex_lock(&text_mutex);
>
> @@ -812,6 +814,7 @@ static void try_to_optimize_kprobe(struc
> out:
> mutex_unlock(&text_mutex);
> jump_label_unlock();
> + cpus_read_unlock();
> }
>
> #ifdef CONFIG_SYSCTL
> @@ -826,6 +829,7 @@ static void optimize_all_kprobes(void)
> if (kprobes_allow_optimization)
> goto out;
>
> + cpus_read_lock();
> kprobes_allow_optimization = true;
> for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
> head = &kprobe_table[i];
> @@ -833,6 +837,7 @@ static void optimize_all_kprobes(void)
> if (!kprobe_disabled(p))
> optimize_kprobe(p);
> }
> + cpus_read_unlock();
> printk(KERN_INFO "Kprobes globally optimized\n");
> out:
> mutex_unlock(&kprobe_mutex);
> @@ -851,6 +856,7 @@ static void unoptimize_all_kprobes(void)
> return;
> }
>
> + cpus_read_lock();
> kprobes_allow_optimization = false;
> for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
> head = &kprobe_table[i];
> @@ -859,6 +865,7 @@ static void unoptimize_all_kprobes(void)
> unoptimize_kprobe(p, false);
> }
> }
> + cpus_read_unlock();
> mutex_unlock(&kprobe_mutex);
>
> /* Wait for unoptimizing completion */
> @@ -1010,14 +1017,11 @@ static void arm_kprobe(struct kprobe *kp
> arm_kprobe_ftrace(kp);
> return;
> }
> - /*
> - * Here, since __arm_kprobe() doesn't use stop_machine(),
> - * this doesn't cause deadlock on text_mutex. So, we don't
> - * need get_online_cpus().
> - */
> + cpus_read_lock();
> mutex_lock(&text_mutex);
> __arm_kprobe(kp);
> mutex_unlock(&text_mutex);
> + cpus_read_unlock();
> }
>
> /* Disarm a kprobe with text_mutex */
> @@ -1027,10 +1031,12 @@ static void disarm_kprobe(struct kprobe
> disarm_kprobe_ftrace(kp);
> return;
> }
> - /* Ditto */
> +
> + cpus_read_lock();
> mutex_lock(&text_mutex);
> __disarm_kprobe(kp, reopt);
> mutex_unlock(&text_mutex);
> + cpus_read_unlock();
> }
>
> /*
> @@ -1298,13 +1304,10 @@ static int register_aggr_kprobe(struct k
> int ret = 0;
> struct kprobe *ap = orig_p;
>
> + cpus_read_lock();
> +
> /* For preparing optimization, jump_label_text_reserved() is called */
> jump_label_lock();
> - /*
> - * Get online CPUs to avoid text_mutex deadlock.with stop machine,
> - * which is invoked by unoptimize_kprobe() in add_new_kprobe()
> - */
> - get_online_cpus();
> mutex_lock(&text_mutex);
>
> if (!kprobe_aggrprobe(orig_p)) {
> @@ -1352,8 +1355,8 @@ static int register_aggr_kprobe(struct k
>
> out:
> mutex_unlock(&text_mutex);
> - put_online_cpus();
> jump_label_unlock();
> + cpus_read_unlock();
>
> if (ret == 0 && kprobe_disabled(ap) && !kprobe_disabled(p)) {
> ap->flags &= ~KPROBE_FLAG_DISABLED;
> @@ -1555,9 +1558,12 @@ int register_kprobe(struct kprobe *p)
> goto out;
> }
>
> - mutex_lock(&text_mutex); /* Avoiding text modification */
> + cpus_read_lock();
> + /* Prevent text modification */
> + mutex_lock(&text_mutex);
> ret = prepare_kprobe(p);
> mutex_unlock(&text_mutex);
> + cpus_read_unlock();
> if (ret)
> goto out;
>
> @@ -1570,7 +1576,6 @@ int register_kprobe(struct kprobe *p)
>
> /* Try to optimize kprobe */
> try_to_optimize_kprobe(p);
> -
> out:
> mutex_unlock(&kprobe_mutex);
>
>
>
--
Masami Hiramatsu <mhiramat@kernel.org>
next prev parent reply other threads:[~2017-05-24 15:54 UTC|newest]
Thread overview: 82+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-24 8:15 [patch V3 00/32] cpu/hotplug: Convert get_online_cpus() to a percpu_rwsem Thomas Gleixner
2017-05-24 8:15 ` [patch V3 01/32] cpu/hotplug: Provide cpus_read|write_[un]lock() Thomas Gleixner
2017-05-24 16:25 ` Paul E. McKenney
2017-05-26 8:31 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 02/32] cpu/hotplug: Provide lockdep_assert_cpus_held() Thomas Gleixner
2017-05-24 16:26 ` Paul E. McKenney
2017-05-26 8:32 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 03/32] cpu/hotplug: Provide cpuhp_setup/remove_state[_nocalls]_cpuslocked() Thomas Gleixner
2017-05-26 8:32 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 04/32] cpu/hotplug: Add __cpuhp_state_add_instance_cpuslocked() Thomas Gleixner
2017-05-26 8:33 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 05/32] stop_machine: Provide stop_machine_cpuslocked() Thomas Gleixner
2017-05-24 17:42 ` Paul E. McKenney
2017-05-26 8:33 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 06/32] padata: Make padata_alloc() static Thomas Gleixner
2017-05-26 8:34 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 07/32] padata: Avoid nested calls to cpus_read_lock() in pcrypt_init_padata() Thomas Gleixner
2017-05-26 8:35 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 08/32] x86/mtrr: Remove get_online_cpus() from mtrr_save_state() Thomas Gleixner
2017-05-26 8:35 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 09/32] cpufreq: Use cpuhp_setup_state_nocalls_cpuslocked() Thomas Gleixner
2017-05-26 8:36 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 10/32] KVM/PPC/Book3S HV: " Thomas Gleixner
2017-05-26 8:36 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 11/32] hwtracing/coresight-etm3x: " Thomas Gleixner
2017-05-25 16:46 ` Mathieu Poirier
2017-05-26 8:37 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 12/32] hwtracing/coresight-etm4x: " Thomas Gleixner
2017-05-25 16:47 ` Mathieu Poirier
2017-05-26 8:37 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 13/32] perf/x86/intel/cqm: Use cpuhp_setup_state_cpuslocked() Thomas Gleixner
2017-05-26 8:38 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 14/32] ARM/hw_breakpoint: " Thomas Gleixner
2017-05-26 8:38 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 15/32] s390/kernel: Use stop_machine_cpuslocked() Thomas Gleixner
2017-05-24 10:57 ` Heiko Carstens
2017-05-26 8:39 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 16/32] powerpc/powernv: " Thomas Gleixner
2017-05-26 8:40 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 17/32] cpu/hotplug: Use stop_machine_cpuslocked() in takedown_cpu() Thomas Gleixner
2017-05-26 8:40 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 18/32] x86/perf: Drop EXPORT of perf_check_microcode Thomas Gleixner
2017-05-26 8:41 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 19/32] perf/x86/intel: Drop get_online_cpus() in intel_snb_check_microcode() Thomas Gleixner
2017-05-26 8:41 ` [tip:smp/hotplug] " tip-bot for Sebastian Andrzej Siewior
2017-05-24 8:15 ` [patch V3 20/32] PCI: Use cpu_hotplug_disable() instead of get_online_cpus() Thomas Gleixner
2017-05-26 8:42 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 21/32] PCI: Replace the racy recursion prevention Thomas Gleixner
2017-05-26 8:42 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 22/32] ACPI/processor: Use cpu_hotplug_disable() instead of get_online_cpus() Thomas Gleixner
2017-05-26 8:43 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 23/32] perf/tracing/cpuhotplug: Fix locking order Thomas Gleixner
2017-05-24 18:30 ` Paul E. McKenney
2017-05-24 18:47 ` Thomas Gleixner
2017-05-24 21:10 ` Paul E. McKenney
2017-05-30 11:22 ` Peter Zijlstra
2017-05-30 16:25 ` Paul E. McKenney
2017-05-26 8:43 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 24/32] jump_label: Reorder hotplug lock and jump_label_lock Thomas Gleixner
2017-05-24 12:50 ` David Miller
2017-05-26 8:44 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 25/32] kprobes: Cure hotplug lock ordering issues Thomas Gleixner
2017-05-24 15:54 ` Masami Hiramatsu [this message]
2017-05-26 7:47 ` Thomas Gleixner
2017-05-26 8:45 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 26/32] arm64: Prevent cpu hotplug rwsem recursion Thomas Gleixner
2017-05-26 8:45 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 27/32] arm: Prevent " Thomas Gleixner
2017-05-26 8:46 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 28/32] s390: " Thomas Gleixner
2017-05-24 10:57 ` Heiko Carstens
2017-05-26 8:46 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 29/32] cpu/hotplug: Convert hotplug locking to percpu rwsem Thomas Gleixner
2017-05-26 8:47 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 30/32] sched: Provide is_percpu_thread() helper Thomas Gleixner
2017-05-26 8:47 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 31/32] acpi/processor: Prevent cpu hotplug deadlock Thomas Gleixner
2017-05-26 8:48 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 8:15 ` [patch V3 32/32] cpuhotplug: Link lock stacks for hotplug callbacks Thomas Gleixner
2017-05-26 8:48 ` [tip:smp/hotplug] " tip-bot for Thomas Gleixner
2017-05-24 16:22 ` [patch V3 00/32] cpu/hotplug: Convert get_online_cpus() to a percpu_rwsem Paul E. McKenney
2017-05-26 7:03 ` Ingo Molnar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170525005410.f7142f05cd5d248600c61f96@kernel.org \
--to=mhiramat@kernel.org \
--cc=bigeasy@linutronix.de \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=paulmck@linux.vnet.ibm.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome