i386: Disallow kprobes on NMI handlers
PATCH 1/2 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 identified and solved by Andi Kleen in the x86_64 architecture. This patch is an adaption of his patch for i386.
---
arch/i386/kernel/entry.S +1 -1
@@ -725,7 +725,7 @@ debug_stack_correct: * check whether we got an NMI on the debug path where the debug * fault happened on the sysenter path. */ -ENTRY(nmi) +KPROBE_ENTRY(nmi) RING0_INT_FRAME pushl %eax CFI_ADJUST_CFA_OFFSET 4
arch/i386/kernel/nmi.c +1 -1
@@ -579,7 +579,7 @@ EXPORT_SYMBOL(touch_nmi_watchdog);extern void die_nmi (struct pt_regs *,const char *msg); -void nmi_watchdog_tick (struct pt_regs * regs) +void __kprobes nmi_watchdog_tick (struct pt_regs * regs) {/*
arch/i386/kernel/traps.c +10 -7
@@ -626,7 +626,8 @@ gp_in_kernel: } } -static void mem_parity_error (unsigned char reason,struct pt_regs * regs) +static __kprobes void +mem_parity_error (unsigned char reason,struct pt_regs * regs) {printk (KERN_EMERG "Uhhuh. NMI received. Dazed and confused, but trying " "to continue\n" );
@@ -637,7 +638,8 @@ static void mem_parity_error(unsigned chclear_mem_error (reason); } -static void io_check_error (unsigned char reason,struct pt_regs * regs) +static __kprobes void +io_check_error (unsigned char reason,struct pt_regs * regs) {unsigned long i;
@@ -653,7 +655,8 @@ static void io_check_error(unsigned charoutb (reason,0x61 ); } -static void unknown_nmi_error (unsigned char reason,struct pt_regs * regs) +static __kprobes void +unknown_nmi_error (unsigned char reason,struct pt_regs * regs) {#ifdef CONFIG_MCA /* Might actually be able to figure out what the guilty party
@@ -671,7 +674,7 @@ static void unknown_nmi_error(unsigned cstatic DEFINE_SPINLOCK (nmi_print_lock); -void die_nmi (struct pt_regs *regs,const char *msg) +void __kprobes die_nmi (struct pt_regs *regs,const char *msg) {if (notify_die (DIE_NMIWATCHDOG , msg, regs,0 ,2 ,SIGINT ) ==NOTIFY_STOP )
@@ -703,7 +706,7 @@ void die_nmi (struct pt_regs *regs, consdo_exit (SIGSEGV ); } -static void default_do_nmi (struct pt_regs * regs) +static __kprobes void default_do_nmi (struct pt_regs * regs) {unsigned char reason =0 ;
@@ -741,14 +744,14 @@ static void default_do_nmi(struct pt_regreassert_nmi (); } -static int dummy_nmi_callback (struct pt_regs * regs,int cpu) +static __kprobes int dummy_nmi_callback (struct pt_regs * regs,int cpu) {return 0 ; }static nmi_callback_t nmi_callback = dummy_nmi_callback; -fastcall void do_nmi(struct pt_regs * regs, long error_code) +fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code) {int cpu;
This version of the patch does not compile. I will fix this problem and resend it.
Sorry for the noise.
Quoted 108 lines · Fernando Luis Vázquez Cao
A kprobe executes IRET early and that could cause NMI recursion and stack corruption.
Note: This problem was originally identified and solved by Andi Kleen in the
x86_64architecture. This patch is an adaption of his patch for i386.Signed-off-by Fernando Vazquez <[email protected]>---
diff -urNp
linux-2.6.18-rc4-orig/arch/i386/kernel/entry.Slinux-2.6.18-rc4/arch/i386/kernel/entry.Sarch/i386/kernel/entry.S +1
-1@@ -725,7 +725,7 @@ debug_stack_correct: * check whether we got an NMI on the debug path where the debug * fault happened on the sysenter path. */ -ENTRY(nmi) +KPROBE_ENTRY(nmi) RING0_INT_FRAME pushl %eax CFI_ADJUST_CFA_OFFSET 4diff -urNp
linux-2.6.18-rc4-orig/arch/i386/kernel/nmi.clinux-2.6.18-rc4/arch/i386/kernel/nmi.carch/i386/kernel/nmi.c +1
-1@@ -579,7 +579,7 @@ EXPORT_SYMBOL(touch_nmi_watchdog);extern void die_nmi (struct pt_regs *,const char *msg); -void nmi_watchdog_tick (struct pt_regs * regs) +void __kprobes nmi_watchdog_tick (struct pt_regs * regs) {/* diff -urNp
linux-2.6.18-rc4-orig/arch/i386/kernel/traps.clinux-2.6.18-rc4/arch/i386/kernel/traps.carch/i386/kernel/traps.c +10
-8@@ -626,7 +626,8 @@ gp_in_kernel: } } -static void mem_parity_error (unsigned char reason,struct pt_regs * regs) +static __kprobes void +mem_parity_error (unsigned char reason,struct pt_regs * regs) {printk (KERN_EMERG "Uhhuh. NMI received. Dazed and confused, but trying " "to continue\n" );@@ -637,7 +638,8 @@ static void mem_parity_error(unsigned chclear_mem_error (reason); } -static void io_check_error (unsigned char reason,struct pt_regs * regs) +static __kprobes void +io_check_error (unsigned char reason,struct pt_regs * regs) {unsigned long i;@@ -653,7 +655,8 @@ static void io_check_error(unsigned charoutb (reason,0x61 ); } -static void unknown_nmi_error (unsigned char reason,struct pt_regs * regs) +static __kprobes void +unknown_nmi_error (unsigned char reason,struct pt_regs * regs) {#ifdef CONFIG_MCA /* Might actually be able to figure out what the guilty party @@ -671,7 +674,7 @@ static void unknown_nmi_error(unsigned cstatic DEFINE_SPINLOCK (nmi_print_lock); -void die_nmi (struct pt_regs *regs,const char *msg) +void __kprobes die_nmi (struct pt_regs *regs,const char *msg) {if (notify_die (DIE_NMIWATCHDOG , msg, regs,0 ,2 ,SIGINT ) ==NOTIFY_STOP )@@ -703,7 +706,7 @@ void die_nmi (struct pt_regs *regs, consdo_exit (SIGSEGV ); } -static void default_do_nmi (struct pt_regs * regs) +static __kprobes void default_do_nmi (struct pt_regs * regs) {unsigned char reason =0 ;@@ -741,14 +744,14 @@ static void default_do_nmi(struct pt_regreassert_nmi (); } -static int dummy_nmi_callback (struct pt_regs * regs,int cpu) +static __kprobes int dummy_nmi_callback (struct pt_regs * regs,int cpu) {return 0 ; }static nmi_callback_t nmi_callback = dummy_nmi_callback; -fastcall void do_nmi(struct pt_regs * regs, long error_code) +fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code) {int cpu; -To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/