On Tue, 25 Jul 2017 23:54:49 +0900 Masami Hiramatsu <mhira...@kernel.org> wrote:
> Since the kernel segment registers are not prepared at the > entry of irq-entry code, if a kprobe on such code is > jump-optimized, accessing per-cpu variables may cause > kernel panic. > However, if the kprobe is not optimized, it kicks int3 > exception and set segment registers correctly. > > This checks probe-address and if it is in irq-entry code, > it prohibits optimizing such kprobes. This means we can > continuously probing such interrupt handlers by kprobes > but it is not optimized anymore. > > Signed-off-by: Masami Hiramatsu <mhira...@kernel.org> > Reported-by: Francis Deslauriers <francis.deslauri...@efficios.com> > Tested-by: Francis Deslauriers <francis.deslauri...@efficios.com> > --- > Changes in V3: > - Define __irqentry_text_start/end symbols when CONFIG_OPTPROBES=y. > --- > arch/x86/kernel/kprobes/opt.c | 9 ++++++--- > include/asm-generic/vmlinux.lds.h | 6 ++++-- > include/linux/interrupt.h | 3 ++- > 3 files changed, 12 insertions(+), 6 deletions(-) > > diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c > index 69ea0bc..c26e7f9 100644 > --- a/arch/x86/kernel/kprobes/opt.c > +++ b/arch/x86/kernel/kprobes/opt.c > @@ -29,6 +29,7 @@ > #include <linux/kallsyms.h> > #include <linux/ftrace.h> > #include <linux/frame.h> > +#include <linux/interrupt.h> > > #include <asm/text-patching.h> > #include <asm/cacheflush.h> > @@ -251,10 +252,12 @@ static int can_optimize(unsigned long paddr) > > /* > * Do not optimize in the entry code due to the unstable > - * stack handling. > + * stack handling and registers setup. > */ > - if ((paddr >= (unsigned long)__entry_text_start) && > - (paddr < (unsigned long)__entry_text_end)) > + if (((paddr >= (unsigned long)__entry_text_start) && > + (paddr < (unsigned long)__entry_text_end)) || > + ((paddr >= (unsigned long)__irqentry_text_start) && > + (paddr < (unsigned long)__irqentry_text_end))) > return 0; > > /* Check there is enough space for a relative jump. */ > diff --git a/include/asm-generic/vmlinux.lds.h > b/include/asm-generic/vmlinux.lds.h > index da0be9a..3092a1f 100644 > --- a/include/asm-generic/vmlinux.lds.h > +++ b/include/asm-generic/vmlinux.lds.h > @@ -483,7 +483,8 @@ > *(.entry.text) \ > VMLINUX_SYMBOL(__entry_text_end) = .; > > -#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN) > +#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN) || > \ > + defined(CONFIG_OPTPROBES) > #define IRQENTRY_TEXT > \ > ALIGN_FUNCTION(); \ > VMLINUX_SYMBOL(__irqentry_text_start) = .; \ > @@ -493,7 +494,8 @@ > #define IRQENTRY_TEXT > #endif > > -#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN) > +#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN) || > \ > + defined(CONFIG_OPTPROBES) > #define SOFTIRQENTRY_TEXT \ > ALIGN_FUNCTION(); \ > VMLINUX_SYMBOL(__softirqentry_text_start) = .; \ > diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h > index a2fdddd..a1b78f4 100644 > --- a/include/linux/interrupt.h > +++ b/include/linux/interrupt.h > @@ -726,7 +726,8 @@ extern int early_irq_init(void); > extern int arch_probe_nr_irqs(void); > extern int arch_early_irq_init(void); > > -#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN) > +#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN) || \ > + defined(CONFIG_KPROBES) Oops, this should be CONFIG_OPTPROBES... > /* > * We want to know which function is an entrypoint of a hardirq or a softirq. > */ > -- Masami Hiramatsu <mhira...@kernel.org>