From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751714AbdG0HC2 (ORCPT ); Thu, 27 Jul 2017 03:02:28 -0400 Received: from mail.kernel.org ([198.145.29.99]:44156 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751682AbdG0HC1 (ORCPT ); Thu, 27 Jul 2017 03:02:27 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E64B822C97 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=mhiramat@kernel.org From: Masami Hiramatsu To: Ingo Molnar Cc: Francis Deslauriers , mathieu.desnoyers@efficios.com, Thomas Gleixner , Ingo Molnar , "H . Peter Anvin" , x86@kernel.org, Masami Hiramatsu , Ananth N Mavinakayanahalli , Anil S Keshavamurthy , "David S . Miller" , linux-kernel@vger.kernel.org Subject: [PATCH -tip v4] [BUGFIX] kprobes/x86: Do not jump-optimize kprobes on irq entry code Date: Thu, 27 Jul 2017 16:01:37 +0900 Message-Id: <150113888679.3169.18059401640325215627.stgit@devbox> X-Mailer: git-send-email 2.9.4 User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 Reported-by: Francis Deslauriers Tested-by: Francis Deslauriers --- Changes in v4: - Fix to use CONFIG_OPTPROBES instead of CONFIG_KPROBES. --- 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 #include #include +#include #include #include @@ -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..f95b046 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_OPTPROBES) /* * We want to know which function is an entrypoint of a hardirq or a softirq. */