Hi,
Here is a series of kprobes blacklist bugfix and improvements mainly on x86 (since I started testing on qemu-x86).
This has been started from discussion about KPROBE_ENENTS_ON_NOTRACE configuration. I tried to find notrace functions which can cause kernel crash with kprobes using following script.
==== #!/bin/sh
i=0; cat notrace_functions | while read f ; do if echo p:event$i $f >> /sys/kernel/debug/tracing/kprobe_events; then echo "Probing on $f" echo 1 > /sys/kernel/debug/tracing/events/kprobes/event$i/enable fi i=$((i+1)) done ====
And I found several functions which must be blacklisted. - optprobe template code, which is just a template code and never be executed. Moreover, since it can be copied and reused, if we probe it, it modifies the template code and can cause a crash. ([1/9][2/9]) - functions which is called before kprobe_int3_handler() handles kprobes. This can cause a breakpoint recursion. ([3/9]) - IRQ entry text, which should not be probed since register/pagetable status has not been stable at that point. ([4/9]) - Suffixed symbols, like .constprop, .part etc. Those suffixed symbols never be blacklisted even if the non-suffixed version has been blacklisted. ([5/9]) - hardirq tracer also works before int3 handling. ([6/9]) - preempt_check debug function also is involved in int3 handling. ([7/9]) - RCU debug routine is also called before kprobe_int3_handler(). ([8/9]) - Some lockdep functions are also involved in int3 handling. ([9/9])
Of course there still may be some functions which can be called by configuration change, I'll continue to test it.
Thank you,
---
Masami Hiramatsu (9): x86/kprobes: Prohibit probing on optprobe template code x86/kprobes: Move trampoline code into RODATA x86/kprobes: Prohibit probing on functions before kprobe_int3_handler() x86/kprobes: Prohibit probing on IRQ handlers directly kprobes: Search non-suffixed symbol in blacklist kprobes: Prohibit probing on hardirq tracers kprobes: Prohibit probing on preempt_check debug functions kprobes: Prohibit probing on RCU debug routine kprobes: Prohibit probing on lockdep functions
arch/x86/kernel/alternative.c | 3 ++- arch/x86/kernel/ftrace.c | 3 ++- arch/x86/kernel/kprobes/core.c | 7 +++++++ arch/x86/kernel/kprobes/opt.c | 4 ++-- arch/x86/kernel/traps.c | 1 + kernel/kprobes.c | 21 ++++++++++++++++++++- kernel/locking/lockdep.c | 7 ++++++- kernel/rcu/tree.c | 2 ++ kernel/rcu/update.c | 2 ++ kernel/trace/trace_irqsoff.c | 9 +++++++-- kernel/trace/trace_preemptirq.c | 5 +++++ lib/smp_processor_id.c | 7 +++++-- 12 files changed, 61 insertions(+), 10 deletions(-)
Prohibit probing on optprobe template code, since it is not a code but a template instruction sequence. If we modify this template, copied template must be broken.
Signed-off-by: Masami Hiramatsu mhiramat@kernel.org Fixes: 9326638cbee2 ("kprobes, x86: Use NOKPROBE_SYMBOL() instead of __kprobes annotation") --- arch/x86/kernel/kprobes/opt.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 6adf6e6c2933..544bd41a514c 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c @@ -141,6 +141,11 @@ asm (
void optprobe_template_func(void); STACK_FRAME_NON_STANDARD(optprobe_template_func); +NOKPROBE_SYMBOL(optprobe_template_func); +NOKPROBE_SYMBOL(optprobe_template_entry); +NOKPROBE_SYMBOL(optprobe_template_val); +NOKPROBE_SYMBOL(optprobe_template_call); +NOKPROBE_SYMBOL(optprobe_template_end);
#define TMPL_MOVE_IDX \ ((long)optprobe_template_val - (long)optprobe_template_entry)
On Thu, Jan 10, 2019 at 11:54:30AM +0900, Masami Hiramatsu wrote:
Prohibit probing on optprobe template code, since it is not a code but a template instruction sequence. If we modify this template, copied template must be broken.
Signed-off-by: Masami Hiramatsu mhiramat@kernel.org Fixes: 9326638cbee2 ("kprobes, x86: Use NOKPROBE_SYMBOL() instead of __kprobes annotation")
arch/x86/kernel/kprobes/opt.c | 5 +++++ 1 file changed, 5 insertions(+)
<formletter>
This is not the correct way to submit patches for inclusion in the stable kernel tree. Please read: https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html for how to do this properly.
</formletter>
Same for all patches in this series...
On Thu, 10 Jan 2019 07:07:20 +0100 Greg KH gregkh@linuxfoundation.org wrote:
On Thu, Jan 10, 2019 at 11:54:30AM +0900, Masami Hiramatsu wrote:
Prohibit probing on optprobe template code, since it is not a code but a template instruction sequence. If we modify this template, copied template must be broken.
Signed-off-by: Masami Hiramatsu mhiramat@kernel.org Fixes: 9326638cbee2 ("kprobes, x86: Use NOKPROBE_SYMBOL() instead of __kprobes annotation")
arch/x86/kernel/kprobes/opt.c | 5 +++++ 1 file changed, 5 insertions(+)
<formletter>
This is not the correct way to submit patches for inclusion in the stable kernel tree. Please read: https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html for how to do this properly.
</formletter>
Same for all patches in this series...
Oops, sorry. I'll fix the format again. BTW, I'm still considering I should make it other patches in this series as improvement instead of fix, since those are just adding blacklist, and usually user can avoid it with KPROBE_EVENTS_ON_NOTRACE=n (which is default).
Thank you,
On Thu, 10 Jan 2019 23:57:10 +0900 Masami Hiramatsu mhiramat@kernel.org wrote:
Same for all patches in this series...
Oops, sorry. I'll fix the format again. BTW, I'm still considering I should make it other patches in this series as improvement instead of fix, since those are just adding blacklist, and usually user can avoid it with KPROBE_EVENTS_ON_NOTRACE=n (which is default).
The issue is that the other patches Cc stable, which they should not unless they are to go to stable.
-- Steve
On Thu, 10 Jan 2019 12:10:34 -0500 Steven Rostedt rostedt@goodmis.org wrote:
On Thu, 10 Jan 2019 23:57:10 +0900 Masami Hiramatsu mhiramat@kernel.org wrote:
Same for all patches in this series...
Oops, sorry. I'll fix the format again. BTW, I'm still considering I should make it other patches in this series as improvement instead of fix, since those are just adding blacklist, and usually user can avoid it with KPROBE_EVENTS_ON_NOTRACE=n (which is default).
The issue is that the other patches Cc stable, which they should not unless they are to go to stable.
Yes, I miss-Cc'd to stable the whole series.
Thank you,
Move optprobe trampoline code into RODATA since it is not executed, but copied and modified to be used on a trampoline buffer.
Signed-off-by: Masami Hiramatsu mhiramat@kernel.org --- arch/x86/kernel/kprobes/opt.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 544bd41a514c..f14262952015 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c @@ -97,6 +97,7 @@ static void synthesize_set_arg1(kprobe_opcode_t *addr, unsigned long val) }
asm ( + ".pushsection .rodata\n" "optprobe_template_func:\n" ".global optprobe_template_entry\n" "optprobe_template_entry:\n" @@ -136,16 +137,10 @@ asm ( #endif ".global optprobe_template_end\n" "optprobe_template_end:\n" - ".type optprobe_template_func, @function\n" - ".size optprobe_template_func, .-optprobe_template_func\n"); + ".popsection\n");
void optprobe_template_func(void); STACK_FRAME_NON_STANDARD(optprobe_template_func); -NOKPROBE_SYMBOL(optprobe_template_func); -NOKPROBE_SYMBOL(optprobe_template_entry); -NOKPROBE_SYMBOL(optprobe_template_val); -NOKPROBE_SYMBOL(optprobe_template_call); -NOKPROBE_SYMBOL(optprobe_template_end);
#define TMPL_MOVE_IDX \ ((long)optprobe_template_val - (long)optprobe_template_entry)
Prohibit probing on the functions called before kprobe_int3_handler() in do_int3(). More specifically, ftrace_int3_handler(), poke_int3_handler(), and ist_enter(). And since rcu_nmi_enter() is called by ist_enter(), it also should be marked as NOKPROBE_SYMBOL.
Since those are handled before kprobe_int3_handler(), probing those functions can cause a breakpoint recursion and crash the kernel.
Signed-off-by: Masami Hiramatsu mhiramat@kernel.org --- arch/x86/kernel/alternative.c | 3 ++- arch/x86/kernel/ftrace.c | 3 ++- arch/x86/kernel/traps.c | 1 + kernel/rcu/tree.c | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index ebeac487a20c..e8b628b1b279 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -11,6 +11,7 @@ #include <linux/stop_machine.h> #include <linux/slab.h> #include <linux/kdebug.h> +#include <linux/kprobes.h> #include <asm/text-patching.h> #include <asm/alternative.h> #include <asm/sections.h> @@ -764,8 +765,8 @@ int poke_int3_handler(struct pt_regs *regs) regs->ip = (unsigned long) bp_int3_handler;
return 1; - } +NOKPROBE_SYMBOL(poke_int3_handler);
/** * text_poke_bp() -- update instructions on live kernel on SMP diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 7ee8067cbf45..22a548919228 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -269,7 +269,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func) return ret; }
-static int is_ftrace_caller(unsigned long ip) +static nokprobe_inline int is_ftrace_caller(unsigned long ip) { if (ip == ftrace_update_func) return 1; @@ -299,6 +299,7 @@ int ftrace_int3_handler(struct pt_regs *regs)
return 1; } +NOKPROBE_SYMBOL(ftrace_int3_handler);
static int ftrace_write(unsigned long ip, const char *val, int size) { diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 9b7c4ca8f0a7..e289ce1332ab 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -111,6 +111,7 @@ void ist_enter(struct pt_regs *regs) /* This code is a bit fragile. Test it. */ RCU_LOCKDEP_WARN(!rcu_is_watching(), "ist_enter didn't work"); } +NOKPROBE_SYMBOL(ist_enter);
void ist_exit(struct pt_regs *regs) { diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 9180158756d2..74db52a0a466 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -62,6 +62,7 @@ #include <linux/suspend.h> #include <linux/ftrace.h> #include <linux/tick.h> +#include <linux/kprobes.h>
#include "tree.h" #include "rcu.h" @@ -872,6 +873,7 @@ void rcu_nmi_enter(void) { rcu_nmi_enter_common(false); } +NOKPROBE_SYMBOL(rcu_nmi_enter);
/** * rcu_irq_enter - inform RCU that current CPU is entering irq away from idle
Prohibit probing on IRQ handlers in irqentry_text because if it interrupts user mode, at that point we haven't changed to kernel space yet and which eventually leads a double fault. E.g.
# echo p apic_timer_interrupt > kprobe_events # echo 1 > events/kprobes/enable PANIC: double fault, error_code: 0x0 CPU: 1 PID: 814 Comm: less Not tainted 4.20.0-rc3+ #30 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) RIP: 0010:error_entry+0x12/0xf0 [snip] Call Trace: <ENTRY_TRAMPOLINE> ? native_iret+0x7/0x7 ? async_page_fault+0x8/0x30 ? trace_hardirqs_on_thunk+0x1c/0x1c ? error_entry+0x7c/0xf0 ? async_page_fault+0x8/0x30 ? native_iret+0x7/0x7 ? int3+0xa/0x20 ? trace_hardirqs_on_thunk+0x1c/0x1c ? error_entry+0x7c/0xf0 ? int3+0xa/0x20 ? apic_timer_interrupt+0x1/0x20 </ENTRY_TRAMPOLINE> Kernel panic - not syncing: Machine halted. Kernel Offset: disabled ---[ end Kernel panic - not syncing: Machine halted. ]---
Signed-off-by: Masami Hiramatsu mhiramat@kernel.org --- arch/x86/kernel/kprobes/core.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index f4b954ff5b89..fed46ddb1eef 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -1072,6 +1072,13 @@ NOKPROBE_SYMBOL(kprobe_fault_handler);
int __init arch_populate_kprobe_blacklist(void) { + int ret; + + ret = kprobe_add_area_blacklist((unsigned long)__irqentry_text_start, + (unsigned long)__irqentry_text_end); + if (ret) + return ret; + return kprobe_add_area_blacklist((unsigned long)__entry_text_start, (unsigned long)__entry_text_end); }
Newer gcc can generate some different instances of a function with suffixed symbols if the function is optimized and only has a part of that. (e.g. .constprop, .part etc.)
In this case, it is not enough to check the entry of kprobe blacklist because it only records non-suffixed symbol address.
To fix this issue, search non-suffixed symbol in blacklist if given address is within a symbol which has a suffix.
Note that this can cause false positive cases if a kprobe-safe function is optimized to suffixed instance and has same name symbol which is blacklisted. But I would like to chose a fail-safe design for this issue.
Signed-off-by: Masami Hiramatsu mhiramat@kernel.org --- kernel/kprobes.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index e8c76164f541..faa519f07aad 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1396,7 +1396,7 @@ bool __weak arch_within_kprobe_blacklist(unsigned long addr) addr < (unsigned long)__kprobes_text_end; }
-bool within_kprobe_blacklist(unsigned long addr) +static bool __within_kprobe_blacklist(unsigned long addr) { struct kprobe_blacklist_entry *ent;
@@ -1410,7 +1410,26 @@ bool within_kprobe_blacklist(unsigned long addr) if (addr >= ent->start_addr && addr < ent->end_addr) return true; } + return false; +}
+bool within_kprobe_blacklist(unsigned long addr) +{ + char symname[KSYM_NAME_LEN], *p; + + if (__within_kprobe_blacklist(addr)) + return true; + + /* Check if the address is on a suffixed-symbol */ + if (!lookup_symbol_name(addr, symname)) { + p = strchr(symname, '.'); + if (!p) + return false; + *p = '\0'; + addr = (unsigned long)kprobe_lookup_name(symname, 0); + if (addr) + return __within_kprobe_blacklist(addr); + } return false; }
Since kprobes breakpoint handling involves hardirq tracer, probing these functions cause breakpoint recursion problem.
Prohibit probing on those functions.
Signed-off-by: Masami Hiramatsu mhiramat@kernel.org --- kernel/trace/trace_irqsoff.c | 9 +++++++-- kernel/trace/trace_preemptirq.c | 5 +++++ 2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index 98ea6d28df15..829709bfec3d 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c @@ -14,6 +14,7 @@ #include <linux/uaccess.h> #include <linux/module.h> #include <linux/ftrace.h> +#include <linux/kprobes.h>
#include "trace.h"
@@ -368,7 +369,7 @@ check_critical_timing(struct trace_array *tr, __trace_function(tr, CALLER_ADDR0, parent_ip, flags, pc); }
-static inline void +static nokprobe_inline void start_critical_timing(unsigned long ip, unsigned long parent_ip, int pc) { int cpu; @@ -404,7 +405,7 @@ start_critical_timing(unsigned long ip, unsigned long parent_ip, int pc) atomic_dec(&data->disabled); }
-static inline void +static nokprobe_inline void stop_critical_timing(unsigned long ip, unsigned long parent_ip, int pc) { int cpu; @@ -446,6 +447,7 @@ void start_critical_timings(void) start_critical_timing(CALLER_ADDR0, CALLER_ADDR1, pc); } EXPORT_SYMBOL_GPL(start_critical_timings); +NOKPROBE_SYMBOL(start_critical_timings);
void stop_critical_timings(void) { @@ -455,6 +457,7 @@ void stop_critical_timings(void) stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1, pc); } EXPORT_SYMBOL_GPL(stop_critical_timings); +NOKPROBE_SYMBOL(stop_critical_timings);
#ifdef CONFIG_FUNCTION_TRACER static bool function_enabled; @@ -615,6 +618,7 @@ void tracer_hardirqs_on(unsigned long a0, unsigned long a1) if (!preempt_trace(pc) && irq_trace()) stop_critical_timing(a0, a1, pc); } +NOKPROBE_SYMBOL(tracer_hardirqs_on);
void tracer_hardirqs_off(unsigned long a0, unsigned long a1) { @@ -623,6 +627,7 @@ void tracer_hardirqs_off(unsigned long a0, unsigned long a1) if (!preempt_trace(pc) && irq_trace()) start_critical_timing(a0, a1, pc); } +NOKPROBE_SYMBOL(tracer_hardirqs_off);
static int irqsoff_tracer_init(struct trace_array *tr) { diff --git a/kernel/trace/trace_preemptirq.c b/kernel/trace/trace_preemptirq.c index 71f553cceb3c..4d8e99fdbbbe 100644 --- a/kernel/trace/trace_preemptirq.c +++ b/kernel/trace/trace_preemptirq.c @@ -9,6 +9,7 @@ #include <linux/uaccess.h> #include <linux/module.h> #include <linux/ftrace.h> +#include <linux/kprobes.h> #include "trace.h"
#define CREATE_TRACE_POINTS @@ -30,6 +31,7 @@ void trace_hardirqs_on(void) lockdep_hardirqs_on(CALLER_ADDR0); } EXPORT_SYMBOL(trace_hardirqs_on); +NOKPROBE_SYMBOL(trace_hardirqs_on);
void trace_hardirqs_off(void) { @@ -43,6 +45,7 @@ void trace_hardirqs_off(void) lockdep_hardirqs_off(CALLER_ADDR0); } EXPORT_SYMBOL(trace_hardirqs_off); +NOKPROBE_SYMBOL(trace_hardirqs_off);
__visible void trace_hardirqs_on_caller(unsigned long caller_addr) { @@ -56,6 +59,7 @@ __visible void trace_hardirqs_on_caller(unsigned long caller_addr) lockdep_hardirqs_on(CALLER_ADDR0); } EXPORT_SYMBOL(trace_hardirqs_on_caller); +NOKPROBE_SYMBOL(trace_hardirqs_on_caller);
__visible void trace_hardirqs_off_caller(unsigned long caller_addr) { @@ -69,6 +73,7 @@ __visible void trace_hardirqs_off_caller(unsigned long caller_addr) lockdep_hardirqs_off(CALLER_ADDR0); } EXPORT_SYMBOL(trace_hardirqs_off_caller); +NOKPROBE_SYMBOL(trace_hardirqs_off_caller); #endif /* CONFIG_TRACE_IRQFLAGS */
#ifdef CONFIG_TRACE_PREEMPT_TOGGLE
On Thu, 10 Jan 2019 11:56:53 +0900 Masami Hiramatsu mhiramat@kernel.org wrote:
Since kprobes breakpoint handling involves hardirq tracer, probing these functions cause breakpoint recursion problem.
Prohibit probing on those functions.
Signed-off-by: Masami Hiramatsu mhiramat@kernel.org
kernel/trace/trace_irqsoff.c | 9 +++++++-- kernel/trace/trace_preemptirq.c | 5 +++++ 2 files changed, 12 insertions(+), 2 deletions(-)
Acked-by: Steven Rostedt (VMware) rostedt@goodmis.org
-- Steve
On Thu, 10 Jan 2019 12:12:31 -0500 Steven Rostedt rostedt@goodmis.org wrote:
On Thu, 10 Jan 2019 11:56:53 +0900 Masami Hiramatsu mhiramat@kernel.org wrote:
Since kprobes breakpoint handling involves hardirq tracer, probing these functions cause breakpoint recursion problem.
Prohibit probing on those functions.
Signed-off-by: Masami Hiramatsu mhiramat@kernel.org
kernel/trace/trace_irqsoff.c | 9 +++++++-- kernel/trace/trace_preemptirq.c | 5 +++++ 2 files changed, 12 insertions(+), 2 deletions(-)
Acked-by: Steven Rostedt (VMware) rostedt@goodmis.org
Thank you for your Ack!
-- Steve
Since kprobes depends on preempt disable/enable, probing on the preempt debug routine can cause recursive breakpoint problem.
Signed-off-by: Masami Hiramatsu mhiramat@kernel.org --- lib/smp_processor_id.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c index 85925aaa4fff..157d9e31f6c2 100644 --- a/lib/smp_processor_id.c +++ b/lib/smp_processor_id.c @@ -5,10 +5,11 @@ * DEBUG_PREEMPT variant of smp_processor_id(). */ #include <linux/export.h> +#include <linux/kprobes.h> #include <linux/sched.h>
-notrace static unsigned int check_preemption_disabled(const char *what1, - const char *what2) +notrace static nokprobe_inline +unsigned int check_preemption_disabled(const char *what1, const char *what2) { int this_cpu = raw_smp_processor_id();
@@ -56,9 +57,11 @@ notrace unsigned int debug_smp_processor_id(void) return check_preemption_disabled("smp_processor_id", ""); } EXPORT_SYMBOL(debug_smp_processor_id); +NOKPROBE_SYMBOL(debug_smp_processor_id);
notrace void __this_cpu_preempt_check(const char *op) { check_preemption_disabled("__this_cpu_", op); } EXPORT_SYMBOL(__this_cpu_preempt_check); +NOKPROBE_SYMBOL(__this_cpu_preempt_check);
Since kprobe itself depends on RCU, probing on RCU debug routine can cause recursive breakpoint problem. Prohibit probing on RCU debug routines.
int3 ->do_int3() ->ist_enter() ->RCU_LOCKDEP_WARN() ->debug_lockdep_rcu_enabled() -> int3
Signed-off-by: Masami Hiramatsu mhiramat@kernel.org --- kernel/rcu/update.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index 1971869c4072..f4ca36d92138 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c @@ -52,6 +52,7 @@ #include <linux/tick.h> #include <linux/rcupdate_wait.h> #include <linux/sched/isolation.h> +#include <linux/kprobes.h>
#define CREATE_TRACE_POINTS
@@ -249,6 +250,7 @@ int notrace debug_lockdep_rcu_enabled(void) current->lockdep_recursion == 0; } EXPORT_SYMBOL_GPL(debug_lockdep_rcu_enabled); +NOKPROBE_SYMBOL(debug_lockdep_rcu_enabled);
/** * rcu_read_lock_held() - might we be in RCU read-side critical section?
Some lockdep functions can be involved in breakpoint handling and probing on those functions can cause a breakpoint recursion. Prohibit probing on those functions by blacklist.
Signed-off-by: Masami Hiramatsu mhiramat@kernel.org --- kernel/locking/lockdep.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 95932333a48b..bc35a54ae3d4 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -50,6 +50,7 @@ #include <linux/random.h> #include <linux/jhash.h> #include <linux/nmi.h> +#include <linux/kprobes.h>
#include <asm/sections.h>
@@ -2814,6 +2815,7 @@ void lockdep_hardirqs_on(unsigned long ip) __trace_hardirqs_on_caller(ip); current->lockdep_recursion = 0; } +NOKPROBE_SYMBOL(lockdep_hardirqs_on);
/* * Hardirqs were disabled: @@ -2843,6 +2845,7 @@ void lockdep_hardirqs_off(unsigned long ip) } else debug_atomic_inc(redundant_hardirqs_off); } +NOKPROBE_SYMBOL(lockdep_hardirqs_off);
/* * Softirqs will be enabled: @@ -3650,7 +3653,8 @@ __lock_release(struct lockdep_map *lock, int nested, unsigned long ip) return 0; }
-static int __lock_is_held(const struct lockdep_map *lock, int read) +static nokprobe_inline +int __lock_is_held(const struct lockdep_map *lock, int read) { struct task_struct *curr = current; int i; @@ -3883,6 +3887,7 @@ int lock_is_held_type(const struct lockdep_map *lock, int read) return ret; } EXPORT_SYMBOL_GPL(lock_is_held_type); +NOKPROBE_SYMBOL(lock_is_held_type);
struct pin_cookie lock_pin_lock(struct lockdep_map *lock) {
linux-stable-mirror@lists.linaro.org