diff options
| author | Andi Kleen <ak@suse.de> | 2006-02-03 21:50:41 +0100 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-04 16:43:12 -0800 | 
| commit | eddb6fb9a54cdc8c7c37e056a2b4bbbc8a128a36 (patch) | |
| tree | c8b9a0773518f45aa86d861fce959c3c4f946b06 /arch | |
| parent | 2f01942536d8c686a3f6b3b38f1257caa2fb763e (diff) | |
[PATCH] x86_64: Disallow kprobes on NMI handlers
A kprobe executes IRET early and that could cause NMI recursion
and stack corruption.
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/x86_64/kernel/entry.S | 3 | ||||
| -rw-r--r-- | arch/x86_64/kernel/nmi.c | 7 | ||||
| -rw-r--r-- | arch/x86_64/kernel/traps.c | 21 | 
3 files changed, 18 insertions, 13 deletions
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index dbdba56e8faa..cdf9cb1288c1 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S @@ -922,7 +922,7 @@ KPROBE_ENTRY(debug)  	.previous .text  	/* runs on exception stack */	 -ENTRY(nmi) +KPROBE_ENTRY(nmi)  	INTR_FRAME  	pushq $-1  	CFI_ADJUST_CFA_OFFSET 8 @@ -969,6 +969,7 @@ paranoid_schedule:  	cli  	jmp paranoid_userspace  	CFI_ENDPROC +	.previous .text  KPROBE_ENTRY(int3)   	INTR_FRAME diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index 5fae6f0cd994..8be407a1f62d 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c @@ -24,6 +24,7 @@  #include <linux/sysdev.h>  #include <linux/nmi.h>  #include <linux/sysctl.h> +#include <linux/kprobes.h>  #include <asm/smp.h>  #include <asm/mtrr.h> @@ -468,7 +469,7 @@ void touch_nmi_watchdog (void)   	touch_softlockup_watchdog();  } -void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason) +void __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)  {  	int sum;  	int touched = 0; @@ -512,14 +513,14 @@ void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)  	}  } -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; -asmlinkage void do_nmi(struct pt_regs * regs, long error_code) +asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code)  {  	int cpu = safe_smp_processor_id(); diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 8bb0aeda78b9..ee1b2da9e5e7 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -372,7 +372,7 @@ void out_of_line_bug(void)  static DEFINE_SPINLOCK(die_lock);  static int die_owner = -1; -unsigned long oops_begin(void) +unsigned __kprobes long oops_begin(void)  {  	int cpu = safe_smp_processor_id();  	unsigned long flags; @@ -391,7 +391,7 @@ unsigned long oops_begin(void)  	return flags;  } -void oops_end(unsigned long flags) +void __kprobes oops_end(unsigned long flags)  {   	die_owner = -1;  	bust_spinlocks(0); @@ -400,7 +400,7 @@ void oops_end(unsigned long flags)  		panic("Oops");  } -void __die(const char * str, struct pt_regs * regs, long err) +void __kprobes __die(const char * str, struct pt_regs * regs, long err)  {  	static int die_counter;  	printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff,++die_counter); @@ -432,7 +432,7 @@ void die(const char * str, struct pt_regs * regs, long err)  	do_exit(SIGSEGV);   } -void die_nmi(char *str, struct pt_regs *regs) +void __kprobes die_nmi(char *str, struct pt_regs *regs)  {  	unsigned long flags = oops_begin(); @@ -575,7 +575,8 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,  	}  } -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("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");  	printk("You probably have a hardware problem with your RAM chips\n"); @@ -585,7 +586,8 @@ static void mem_parity_error(unsigned char reason, struct pt_regs * regs)  	outb(reason, 0x61);  } -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)  {  	printk("NMI: IOCK error (debug interrupt?)\n");  	show_registers(regs); @@ -598,7 +600,8 @@ static void io_check_error(unsigned char reason, struct pt_regs * regs)  	outb(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)  {	printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);  	printk("Dazed and confused, but trying to continue\n");  	printk("Do you have a strange power saving mode enabled?\n"); @@ -606,7 +609,7 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)  /* Runs on IST stack. This code must keep interrupts off all the time.     Nested NMIs are prevented by the CPU. */ -asmlinkage void default_do_nmi(struct pt_regs *regs) +asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)  {  	unsigned char reason = 0;  	int cpu; @@ -658,7 +661,7 @@ asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)  /* Help handler running on IST stack to switch back to user stack     for scheduling or signal handling. The actual stack switch is done in     entry.S */ -asmlinkage struct pt_regs *sync_regs(struct pt_regs *eregs) +asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)  {  	struct pt_regs *regs = eregs;  	/* Did already sync */  | 
