Commit e5779e8e authored by Andy Lutomirski's avatar Andy Lutomirski Committed by Ingo Molnar

perf/x86/hw_breakpoints: Disallow kernel breakpoints unless kprobe-safe

Code on the kprobe blacklist doesn't want unexpected int3
exceptions. It probably doesn't want unexpected debug exceptions
either. Be safe: disallow breakpoints in nokprobes code.

On non-CONFIG_KPROBES kernels, there is no kprobe blacklist.  In
that case, disallow kernel breakpoints entirely.

It will be particularly important to keep hw breakpoints out of the
entry and NMI code once we move debug exceptions off the IST stack.
Signed-off-by: default avatarAndy Lutomirski <luto@kernel.org>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/e14b152af99640448d895e3c2a8c2d5ee19a1325.1438312874.git.luto@kernel.orgSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent ae3f011f
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/irqflags.h> #include <linux/irqflags.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include <linux/kprobes.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/kdebug.h> #include <linux/kdebug.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -243,6 +244,20 @@ static int arch_build_bp_info(struct perf_event *bp) ...@@ -243,6 +244,20 @@ static int arch_build_bp_info(struct perf_event *bp)
info->type = X86_BREAKPOINT_RW; info->type = X86_BREAKPOINT_RW;
break; break;
case HW_BREAKPOINT_X: case HW_BREAKPOINT_X:
/*
* We don't allow kernel breakpoints in places that are not
* acceptable for kprobes. On non-kprobes kernels, we don't
* allow kernel breakpoints at all.
*/
if (bp->attr.bp_addr >= TASK_SIZE_MAX) {
#ifdef CONFIG_KPROBES
if (within_kprobe_blacklist(bp->attr.bp_addr))
return -EINVAL;
#else
return -EINVAL;
#endif
}
info->type = X86_BREAKPOINT_EXECUTE; info->type = X86_BREAKPOINT_EXECUTE;
/* /*
* x86 inst breakpoints need to have a specific undefined len. * x86 inst breakpoints need to have a specific undefined len.
......
...@@ -267,6 +267,8 @@ extern void show_registers(struct pt_regs *regs); ...@@ -267,6 +267,8 @@ extern void show_registers(struct pt_regs *regs);
extern void kprobes_inc_nmissed_count(struct kprobe *p); extern void kprobes_inc_nmissed_count(struct kprobe *p);
extern bool arch_within_kprobe_blacklist(unsigned long addr); extern bool arch_within_kprobe_blacklist(unsigned long addr);
extern bool within_kprobe_blacklist(unsigned long addr);
struct kprobe_insn_cache { struct kprobe_insn_cache {
struct mutex mutex; struct mutex mutex;
void *(*alloc)(void); /* allocate insn page */ void *(*alloc)(void); /* allocate insn page */
......
...@@ -1332,7 +1332,7 @@ bool __weak arch_within_kprobe_blacklist(unsigned long addr) ...@@ -1332,7 +1332,7 @@ bool __weak arch_within_kprobe_blacklist(unsigned long addr)
addr < (unsigned long)__kprobes_text_end; addr < (unsigned long)__kprobes_text_end;
} }
static bool within_kprobe_blacklist(unsigned long addr) bool within_kprobe_blacklist(unsigned long addr)
{ {
struct kprobe_blacklist_entry *ent; struct kprobe_blacklist_entry *ent;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment