aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/alternative.h2
-rw-r--r--arch/x86/kernel/alternative.c31
-rw-r--r--arch/x86/kernel/traps.c4
-rw-r--r--kernel/kprobes.c2
4 files changed, 15 insertions, 24 deletions
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index 4daf8c501239..0a3f9c9f98d5 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -5,6 +5,7 @@
5#include <linux/stddef.h> 5#include <linux/stddef.h>
6#include <linux/stringify.h> 6#include <linux/stringify.h>
7#include <asm/asm.h> 7#include <asm/asm.h>
8#include <asm/ptrace.h>
8 9
9/* 10/*
10 * Alternative inline assembly for SMP. 11 * Alternative inline assembly for SMP.
@@ -224,6 +225,7 @@ extern void *text_poke_early(void *addr, const void *opcode, size_t len);
224 * inconsistent instruction while you patch. 225 * inconsistent instruction while you patch.
225 */ 226 */
226extern void *text_poke(void *addr, const void *opcode, size_t len); 227extern void *text_poke(void *addr, const void *opcode, size_t len);
228extern int poke_int3_handler(struct pt_regs *regs);
227extern void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler); 229extern void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler);
228 230
229#endif /* _ASM_X86_ALTERNATIVE_H */ 231#endif /* _ASM_X86_ALTERNATIVE_H */
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 5d8782ee3dd7..15e8563e5c24 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -605,26 +605,24 @@ static void do_sync_core(void *info)
605static bool bp_patching_in_progress; 605static bool bp_patching_in_progress;
606static void *bp_int3_handler, *bp_int3_addr; 606static void *bp_int3_handler, *bp_int3_addr;
607 607
608static int int3_notify(struct notifier_block *self, unsigned long val, void *data) 608int poke_int3_handler(struct pt_regs *regs)
609{ 609{
610 struct die_args *args = data;
611
612 /* bp_patching_in_progress */ 610 /* bp_patching_in_progress */
613 smp_rmb(); 611 smp_rmb();
614 612
615 if (likely(!bp_patching_in_progress)) 613 if (likely(!bp_patching_in_progress))
616 return NOTIFY_DONE; 614 return 0;
617 615
618 /* we are not interested in non-int3 faults and ring > 0 faults */ 616 if (user_mode_vm(regs) || regs->ip != (unsigned long)bp_int3_addr)
619 if (val != DIE_INT3 || !args->regs || user_mode_vm(args->regs) 617 return 0;
620 || args->regs->ip != (unsigned long)bp_int3_addr)
621 return NOTIFY_DONE;
622 618
623 /* set up the specified breakpoint handler */ 619 /* set up the specified breakpoint handler */
624 args->regs->ip = (unsigned long) bp_int3_handler; 620 regs->ip = (unsigned long) bp_int3_handler;
621
622 return 1;
625 623
626 return NOTIFY_STOP;
627} 624}
625
628/** 626/**
629 * text_poke_bp() -- update instructions on live kernel on SMP 627 * text_poke_bp() -- update instructions on live kernel on SMP
630 * @addr: address to patch 628 * @addr: address to patch
@@ -689,16 +687,3 @@ void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler)
689 return addr; 687 return addr;
690} 688}
691 689
692/* this one needs to run before anything else handles it as a
693 * regular exception */
694static struct notifier_block int3_nb = {
695 .priority = 0x7fffffff,
696 .notifier_call = int3_notify
697};
698
699static int __init int3_init(void)
700{
701 return register_die_notifier(&int3_nb);
702}
703
704arch_initcall(int3_init);
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 1b23a1c92746..8c8093b146ca 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -58,6 +58,7 @@
58#include <asm/mce.h> 58#include <asm/mce.h>
59#include <asm/fixmap.h> 59#include <asm/fixmap.h>
60#include <asm/mach_traps.h> 60#include <asm/mach_traps.h>
61#include <asm/alternative.h>
61 62
62#ifdef CONFIG_X86_64 63#ifdef CONFIG_X86_64
63#include <asm/x86_init.h> 64#include <asm/x86_init.h>
@@ -327,6 +328,9 @@ dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_co
327 ftrace_int3_handler(regs)) 328 ftrace_int3_handler(regs))
328 return; 329 return;
329#endif 330#endif
331 if (poke_int3_handler(regs))
332 return;
333
330 prev_state = exception_enter(); 334 prev_state = exception_enter();
331#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP 335#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
332 if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, 336 if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index b58b490fa439..6e33498d665c 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1709,7 +1709,7 @@ EXPORT_SYMBOL_GPL(unregister_kprobes);
1709 1709
1710static struct notifier_block kprobe_exceptions_nb = { 1710static struct notifier_block kprobe_exceptions_nb = {
1711 .notifier_call = kprobe_exceptions_notify, 1711 .notifier_call = kprobe_exceptions_notify,
1712 .priority = 0x7ffffff0 /* High priority, but not first. */ 1712 .priority = 0x7fffffff /* we need to be notified first */
1713}; 1713};
1714 1714
1715unsigned long __weak arch_deref_entry_point(void *entry) 1715unsigned long __weak arch_deref_entry_point(void *entry)