Commit 644f6741 authored by Prasanna S. Panchamukhi's avatar Prasanna S. Panchamukhi Committed by Linus Torvalds

[PATCH] kprobes exception notifier fix

This patch modifies the return value of kprobes exceptions notify handler. 
The kprobes exception notifier returns NOTIFY_STOP on handling
notification.  This patch helps other debuggers to co-exists with the
Kprobes.  Other debuggers registered for exceptions notification must
return NOTIFY_STOP on handling the notification.
Signed-off-by: default avatarPrasanna S Panchamukhi <prasanna@in.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5fe20d6e
...@@ -267,26 +267,26 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, ...@@ -267,26 +267,26 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
switch (val) { switch (val) {
case DIE_INT3: case DIE_INT3:
if (kprobe_handler(args->regs)) if (kprobe_handler(args->regs))
return NOTIFY_OK; return NOTIFY_STOP;
break; break;
case DIE_DEBUG: case DIE_DEBUG:
if (post_kprobe_handler(args->regs)) if (post_kprobe_handler(args->regs))
return NOTIFY_OK; return NOTIFY_STOP;
break; break;
case DIE_GPF: case DIE_GPF:
if (kprobe_running() && if (kprobe_running() &&
kprobe_fault_handler(args->regs, args->trapnr)) kprobe_fault_handler(args->regs, args->trapnr))
return NOTIFY_OK; return NOTIFY_STOP;
break; break;
case DIE_PAGE_FAULT: case DIE_PAGE_FAULT:
if (kprobe_running() && if (kprobe_running() &&
kprobe_fault_handler(args->regs, args->trapnr)) kprobe_fault_handler(args->regs, args->trapnr))
return NOTIFY_OK; return NOTIFY_STOP;
break; break;
default: default:
break; break;
} }
return NOTIFY_BAD; return NOTIFY_DONE;
} }
int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
......
...@@ -459,7 +459,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ ...@@ -459,7 +459,7 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
info.si_code = sicode; \ info.si_code = sicode; \
info.si_addr = (void __user *)siaddr; \ info.si_addr = (void __user *)siaddr; \
if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
== NOTIFY_OK) \ == NOTIFY_STOP) \
return; \ return; \
do_trap(trapnr, signr, str, 1, regs, error_code, &info); \ do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
} }
...@@ -528,7 +528,7 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) ...@@ -528,7 +528,7 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
gp_in_kernel: gp_in_kernel:
if (!fixup_exception(regs)) { if (!fixup_exception(regs)) {
if (notify_die(DIE_GPF, "general protection fault", regs, if (notify_die(DIE_GPF, "general protection fault", regs,
error_code, 13, SIGSEGV) == NOTIFY_OK); error_code, 13, SIGSEGV) == NOTIFY_STOP);
return; return;
die("general protection fault", regs, error_code); die("general protection fault", regs, error_code);
} }
...@@ -602,7 +602,7 @@ static void default_do_nmi(struct pt_regs * regs) ...@@ -602,7 +602,7 @@ static void default_do_nmi(struct pt_regs * regs)
if (!(reason & 0xc0)) { if (!(reason & 0xc0)) {
if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT) if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
== NOTIFY_BAD) == NOTIFY_STOP)
return; return;
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
/* /*
...@@ -617,7 +617,7 @@ static void default_do_nmi(struct pt_regs * regs) ...@@ -617,7 +617,7 @@ static void default_do_nmi(struct pt_regs * regs)
unknown_nmi_error(reason, regs); unknown_nmi_error(reason, regs);
return; return;
} }
if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_BAD) if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP)
return; return;
if (reason & 0x80) if (reason & 0x80)
mem_parity_error(reason, regs); mem_parity_error(reason, regs);
...@@ -666,7 +666,7 @@ void unset_nmi_callback(void) ...@@ -666,7 +666,7 @@ void unset_nmi_callback(void)
asmlinkage int do_int3(struct pt_regs *regs, long error_code) asmlinkage int do_int3(struct pt_regs *regs, long error_code)
{ {
if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
== NOTIFY_OK) == NOTIFY_STOP)
return 1; return 1;
/* This is an interrupt gate, because kprobes wants interrupts /* This is an interrupt gate, because kprobes wants interrupts
disabled. Normal trap handlers don't. */ disabled. Normal trap handlers don't. */
...@@ -707,7 +707,7 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code) ...@@ -707,7 +707,7 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
__asm__ __volatile__("movl %%db6,%0" : "=r" (condition)); __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
SIGTRAP) == NOTIFY_OK) SIGTRAP) == NOTIFY_STOP)
return; return;
/* It's safe to allow irq's after DR6 has been saved */ /* It's safe to allow irq's after DR6 has been saved */
if (regs->eflags & X86_EFLAGS_IF) if (regs->eflags & X86_EFLAGS_IF)
......
...@@ -227,7 +227,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -227,7 +227,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
__asm__("movl %%cr2,%0":"=r" (address)); __asm__("movl %%cr2,%0":"=r" (address));
if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
SIGSEGV) == NOTIFY_OK) SIGSEGV) == NOTIFY_STOP)
return; return;
/* It's safe to allow irq's after cr2 has been saved */ /* It's safe to allow irq's after cr2 has been saved */
if (regs->eflags & (X86_EFLAGS_IF|VM_MASK)) if (regs->eflags & (X86_EFLAGS_IF|VM_MASK))
......
...@@ -179,26 +179,26 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, ...@@ -179,26 +179,26 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
switch (val) { switch (val) {
case DIE_DEBUG: case DIE_DEBUG:
if (kprobe_handler(args->regs)) if (kprobe_handler(args->regs))
return NOTIFY_OK; return NOTIFY_STOP;
break; break;
case DIE_DEBUG_2: case DIE_DEBUG_2:
if (post_kprobe_handler(args->regs)) if (post_kprobe_handler(args->regs))
return NOTIFY_OK; return NOTIFY_STOP;
break; break;
case DIE_GPF: case DIE_GPF:
if (kprobe_running() && if (kprobe_running() &&
kprobe_fault_handler(args->regs, args->trapnr)) kprobe_fault_handler(args->regs, args->trapnr))
return NOTIFY_OK; return NOTIFY_STOP;
break; break;
case DIE_PAGE_FAULT: case DIE_PAGE_FAULT:
if (kprobe_running() && if (kprobe_running() &&
kprobe_fault_handler(args->regs, args->trapnr)) kprobe_fault_handler(args->regs, args->trapnr))
return NOTIFY_OK; return NOTIFY_STOP;
break; break;
default: default:
break; break;
} }
return NOTIFY_BAD; return NOTIFY_DONE;
} }
asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs) asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs)
...@@ -216,7 +216,7 @@ asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs) ...@@ -216,7 +216,7 @@ asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs)
*/ */
if (notify_die((trap_level == 0x170) ? DIE_DEBUG : DIE_DEBUG_2, if (notify_die((trap_level == 0x170) ? DIE_DEBUG : DIE_DEBUG_2,
(trap_level == 0x170) ? "debug" : "debug_2", (trap_level == 0x170) ? "debug" : "debug_2",
regs, 0, trap_level, SIGTRAP) != NOTIFY_OK) regs, 0, trap_level, SIGTRAP) != NOTIFY_STOP)
bad_trap(regs, trap_level); bad_trap(regs, trap_level);
} }
......
...@@ -96,7 +96,7 @@ void bad_trap(struct pt_regs *regs, long lvl) ...@@ -96,7 +96,7 @@ void bad_trap(struct pt_regs *regs, long lvl)
siginfo_t info; siginfo_t info;
if (notify_die(DIE_TRAP, "bad trap", regs, if (notify_die(DIE_TRAP, "bad trap", regs,
0, lvl, SIGTRAP) == NOTIFY_OK) 0, lvl, SIGTRAP) == NOTIFY_STOP)
return; return;
if (lvl < 0x100) { if (lvl < 0x100) {
...@@ -126,7 +126,7 @@ void bad_trap_tl1(struct pt_regs *regs, long lvl) ...@@ -126,7 +126,7 @@ void bad_trap_tl1(struct pt_regs *regs, long lvl)
char buffer[32]; char buffer[32];
if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs, if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs,
0, lvl, SIGTRAP) == NOTIFY_OK) 0, lvl, SIGTRAP) == NOTIFY_STOP)
return; return;
dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
...@@ -149,7 +149,7 @@ void instruction_access_exception(struct pt_regs *regs, ...@@ -149,7 +149,7 @@ void instruction_access_exception(struct pt_regs *regs,
siginfo_t info; siginfo_t info;
if (notify_die(DIE_TRAP, "instruction access exception", regs, if (notify_die(DIE_TRAP, "instruction access exception", regs,
0, 0x8, SIGTRAP) == NOTIFY_OK) 0, 0x8, SIGTRAP) == NOTIFY_STOP)
return; return;
if (regs->tstate & TSTATE_PRIV) { if (regs->tstate & TSTATE_PRIV) {
...@@ -173,7 +173,7 @@ void instruction_access_exception_tl1(struct pt_regs *regs, ...@@ -173,7 +173,7 @@ void instruction_access_exception_tl1(struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar) unsigned long sfsr, unsigned long sfar)
{ {
if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs, if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs,
0, 0x8, SIGTRAP) == NOTIFY_OK) 0, 0x8, SIGTRAP) == NOTIFY_STOP)
return; return;
dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
...@@ -186,7 +186,7 @@ void data_access_exception(struct pt_regs *regs, ...@@ -186,7 +186,7 @@ void data_access_exception(struct pt_regs *regs,
siginfo_t info; siginfo_t info;
if (notify_die(DIE_TRAP, "data access exception", regs, if (notify_die(DIE_TRAP, "data access exception", regs,
0, 0x30, SIGTRAP) == NOTIFY_OK) 0, 0x30, SIGTRAP) == NOTIFY_STOP)
return; return;
if (regs->tstate & TSTATE_PRIV) { if (regs->tstate & TSTATE_PRIV) {
...@@ -260,7 +260,7 @@ void do_iae(struct pt_regs *regs) ...@@ -260,7 +260,7 @@ void do_iae(struct pt_regs *regs)
spitfire_clean_and_reenable_l1_caches(); spitfire_clean_and_reenable_l1_caches();
if (notify_die(DIE_TRAP, "instruction access exception", regs, if (notify_die(DIE_TRAP, "instruction access exception", regs,
0, 0x8, SIGTRAP) == NOTIFY_OK) 0, 0x8, SIGTRAP) == NOTIFY_STOP)
return; return;
info.si_signo = SIGBUS; info.si_signo = SIGBUS;
...@@ -292,7 +292,7 @@ void do_dae(struct pt_regs *regs) ...@@ -292,7 +292,7 @@ void do_dae(struct pt_regs *regs)
spitfire_clean_and_reenable_l1_caches(); spitfire_clean_and_reenable_l1_caches();
if (notify_die(DIE_TRAP, "data access exception", regs, if (notify_die(DIE_TRAP, "data access exception", regs,
0, 0x30, SIGTRAP) == NOTIFY_OK) 0, 0x30, SIGTRAP) == NOTIFY_STOP)
return; return;
info.si_signo = SIGBUS; info.si_signo = SIGBUS;
...@@ -1695,7 +1695,7 @@ void do_fpe_common(struct pt_regs *regs) ...@@ -1695,7 +1695,7 @@ void do_fpe_common(struct pt_regs *regs)
void do_fpieee(struct pt_regs *regs) void do_fpieee(struct pt_regs *regs)
{ {
if (notify_die(DIE_TRAP, "fpu exception ieee", regs, if (notify_die(DIE_TRAP, "fpu exception ieee", regs,
0, 0x24, SIGFPE) == NOTIFY_OK) 0, 0x24, SIGFPE) == NOTIFY_STOP)
return; return;
do_fpe_common(regs); do_fpe_common(regs);
...@@ -1709,7 +1709,7 @@ void do_fpother(struct pt_regs *regs) ...@@ -1709,7 +1709,7 @@ void do_fpother(struct pt_regs *regs)
int ret = 0; int ret = 0;
if (notify_die(DIE_TRAP, "fpu exception other", regs, if (notify_die(DIE_TRAP, "fpu exception other", regs,
0, 0x25, SIGFPE) == NOTIFY_OK) 0, 0x25, SIGFPE) == NOTIFY_STOP)
return; return;
switch ((current_thread_info()->xfsr[0] & 0x1c000)) { switch ((current_thread_info()->xfsr[0] & 0x1c000)) {
...@@ -1728,7 +1728,7 @@ void do_tof(struct pt_regs *regs) ...@@ -1728,7 +1728,7 @@ void do_tof(struct pt_regs *regs)
siginfo_t info; siginfo_t info;
if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs, if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs,
0, 0x26, SIGEMT) == NOTIFY_OK) 0, 0x26, SIGEMT) == NOTIFY_STOP)
return; return;
if (regs->tstate & TSTATE_PRIV) if (regs->tstate & TSTATE_PRIV)
...@@ -1750,7 +1750,7 @@ void do_div0(struct pt_regs *regs) ...@@ -1750,7 +1750,7 @@ void do_div0(struct pt_regs *regs)
siginfo_t info; siginfo_t info;
if (notify_die(DIE_TRAP, "integer division by zero", regs, if (notify_die(DIE_TRAP, "integer division by zero", regs,
0, 0x28, SIGFPE) == NOTIFY_OK) 0, 0x28, SIGFPE) == NOTIFY_STOP)
return; return;
if (regs->tstate & TSTATE_PRIV) if (regs->tstate & TSTATE_PRIV)
...@@ -1936,7 +1936,7 @@ void do_illegal_instruction(struct pt_regs *regs) ...@@ -1936,7 +1936,7 @@ void do_illegal_instruction(struct pt_regs *regs)
siginfo_t info; siginfo_t info;
if (notify_die(DIE_TRAP, "illegal instruction", regs, if (notify_die(DIE_TRAP, "illegal instruction", regs,
0, 0x10, SIGILL) == NOTIFY_OK) 0, 0x10, SIGILL) == NOTIFY_STOP)
return; return;
if (tstate & TSTATE_PRIV) if (tstate & TSTATE_PRIV)
...@@ -1965,7 +1965,7 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo ...@@ -1965,7 +1965,7 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo
siginfo_t info; siginfo_t info;
if (notify_die(DIE_TRAP, "memory address unaligned", regs, if (notify_die(DIE_TRAP, "memory address unaligned", regs,
0, 0x34, SIGSEGV) == NOTIFY_OK) 0, 0x34, SIGSEGV) == NOTIFY_STOP)
return; return;
if (regs->tstate & TSTATE_PRIV) { if (regs->tstate & TSTATE_PRIV) {
...@@ -1991,7 +1991,7 @@ void do_privop(struct pt_regs *regs) ...@@ -1991,7 +1991,7 @@ void do_privop(struct pt_regs *regs)
siginfo_t info; siginfo_t info;
if (notify_die(DIE_TRAP, "privileged operation", regs, if (notify_die(DIE_TRAP, "privileged operation", regs,
0, 0x11, SIGILL) == NOTIFY_OK) 0, 0x11, SIGILL) == NOTIFY_STOP)
return; return;
if (test_thread_flag(TIF_32BIT)) { if (test_thread_flag(TIF_32BIT)) {
......
...@@ -149,7 +149,7 @@ static void unhandled_fault(unsigned long address, struct task_struct *tsk, ...@@ -149,7 +149,7 @@ static void unhandled_fault(unsigned long address, struct task_struct *tsk,
(tsk->mm ? (unsigned long) tsk->mm->pgd : (tsk->mm ? (unsigned long) tsk->mm->pgd :
(unsigned long) tsk->active_mm->pgd)); (unsigned long) tsk->active_mm->pgd));
if (notify_die(DIE_GPF, "general protection fault", regs, if (notify_die(DIE_GPF, "general protection fault", regs,
0, 0, SIGSEGV) == NOTIFY_OK) 0, 0, SIGSEGV) == NOTIFY_STOP)
return; return;
die_if_kernel("Oops", regs); die_if_kernel("Oops", regs);
} }
...@@ -325,7 +325,7 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs) ...@@ -325,7 +325,7 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs)
fault_code = get_thread_fault_code(); fault_code = get_thread_fault_code();
if (notify_die(DIE_PAGE_FAULT, "page_fault", regs, if (notify_die(DIE_PAGE_FAULT, "page_fault", regs,
fault_code, 0, SIGSEGV) == NOTIFY_OK) fault_code, 0, SIGSEGV) == NOTIFY_STOP)
return; return;
si_code = SEGV_MAPERR; si_code = SEGV_MAPERR;
......
...@@ -390,7 +390,8 @@ void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason) ...@@ -390,7 +390,8 @@ void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
*/ */
alert_counter[cpu]++; alert_counter[cpu]++;
if (alert_counter[cpu] == 5*nmi_hz) { if (alert_counter[cpu] == 5*nmi_hz) {
if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_BAD) { if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
== NOTIFY_STOP) {
alert_counter[cpu] = 0; alert_counter[cpu] = 0;
return; return;
} }
......
...@@ -437,7 +437,8 @@ static void do_trap(int trapnr, int signr, char *str, ...@@ -437,7 +437,8 @@ static void do_trap(int trapnr, int signr, char *str,
#define DO_ERROR(trapnr, signr, str, name) \ #define DO_ERROR(trapnr, signr, str, name) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
{ \ { \
if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
== NOTIFY_STOP) \
return; \ return; \
do_trap(trapnr, signr, str, regs, error_code, NULL); \ do_trap(trapnr, signr, str, regs, error_code, NULL); \
} }
...@@ -450,7 +451,8 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ ...@@ -450,7 +451,8 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
info.si_errno = 0; \ info.si_errno = 0; \
info.si_code = sicode; \ info.si_code = sicode; \
info.si_addr = (void __user *)siaddr; \ info.si_addr = (void __user *)siaddr; \
if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
== NOTIFY_STOP) \
return; \ return; \
do_trap(trapnr, signr, str, regs, error_code, &info); \ do_trap(trapnr, signr, str, regs, error_code, &info); \
} }
...@@ -471,7 +473,8 @@ DO_ERROR(18, SIGSEGV, "reserved", reserved) ...@@ -471,7 +473,8 @@ DO_ERROR(18, SIGSEGV, "reserved", reserved)
asmlinkage void *do_##name(struct pt_regs * regs, long error_code) \ asmlinkage void *do_##name(struct pt_regs * regs, long error_code) \
{ \ { \
struct pt_regs *pr = ((struct pt_regs *)(current->thread.rsp0))-1; \ struct pt_regs *pr = ((struct pt_regs *)(current->thread.rsp0))-1; \
if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
== NOTIFY_STOP) \
return regs; \ return regs; \
if (regs->cs & 3) { \ if (regs->cs & 3) { \
memcpy(pr, regs, sizeof(struct pt_regs)); \ memcpy(pr, regs, sizeof(struct pt_regs)); \
...@@ -565,7 +568,8 @@ asmlinkage void default_do_nmi(struct pt_regs * regs) ...@@ -565,7 +568,8 @@ asmlinkage void default_do_nmi(struct pt_regs * regs)
unsigned char reason = inb(0x61); unsigned char reason = inb(0x61);
if (!(reason & 0xc0)) { if (!(reason & 0xc0)) {
if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT) == NOTIFY_BAD) if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
== NOTIFY_STOP)
return; return;
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
/* /*
...@@ -580,7 +584,7 @@ asmlinkage void default_do_nmi(struct pt_regs * regs) ...@@ -580,7 +584,7 @@ asmlinkage void default_do_nmi(struct pt_regs * regs)
unknown_nmi_error(reason, regs); unknown_nmi_error(reason, regs);
return; return;
} }
if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_BAD) if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP)
return; return;
if (reason & 0x80) if (reason & 0x80)
mem_parity_error(reason, regs); mem_parity_error(reason, regs);
...@@ -676,7 +680,7 @@ asmlinkage void *do_debug(struct pt_regs * regs, unsigned long error_code) ...@@ -676,7 +680,7 @@ asmlinkage void *do_debug(struct pt_regs * regs, unsigned long error_code)
clear_TF: clear_TF:
/* RED-PEN could cause spurious errors */ /* RED-PEN could cause spurious errors */
if (notify_die(DIE_DEBUG, "debug2", regs, condition, 1, SIGTRAP) if (notify_die(DIE_DEBUG, "debug2", regs, condition, 1, SIGTRAP)
!= NOTIFY_BAD) != NOTIFY_STOP)
regs->eflags &= ~TF_MASK; regs->eflags &= ~TF_MASK;
return regs; return regs;
} }
......
...@@ -29,6 +29,10 @@ extern int notifier_call_chain(struct notifier_block **n, unsigned long val, voi ...@@ -29,6 +29,10 @@ extern int notifier_call_chain(struct notifier_block **n, unsigned long val, voi
#define NOTIFY_OK 0x0001 /* Suits me */ #define NOTIFY_OK 0x0001 /* Suits me */
#define NOTIFY_STOP_MASK 0x8000 /* Don't call further */ #define NOTIFY_STOP_MASK 0x8000 /* Don't call further */
#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002) /* Bad/Veto action */ #define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002) /* Bad/Veto action */
/*
* Clean way to return from the notifier and stop further calls.
*/
#define NOTIFY_STOP (NOTIFY_OK|NOTIFY_STOP_MASK)
/* /*
* Declared notifiers so far. I can imagine quite a few more chains * Declared notifiers so far. I can imagine quite a few more chains
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
* hlists and exceptions notifier as suggested by Andi Kleen. * hlists and exceptions notifier as suggested by Andi Kleen.
* 2004-July Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes * 2004-July Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
* interface to access function arguments. * interface to access function arguments.
* 2004-Sep Prasanna S Panchamukhi <prasanna@in.ibm.com> Changed Kprobes
* exceptions notifier to be first on the priority list.
*/ */
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -108,6 +110,7 @@ void unregister_kprobe(struct kprobe *p) ...@@ -108,6 +110,7 @@ void unregister_kprobe(struct kprobe *p)
static struct notifier_block kprobe_exceptions_nb = { static struct notifier_block kprobe_exceptions_nb = {
.notifier_call = kprobe_exceptions_notify, .notifier_call = kprobe_exceptions_notify,
.priority = 0x7fffffff /* we need to notified first */
}; };
int register_jprobe(struct jprobe *jp) int register_jprobe(struct jprobe *jp)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment