diff options
-rw-r--r-- | arch/x86/include/asm/alternative.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/alternative.c | 31 | ||||
-rw-r--r-- | arch/x86/kernel/traps.c | 4 | ||||
-rw-r--r-- | kernel/kprobes.c | 2 |
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 | */ |
226 | extern void *text_poke(void *addr, const void *opcode, size_t len); | 227 | extern void *text_poke(void *addr, const void *opcode, size_t len); |
228 | extern int poke_int3_handler(struct pt_regs *regs); | ||
227 | extern void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler); | 229 | extern 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) | |||
605 | static bool bp_patching_in_progress; | 605 | static bool bp_patching_in_progress; |
606 | static void *bp_int3_handler, *bp_int3_addr; | 606 | static void *bp_int3_handler, *bp_int3_addr; |
607 | 607 | ||
608 | static int int3_notify(struct notifier_block *self, unsigned long val, void *data) | 608 | int 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 */ | ||
694 | static struct notifier_block int3_nb = { | ||
695 | .priority = 0x7fffffff, | ||
696 | .notifier_call = int3_notify | ||
697 | }; | ||
698 | |||
699 | static int __init int3_init(void) | ||
700 | { | ||
701 | return register_die_notifier(&int3_nb); | ||
702 | } | ||
703 | |||
704 | arch_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 | ||
1710 | static struct notifier_block kprobe_exceptions_nb = { | 1710 | static 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 | ||
1715 | unsigned long __weak arch_deref_entry_point(void *entry) | 1715 | unsigned long __weak arch_deref_entry_point(void *entry) |