[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>
This commit is contained in:
Родитель
6f6b1e0477
Коммит
06039754d7
|
@ -729,7 +729,7 @@ KPROBE_END(debug)
|
|||
* 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
|
||||
|
@ -805,6 +805,7 @@ nmi_16bit_stack:
|
|||
.align 4
|
||||
.long 1b,iret_exc
|
||||
.previous
|
||||
KPROBE_END(nmi)
|
||||
|
||||
KPROBE_ENTRY(int3)
|
||||
RING0_INT_FRAME
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/sysctl.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kprobes.h>
|
||||
|
||||
#include <asm/smp.h>
|
||||
#include <asm/nmi.h>
|
||||
|
@ -882,7 +883,7 @@ EXPORT_SYMBOL(touch_nmi_watchdog);
|
|||
|
||||
extern void die_nmi(struct pt_regs *, const char *msg);
|
||||
|
||||
int nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
|
||||
__kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
|
||||
{
|
||||
|
||||
/*
|
||||
|
@ -962,8 +963,7 @@ int nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
|
|||
* This matches the old behaviour.
|
||||
*/
|
||||
rc = 1;
|
||||
} else
|
||||
printk(KERN_WARNING "Unknown enabled NMI hardware?!\n");
|
||||
}
|
||||
}
|
||||
done:
|
||||
return rc;
|
||||
|
|
|
@ -689,7 +689,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 for unknown reason %02x on "
|
||||
"CPU %d.\n", reason, smp_processor_id());
|
||||
|
@ -704,7 +705,8 @@ static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
|
|||
clear_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;
|
||||
|
||||
|
@ -720,7 +722,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)
|
||||
{
|
||||
#ifdef CONFIG_MCA
|
||||
/* 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)
|
|||
|
||||
static 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)
|
||||
|
@ -773,7 +776,7 @@ void die_nmi (struct pt_regs *regs, const char *msg)
|
|||
do_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;
|
||||
|
||||
|
@ -811,7 +814,7 @@ static void default_do_nmi(struct pt_regs * regs)
|
|||
reassert_nmi();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче