diff options
author | Fernando Luis Vázquez Cao <fernando@oss.ntt.co.jp> | 2006-09-26 04:52:36 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-09-26 04:52:36 -0400 |
commit | 06039754d775d3e48e4a292e4f353321205eff53 (patch) | |
tree | a6abdd9ca0efb34006792e7275c4a2c954b229be /arch/i386/kernel/traps.c | |
parent | 6f6b1e0477ccb2f25a9b045e38440347d2ce21c8 (diff) |
[PATCH] i386: Disallow kprobes on NMI handlers
A kprobe executes IRET early and that could cause NMI recursion and stack
corruption.
Note: This problem was originally spotted and solved by Andi Kleen in the
x86_64 architecture. This patch is an adaption of his patch for i386.
AK: Merged with current code which was a bit different.
AK: Removed printk in nmi handler that shouldn't be there in the first time
AK: Added missing include.
AK: added KPROBES_END
Signed-off-by: Fernando Vazquez <fernando@intellilink.co.jp>
Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r-- | arch/i386/kernel/traps.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 00d643f3de41..5c0f4960c67d 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -689,7 +689,8 @@ gp_in_kernel: | |||
689 | } | 689 | } |
690 | } | 690 | } |
691 | 691 | ||
692 | static void mem_parity_error(unsigned char reason, struct pt_regs * regs) | 692 | static __kprobes void |
693 | mem_parity_error(unsigned char reason, struct pt_regs * regs) | ||
693 | { | 694 | { |
694 | printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on " | 695 | printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on " |
695 | "CPU %d.\n", reason, smp_processor_id()); | 696 | "CPU %d.\n", reason, smp_processor_id()); |
@@ -704,7 +705,8 @@ static void mem_parity_error(unsigned char reason, struct pt_regs * regs) | |||
704 | clear_mem_error(reason); | 705 | clear_mem_error(reason); |
705 | } | 706 | } |
706 | 707 | ||
707 | static void io_check_error(unsigned char reason, struct pt_regs * regs) | 708 | static __kprobes void |
709 | io_check_error(unsigned char reason, struct pt_regs * regs) | ||
708 | { | 710 | { |
709 | unsigned long i; | 711 | unsigned long i; |
710 | 712 | ||
@@ -720,7 +722,8 @@ static void io_check_error(unsigned char reason, struct pt_regs * regs) | |||
720 | outb(reason, 0x61); | 722 | outb(reason, 0x61); |
721 | } | 723 | } |
722 | 724 | ||
723 | static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) | 725 | static __kprobes void |
726 | unknown_nmi_error(unsigned char reason, struct pt_regs * regs) | ||
724 | { | 727 | { |
725 | #ifdef CONFIG_MCA | 728 | #ifdef CONFIG_MCA |
726 | /* Might actually be able to figure out what the guilty party | 729 | /* Might actually be able to figure out what the guilty party |
@@ -741,7 +744,7 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) | |||
741 | 744 | ||
742 | static DEFINE_SPINLOCK(nmi_print_lock); | 745 | static DEFINE_SPINLOCK(nmi_print_lock); |
743 | 746 | ||
744 | void die_nmi (struct pt_regs *regs, const char *msg) | 747 | void __kprobes die_nmi(struct pt_regs *regs, const char *msg) |
745 | { | 748 | { |
746 | if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) == | 749 | if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) == |
747 | NOTIFY_STOP) | 750 | NOTIFY_STOP) |
@@ -773,7 +776,7 @@ void die_nmi (struct pt_regs *regs, const char *msg) | |||
773 | do_exit(SIGSEGV); | 776 | do_exit(SIGSEGV); |
774 | } | 777 | } |
775 | 778 | ||
776 | static void default_do_nmi(struct pt_regs * regs) | 779 | static __kprobes void default_do_nmi(struct pt_regs * regs) |
777 | { | 780 | { |
778 | unsigned char reason = 0; | 781 | unsigned char reason = 0; |
779 | 782 | ||
@@ -811,7 +814,7 @@ static void default_do_nmi(struct pt_regs * regs) | |||
811 | reassert_nmi(); | 814 | reassert_nmi(); |
812 | } | 815 | } |
813 | 816 | ||
814 | fastcall void do_nmi(struct pt_regs * regs, long error_code) | 817 | fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code) |
815 | { | 818 | { |
816 | int cpu; | 819 | int cpu; |
817 | 820 | ||