* [PATCH -tip V4 0/4] kprobes: Fixes and cleanups
@ 2020-02-26 8:59 Masami Hiramatsu
2020-02-26 8:59 ` [PATCH -tip V4 1/4] kprobes: Suppress the suspicious RCU warning on kprobes Masami Hiramatsu
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Masami Hiramatsu @ 2020-02-26 8:59 UTC (permalink / raw)
To: Ingo Molnar
Cc: Anders Roxell, paulmck, joel, Naveen N . Rao,
Anil S Keshavamurthy, David Miller, Masami Hiramatsu,
Linux Kernel Mailing List, Steven Rostedt
Hi Ingo,
Here is a collection of fixes and cleanups for kprobes, which have
been submitted previously.
Basically, those were not changed but ported on the top of the
latest -tip tree. Just to distinguish it from previous posts,
I tagged v4 (v3 was last post [1]) on this series. In this v4,
I added 2 fixes which were posted with another RFT series [2].
[1] https://lkml.org/lkml/2020/1/14/1460
[2] https://lkml.org/lkml/2020/1/16/571
Thank you,
---
Masami Hiramatsu (4):
kprobes: Suppress the suspicious RCU warning on kprobes
kprobes: Use non RCU traversal APIs on kprobe_tables if possible
kprobes: Fix to protect kick_kprobe_optimizer() by kprobe_mutex
kprobes: Remove redundant arch_disarm_kprobe() call
kernel/kprobes.c | 37 ++++++++++++++++++++++++-------------
1 file changed, 24 insertions(+), 13 deletions(-)
--
Masami Hiramatsu (Linaro) <mhiramat@kernel.org>
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH -tip V4 1/4] kprobes: Suppress the suspicious RCU warning on kprobes 2020-02-26 8:59 [PATCH -tip V4 0/4] kprobes: Fixes and cleanups Masami Hiramatsu @ 2020-02-26 8:59 ` Masami Hiramatsu 2020-02-26 8:59 ` [PATCH -tip V4 2/4] kprobes: Use non RCU traversal APIs on kprobe_tables if possible Masami Hiramatsu ` (2 subsequent siblings) 3 siblings, 0 replies; 7+ messages in thread From: Masami Hiramatsu @ 2020-02-26 8:59 UTC (permalink / raw) To: Ingo Molnar Cc: Anders Roxell, paulmck, joel, Naveen N . Rao, Anil S Keshavamurthy, David Miller, Masami Hiramatsu, Linux Kernel Mailing List, Steven Rostedt Anders reported that the lockdep warns that suspicious RCU list usage in register_kprobe() (detected by CONFIG_PROVE_RCU_LIST.) This is because get_kprobe() access kprobe_table[] by hlist_for_each_entry_rcu() without rcu_read_lock. If we call get_kprobe() from the breakpoint handler context, it is run with preempt disabled, so this is not a problem. But in other cases, instead of rcu_read_lock(), we locks kprobe_mutex so that the kprobe_table[] is not updated. So, current code is safe, but still not good from the view point of RCU. Joel suggested that we can silent that warning by passing lockdep_is_held() to the last argument of hlist_for_each_entry_rcu(). Add lockdep_is_held(&kprobe_mutex) at the end of the hlist_for_each_entry_rcu() to suppress the warning. Reported-by: Anders Roxell <anders.roxell@linaro.org> Suggested-by: Joel Fernandes <joel@joelfernandes.org> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org> --- kernel/kprobes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 2625c241ac00..bd484392d789 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -326,7 +326,8 @@ struct kprobe *get_kprobe(void *addr) struct kprobe *p; head = &kprobe_table[hash_ptr(addr, KPROBE_HASH_BITS)]; - hlist_for_each_entry_rcu(p, head, hlist) { + hlist_for_each_entry_rcu(p, head, hlist, + lockdep_is_held(&kprobe_mutex)) { if (p->addr == addr) return p; } ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH -tip V4 2/4] kprobes: Use non RCU traversal APIs on kprobe_tables if possible 2020-02-26 8:59 [PATCH -tip V4 0/4] kprobes: Fixes and cleanups Masami Hiramatsu 2020-02-26 8:59 ` [PATCH -tip V4 1/4] kprobes: Suppress the suspicious RCU warning on kprobes Masami Hiramatsu @ 2020-02-26 8:59 ` Masami Hiramatsu 2020-02-26 8:59 ` [PATCH -tip V4 3/4] kprobes: Fix to protect kick_kprobe_optimizer() by kprobe_mutex Masami Hiramatsu 2020-02-26 9:00 ` [PATCH -tip V4 4/4] kprobes: Remove redundant arch_disarm_kprobe() call Masami Hiramatsu 3 siblings, 0 replies; 7+ messages in thread From: Masami Hiramatsu @ 2020-02-26 8:59 UTC (permalink / raw) To: Ingo Molnar Cc: Anders Roxell, paulmck, joel, Naveen N . Rao, Anil S Keshavamurthy, David Miller, Masami Hiramatsu, Linux Kernel Mailing List, Steven Rostedt Current kprobes uses RCU traversal APIs on kprobe_tables even if it is safe because kprobe_mutex is locked. Make those traversals to non-RCU APIs where the kprobe_mutex is locked. Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org> --- kernel/kprobes.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index bd484392d789..38d9a5d7c8a4 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -46,6 +46,11 @@ static int kprobes_initialized; +/* kprobe_table can be accessed by + * - Normal hlist traversal and RCU add/del under kprobe_mutex is held. + * Or + * - RCU hlist traversal under disabling preempt (breakpoint handlers) + */ static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; @@ -850,7 +855,7 @@ static void optimize_all_kprobes(void) kprobes_allow_optimization = true; for (i = 0; i < KPROBE_TABLE_SIZE; i++) { head = &kprobe_table[i]; - hlist_for_each_entry_rcu(p, head, hlist) + hlist_for_each_entry(p, head, hlist) if (!kprobe_disabled(p)) optimize_kprobe(p); } @@ -877,7 +882,7 @@ static void unoptimize_all_kprobes(void) kprobes_allow_optimization = false; for (i = 0; i < KPROBE_TABLE_SIZE; i++) { head = &kprobe_table[i]; - hlist_for_each_entry_rcu(p, head, hlist) { + hlist_for_each_entry(p, head, hlist) { if (!kprobe_disabled(p)) unoptimize_kprobe(p, false); } @@ -1500,12 +1505,14 @@ static struct kprobe *__get_valid_kprobe(struct kprobe *p) { struct kprobe *ap, *list_p; + lockdep_assert_held(&kprobe_mutex); + ap = get_kprobe(p->addr); if (unlikely(!ap)) return NULL; if (p != ap) { - list_for_each_entry_rcu(list_p, &ap->list, list) + list_for_each_entry(list_p, &ap->list, list) if (list_p == p) /* kprobe p is a valid probe */ goto valid; @@ -1670,7 +1677,9 @@ static int aggr_kprobe_disabled(struct kprobe *ap) { struct kprobe *kp; - list_for_each_entry_rcu(kp, &ap->list, list) + lockdep_assert_held(&kprobe_mutex); + + list_for_each_entry(kp, &ap->list, list) if (!kprobe_disabled(kp)) /* * There is an active probe on the list. @@ -1749,7 +1758,7 @@ static int __unregister_kprobe_top(struct kprobe *p) else { /* If disabling probe has special handlers, update aggrprobe */ if (p->post_handler && !kprobe_gone(p)) { - list_for_each_entry_rcu(list_p, &ap->list, list) { + list_for_each_entry(list_p, &ap->list, list) { if ((list_p != p) && (list_p->post_handler)) goto noclean; } @@ -2063,13 +2072,15 @@ static void kill_kprobe(struct kprobe *p) { struct kprobe *kp; + lockdep_assert_held(&kprobe_mutex); + p->flags |= KPROBE_FLAG_GONE; if (kprobe_aggrprobe(p)) { /* * If this is an aggr_kprobe, we have to list all the * chained probes and mark them GONE. */ - list_for_each_entry_rcu(kp, &p->list, list) + list_for_each_entry(kp, &p->list, list) kp->flags |= KPROBE_FLAG_GONE; p->post_handler = NULL; kill_optimized_kprobe(p); @@ -2238,7 +2249,7 @@ static int kprobes_module_callback(struct notifier_block *nb, mutex_lock(&kprobe_mutex); for (i = 0; i < KPROBE_TABLE_SIZE; i++) { head = &kprobe_table[i]; - hlist_for_each_entry_rcu(p, head, hlist) + hlist_for_each_entry(p, head, hlist) if (within_module_init((unsigned long)p->addr, mod) || (checkcore && within_module_core((unsigned long)p->addr, mod))) { @@ -2489,7 +2500,7 @@ static int arm_all_kprobes(void) for (i = 0; i < KPROBE_TABLE_SIZE; i++) { head = &kprobe_table[i]; /* Arm all kprobes on a best-effort basis */ - hlist_for_each_entry_rcu(p, head, hlist) { + hlist_for_each_entry(p, head, hlist) { if (!kprobe_disabled(p)) { err = arm_kprobe(p); if (err) { @@ -2532,7 +2543,7 @@ static int disarm_all_kprobes(void) for (i = 0; i < KPROBE_TABLE_SIZE; i++) { head = &kprobe_table[i]; /* Disarm all kprobes on a best-effort basis */ - hlist_for_each_entry_rcu(p, head, hlist) { + hlist_for_each_entry(p, head, hlist) { if (!arch_trampoline_kprobe(p) && !kprobe_disabled(p)) { err = disarm_kprobe(p, false); if (err) { ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH -tip V4 3/4] kprobes: Fix to protect kick_kprobe_optimizer() by kprobe_mutex 2020-02-26 8:59 [PATCH -tip V4 0/4] kprobes: Fixes and cleanups Masami Hiramatsu 2020-02-26 8:59 ` [PATCH -tip V4 1/4] kprobes: Suppress the suspicious RCU warning on kprobes Masami Hiramatsu 2020-02-26 8:59 ` [PATCH -tip V4 2/4] kprobes: Use non RCU traversal APIs on kprobe_tables if possible Masami Hiramatsu @ 2020-02-26 8:59 ` Masami Hiramatsu 2020-03-03 23:52 ` Steven Rostedt 2020-02-26 9:00 ` [PATCH -tip V4 4/4] kprobes: Remove redundant arch_disarm_kprobe() call Masami Hiramatsu 3 siblings, 1 reply; 7+ messages in thread From: Masami Hiramatsu @ 2020-02-26 8:59 UTC (permalink / raw) To: Ingo Molnar Cc: Anders Roxell, paulmck, joel, Naveen N . Rao, Anil S Keshavamurthy, David Miller, Masami Hiramatsu, Linux Kernel Mailing List, Steven Rostedt In kprobe_optimizer() kick_kprobe_optimizer() is called without kprobe_mutex, but this can race with other caller which is protected by kprobe_mutex. To fix that, expand kprobe_mutex protected area to protect kick_kprobe_optimizer() call. Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> --- kernel/kprobes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 38d9a5d7c8a4..6d76a6e3e1a5 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -592,11 +592,12 @@ static void kprobe_optimizer(struct work_struct *work) mutex_unlock(&module_mutex); mutex_unlock(&text_mutex); cpus_read_unlock(); - mutex_unlock(&kprobe_mutex); /* Step 5: Kick optimizer again if needed */ if (!list_empty(&optimizing_list) || !list_empty(&unoptimizing_list)) kick_kprobe_optimizer(); + + mutex_unlock(&kprobe_mutex); } /* Wait for completing optimization and unoptimization */ ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH -tip V4 3/4] kprobes: Fix to protect kick_kprobe_optimizer() by kprobe_mutex 2020-02-26 8:59 ` [PATCH -tip V4 3/4] kprobes: Fix to protect kick_kprobe_optimizer() by kprobe_mutex Masami Hiramatsu @ 2020-03-03 23:52 ` Steven Rostedt 2020-03-04 7:18 ` Masami Hiramatsu 0 siblings, 1 reply; 7+ messages in thread From: Steven Rostedt @ 2020-03-03 23:52 UTC (permalink / raw) To: Masami Hiramatsu Cc: Ingo Molnar, Anders Roxell, paulmck, joel, Naveen N . Rao, Anil S Keshavamurthy, David Miller, Linux Kernel Mailing List On Wed, 26 Feb 2020 17:59:51 +0900 Masami Hiramatsu <mhiramat@kernel.org> wrote: > In kprobe_optimizer() kick_kprobe_optimizer() is called > without kprobe_mutex, but this can race with other caller > which is protected by kprobe_mutex. > > To fix that, expand kprobe_mutex protected area to protect > kick_kprobe_optimizer() call. > Should we add Cc: stable@vger.kernel.org Fixes: cd7ebe2298ff ("kprobes: Use text_poke_smp_batch for optimizing") tags? -- Steve > Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> > --- > kernel/kprobes.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/kernel/kprobes.c b/kernel/kprobes.c > index 38d9a5d7c8a4..6d76a6e3e1a5 100644 > --- a/kernel/kprobes.c > +++ b/kernel/kprobes.c > @@ -592,11 +592,12 @@ static void kprobe_optimizer(struct work_struct *work) > mutex_unlock(&module_mutex); > mutex_unlock(&text_mutex); > cpus_read_unlock(); > - mutex_unlock(&kprobe_mutex); > > /* Step 5: Kick optimizer again if needed */ > if (!list_empty(&optimizing_list) || !list_empty(&unoptimizing_list)) > kick_kprobe_optimizer(); > + > + mutex_unlock(&kprobe_mutex); > } > > /* Wait for completing optimization and unoptimization */ ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH -tip V4 3/4] kprobes: Fix to protect kick_kprobe_optimizer() by kprobe_mutex 2020-03-03 23:52 ` Steven Rostedt @ 2020-03-04 7:18 ` Masami Hiramatsu 0 siblings, 0 replies; 7+ messages in thread From: Masami Hiramatsu @ 2020-03-04 7:18 UTC (permalink / raw) To: Steven Rostedt Cc: Ingo Molnar, Anders Roxell, paulmck, joel, Naveen N . Rao, Anil S Keshavamurthy, David Miller, Linux Kernel Mailing List On Tue, 3 Mar 2020 18:52:36 -0500 Steven Rostedt <rostedt@goodmis.org> wrote: > On Wed, 26 Feb 2020 17:59:51 +0900 > Masami Hiramatsu <mhiramat@kernel.org> wrote: > > > In kprobe_optimizer() kick_kprobe_optimizer() is called > > without kprobe_mutex, but this can race with other caller > > which is protected by kprobe_mutex. > > > > To fix that, expand kprobe_mutex protected area to protect > > kick_kprobe_optimizer() call. > > > > Should we add > > Cc: stable@vger.kernel.org > Fixes: cd7ebe2298ff ("kprobes: Use text_poke_smp_batch for optimizing") > > tags? Good catch! Yes, it is correct commit to be fixed. Thank you! > > -- Steve > > > Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> > > --- > > kernel/kprobes.c | 3 ++- > > 1 file changed, 2 insertions(+), 1 deletion(-) > > > > diff --git a/kernel/kprobes.c b/kernel/kprobes.c > > index 38d9a5d7c8a4..6d76a6e3e1a5 100644 > > --- a/kernel/kprobes.c > > +++ b/kernel/kprobes.c > > @@ -592,11 +592,12 @@ static void kprobe_optimizer(struct work_struct *work) > > mutex_unlock(&module_mutex); > > mutex_unlock(&text_mutex); > > cpus_read_unlock(); > > - mutex_unlock(&kprobe_mutex); > > > > /* Step 5: Kick optimizer again if needed */ > > if (!list_empty(&optimizing_list) || !list_empty(&unoptimizing_list)) > > kick_kprobe_optimizer(); > > + > > + mutex_unlock(&kprobe_mutex); > > } > > > > /* Wait for completing optimization and unoptimization */ > -- Masami Hiramatsu <mhiramat@kernel.org> ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH -tip V4 4/4] kprobes: Remove redundant arch_disarm_kprobe() call 2020-02-26 8:59 [PATCH -tip V4 0/4] kprobes: Fixes and cleanups Masami Hiramatsu ` (2 preceding siblings ...) 2020-02-26 8:59 ` [PATCH -tip V4 3/4] kprobes: Fix to protect kick_kprobe_optimizer() by kprobe_mutex Masami Hiramatsu @ 2020-02-26 9:00 ` Masami Hiramatsu 3 siblings, 0 replies; 7+ messages in thread From: Masami Hiramatsu @ 2020-02-26 9:00 UTC (permalink / raw) To: Ingo Molnar Cc: Anders Roxell, paulmck, joel, Naveen N . Rao, Anil S Keshavamurthy, David Miller, Masami Hiramatsu, Linux Kernel Mailing List, Steven Rostedt Fix to remove redundant arch_disarm_kprobe() call in force_unoptimize_kprobe(). This arch_disarm_kprobe() will be invoked if the kprobe is optimized but disabled, but that means the kprobe (optprobe) is unused (and unoptimized) state. In that case, unoptimize_kprobe() puts it in freeing_list and kprobe_optimizer (do_unoptimize_kprobes()) automatically disarm it. Thus this arch_disarm_kprobe() is redundant. Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> --- kernel/kprobes.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 6d76a6e3e1a5..627fc1b7011a 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -675,8 +675,6 @@ static void force_unoptimize_kprobe(struct optimized_kprobe *op) lockdep_assert_cpus_held(); arch_unoptimize_kprobe(op); op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED; - if (kprobe_disabled(&op->kp)) - arch_disarm_kprobe(&op->kp); } /* Unoptimize a kprobe if p is optimized */ ^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-03-04 7:18 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-02-26 8:59 [PATCH -tip V4 0/4] kprobes: Fixes and cleanups Masami Hiramatsu 2020-02-26 8:59 ` [PATCH -tip V4 1/4] kprobes: Suppress the suspicious RCU warning on kprobes Masami Hiramatsu 2020-02-26 8:59 ` [PATCH -tip V4 2/4] kprobes: Use non RCU traversal APIs on kprobe_tables if possible Masami Hiramatsu 2020-02-26 8:59 ` [PATCH -tip V4 3/4] kprobes: Fix to protect kick_kprobe_optimizer() by kprobe_mutex Masami Hiramatsu 2020-03-03 23:52 ` Steven Rostedt 2020-03-04 7:18 ` Masami Hiramatsu 2020-02-26 9:00 ` [PATCH -tip V4 4/4] kprobes: Remove redundant arch_disarm_kprobe() call Masami Hiramatsu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox