public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [Patch] kprobes exception notifier fix 2.6.9-rc2
@ 2004-09-23  5:30 Prasanna S Panchamukhi
  2004-09-23  8:06 ` Andi Kleen
  0 siblings, 1 reply; 5+ messages in thread
From: Prasanna S Panchamukhi @ 2004-09-23  5:30 UTC (permalink / raw)
  To: linux-kernel
  Cc: torvalds, Andrew Morton, ak, suparna, Tom Rini, kgdb-bugreport

[-- Attachment #1: Type: text/plain, Size: 387 bytes --]

In order to make other debuggers use exception notifiers, kprobes 
notifier return values are required to be modified. This patch modifies the
return values of kprobes notifier return values in a clean way.

Please let me know your comments.

Thanks
Prasanna
-- 

Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<prasanna@in.ibm.com>

[-- Attachment #2: kprobes-exceptions-notifier-fix.patch --]
[-- Type: text/plain, Size: 7302 bytes --]


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 : Prasanna S Panchamukhi <prasanna@in.ibm.com>


---

 linux-2.6.9-rc2-prasanna/arch/i386/kernel/kprobes.c |   10 +++++-----
 linux-2.6.9-rc2-prasanna/arch/i386/kernel/traps.c   |   18 +++++++++---------
 linux-2.6.9-rc2-prasanna/arch/i386/mm/fault.c       |    2 +-
 linux-2.6.9-rc2-prasanna/include/linux/notifier.h   |    4 ++++
 linux-2.6.9-rc2-prasanna/kernel/kprobes.c           |    3 +++
 5 files changed, 22 insertions(+), 15 deletions(-)

diff -puN arch/i386/kernel/kprobes.c~kprobes-exceptions-nofitier-fix arch/i386/kernel/kprobes.c
--- linux-2.6.9-rc2/arch/i386/kernel/kprobes.c~kprobes-exceptions-nofitier-fix	2004-09-21 15:06:22.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/arch/i386/kernel/kprobes.c	2004-09-21 15:06:22.000000000 +0530
@@ -267,26 +267,26 @@ int kprobe_exceptions_notify(struct noti
 	switch (val) {
 	case DIE_INT3:
 		if (kprobe_handler(args->regs))
-			return NOTIFY_OK;
+			return NOTIFY_STOP;
 		break;
 	case DIE_DEBUG:
 		if (post_kprobe_handler(args->regs))
-			return NOTIFY_OK;
+			return NOTIFY_STOP;
 		break;
 	case DIE_GPF:
 		if (kprobe_running() &&
 		    kprobe_fault_handler(args->regs, args->trapnr))
-			return NOTIFY_OK;
+			return NOTIFY_STOP;
 		break;
 	case DIE_PAGE_FAULT:
 		if (kprobe_running() &&
 		    kprobe_fault_handler(args->regs, args->trapnr))
-			return NOTIFY_OK;
+			return NOTIFY_STOP;
 		break;
 	default:
 		break;
 	}
-	return NOTIFY_BAD;
+	return NOTIFY_DONE;
 }
 
 int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
diff -puN arch/i386/kernel/traps.c~kprobes-exceptions-nofitier-fix arch/i386/kernel/traps.c
--- linux-2.6.9-rc2/arch/i386/kernel/traps.c~kprobes-exceptions-nofitier-fix	2004-09-21 15:06:22.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/arch/i386/kernel/traps.c	2004-09-21 15:06:22.000000000 +0530
@@ -422,7 +422,7 @@ static inline void do_trap(int trapnr, i
 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 { \
 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
-						== NOTIFY_OK) \
+						== NOTIFY_STOP) \
 		return; \
 	do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
 }
@@ -436,7 +436,7 @@ asmlinkage void do_##name(struct pt_regs
 	info.si_code = sicode; \
 	info.si_addr = (void __user *)siaddr; \
 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
-						== NOTIFY_BAD) \
+						== NOTIFY_STOP) \
 		return; \
 	do_trap(trapnr, signr, str, 0, regs, error_code, &info); \
 }
@@ -445,7 +445,7 @@ asmlinkage void do_##name(struct pt_regs
 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 { \
 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
-						== NOTIFY_OK) \
+						== NOTIFY_STOP) \
 		return; \
 	do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
 }
@@ -459,7 +459,7 @@ asmlinkage void do_##name(struct pt_regs
 	info.si_code = sicode; \
 	info.si_addr = (void __user *)siaddr; \
 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
-						== NOTIFY_OK) \
+						== NOTIFY_STOP) \
 		return; \
 	do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
 }
@@ -498,7 +498,7 @@ gp_in_vm86:
 gp_in_kernel:
 	if (!fixup_exception(regs)) {
 		if (notify_die(DIE_GPF, "general protection fault", regs,
-				error_code, 13, SIGSEGV) == NOTIFY_OK);
+				error_code, 13, SIGSEGV) == NOTIFY_STOP);
 			return;
 		die("general protection fault", regs, error_code);
 	}
@@ -572,7 +572,7 @@ static void default_do_nmi(struct pt_reg
  
 	if (!(reason & 0xc0)) {
 		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
-							== NOTIFY_BAD)
+							== NOTIFY_STOP)
 			return;
 #ifdef CONFIG_X86_LOCAL_APIC
 		/*
@@ -587,7 +587,7 @@ static void default_do_nmi(struct pt_reg
 		unknown_nmi_error(reason, regs);
 		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;
 	if (reason & 0x80)
 		mem_parity_error(reason, regs);
@@ -636,7 +636,7 @@ void unset_nmi_callback(void)
 asmlinkage int do_int3(struct pt_regs *regs, long error_code)
 {
 	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
-			== NOTIFY_OK)
+			== NOTIFY_STOP)
 		return 1;
 	/* This is an interrupt gate, because kprobes wants interrupts
 	disabled.  Normal trap handlers don't. */
@@ -677,7 +677,7 @@ asmlinkage void do_debug(struct pt_regs 
 	__asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
 
 	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
-					SIGTRAP) == NOTIFY_OK)
+					SIGTRAP) == NOTIFY_STOP)
 		return;
 	/* It's safe to allow irq's after DR6 has been saved */
 	if (regs->eflags & X86_EFLAGS_IF)
diff -puN arch/i386/mm/fault.c~kprobes-exceptions-nofitier-fix arch/i386/mm/fault.c
--- linux-2.6.9-rc2/arch/i386/mm/fault.c~kprobes-exceptions-nofitier-fix	2004-09-21 15:06:22.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/arch/i386/mm/fault.c	2004-09-21 15:06:22.000000000 +0530
@@ -227,7 +227,7 @@ asmlinkage void do_page_fault(struct pt_
 	__asm__("movl %%cr2,%0":"=r" (address));
 
 	if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
-					SIGSEGV) == NOTIFY_OK)
+					SIGSEGV) == NOTIFY_STOP)
 		return;
 	/* It's safe to allow irq's after cr2 has been saved */
 	if (regs->eflags & (X86_EFLAGS_IF|VM_MASK))
diff -puN kernel/kprobes.c~kprobes-exceptions-nofitier-fix kernel/kprobes.c
--- linux-2.6.9-rc2/kernel/kprobes.c~kprobes-exceptions-nofitier-fix	2004-09-21 15:06:22.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/kernel/kprobes.c	2004-09-21 15:06:22.000000000 +0530
@@ -25,6 +25,8 @@
  *		hlists and exceptions notifier as suggested by Andi Kleen.
  * 2004-July	Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
  *		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/spinlock.h>
@@ -108,6 +110,7 @@ void unregister_kprobe(struct kprobe *p)
 
 static struct notifier_block kprobe_exceptions_nb = {
 	.notifier_call = kprobe_exceptions_notify,
+	.priority = 0x7fffffff /* we need to notified first */
 };
 
 int register_jprobe(struct jprobe *jp)
diff -puN include/linux/notifier.h~kprobes-exceptions-nofitier-fix include/linux/notifier.h
--- linux-2.6.9-rc2/include/linux/notifier.h~kprobes-exceptions-nofitier-fix	2004-09-21 15:06:22.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/include/linux/notifier.h	2004-09-21 15:07:21.000000000 +0530
@@ -29,6 +29,10 @@ extern int notifier_call_chain(struct no
 #define NOTIFY_OK		0x0001		/* Suits me */
 #define NOTIFY_STOP_MASK	0x8000		/* Don't call further */
 #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

_

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch] kprobes exception notifier fix 2.6.9-rc2
  2004-09-23  5:30 [Patch] kprobes exception notifier fix 2.6.9-rc2 Prasanna S Panchamukhi
@ 2004-09-23  8:06 ` Andi Kleen
  2004-09-23  8:45   ` Prasanna S Panchamukhi
  2004-09-23 19:32   ` David S. Miller
  0 siblings, 2 replies; 5+ messages in thread
From: Andi Kleen @ 2004-09-23  8:06 UTC (permalink / raw)
  To: Prasanna S Panchamukhi
  Cc: linux-kernel, torvalds, Andrew Morton, suparna, Tom Rini,
	kgdb-bugreport

On Thu, Sep 23, 2004 at 11:00:29AM +0530, Prasanna S Panchamukhi wrote:
> In order to make other debuggers use exception notifiers, kprobes 
> notifier return values are required to be modified. This patch modifies the
> return values of kprobes notifier return values in a clean way.

It's incompatible to x86-64. If you change anything in exception
notifiers change both.

And I don't really see the sense of inverting the test: NOTIFY_OK
for handling the exception should be as good as NOTIFY_STOP.

-Andi

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch] kprobes exception notifier fix 2.6.9-rc2
  2004-09-23  8:06 ` Andi Kleen
@ 2004-09-23  8:45   ` Prasanna S Panchamukhi
  2004-09-23 19:32   ` David S. Miller
  1 sibling, 0 replies; 5+ messages in thread
From: Prasanna S Panchamukhi @ 2004-09-23  8:45 UTC (permalink / raw)
  To: Andi Kleen
  Cc: linux-kernel, torvalds, Andrew Morton, suparna, Tom Rini,
	kgdb-bugreport

Hi Andi,

On Thu, Sep 23, 2004 at 10:06:28AM +0200, Andi Kleen wrote:
> On Thu, Sep 23, 2004 at 11:00:29AM +0530, Prasanna S Panchamukhi wrote:
> > In order to make other debuggers use exception notifiers, kprobes 
> > notifier return values are required to be modified. This patch modifies the
> > return values of kprobes notifier return values in a clean way.
> 
> It's incompatible to x86-64. If you change anything in exception
> notifiers change both.
> 

Yes, I will make the changes to x86_64 exception notifiers as well and
send a patch to you.

> And I don't really see the sense of inverting the test: NOTIFY_OK
> for handling the exception should be as good as NOTIFY_STOP.
> 

NOTIFY_OK does not stop notifying others registered for the same event.
This was causing problems when Kprobes and KGDB co-exist and KGDB handler
would get involked, when kprobes handler would have already handled its own
breakpoint. NOTIFY_BAD will also work, but returning NOTIFY_BAD would mean 
Bad/Veto action. This patch solves the problem by returning NOTIFY_OK | NOTIFY_STOP_MASK in a clean way.

Please let me know your comments.

Thanks
Prasanna

> -Andi

-- 
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<prasanna@in.ibm.com>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch] kprobes exception notifier fix 2.6.9-rc2
  2004-09-23  8:06 ` Andi Kleen
  2004-09-23  8:45   ` Prasanna S Panchamukhi
@ 2004-09-23 19:32   ` David S. Miller
  2004-09-27 12:10     ` Prasanna S Panchamukhi
  1 sibling, 1 reply; 5+ messages in thread
From: David S. Miller @ 2004-09-23 19:32 UTC (permalink / raw)
  To: Andi Kleen
  Cc: prasanna, linux-kernel, torvalds, akpm, suparna, trini,
	kgdb-bugreport

On 23 Sep 2004 10:06:28 +0200
Andi Kleen <ak@muc.de> wrote:

> On Thu, Sep 23, 2004 at 11:00:29AM +0530, Prasanna S Panchamukhi wrote:
> > In order to make other debuggers use exception notifiers, kprobes 
> > notifier return values are required to be modified. This patch modifies the
> > return values of kprobes notifier return values in a clean way.
> 
> It's incompatible to x86-64. If you change anything in exception
> notifiers change both.

And please change sparc64 as well, as it has the same exception
notification implemented there as well.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch] kprobes exception notifier fix 2.6.9-rc2
  2004-09-23 19:32   ` David S. Miller
@ 2004-09-27 12:10     ` Prasanna S Panchamukhi
  0 siblings, 0 replies; 5+ messages in thread
From: Prasanna S Panchamukhi @ 2004-09-27 12:10 UTC (permalink / raw)
  To: David S. Miller
  Cc: Andi Kleen, linux-kernel, torvalds, akpm, suparna, trini,
	kgdb-bugreport

[-- Attachment #1: Type: text/plain, Size: 1149 bytes --]

Hi,

As per Andi and David's request, I have updated exception notifiers for x86_64
and sparc64. This patch can been applied over linux-2.6.9-rc2-mm4. 
Also KGDB exception notifier handler for x86_64 and 
kprobes notifier handler for sparc64 have been updated. 
I have only tested this patch on i386 architecture.

Please let me know if you have any issues.

Thanks
Prasanna

On Thu, Sep 23, 2004 at 12:32:50PM -0700, David S. Miller wrote:
> On 23 Sep 2004 10:06:28 +0200
> Andi Kleen <ak@muc.de> wrote:
> 
> > On Thu, Sep 23, 2004 at 11:00:29AM +0530, Prasanna S Panchamukhi wrote:
> > > In order to make other debuggers use exception notifiers, kprobes 
> > > notifier return values are required to be modified. This patch modifies the
> > > return values of kprobes notifier return values in a clean way.
> > 
> > It's incompatible to x86-64. If you change anything in exception
> > notifiers change both.
> 
> And please change sparc64 as well, as it has the same exception
> notification implemented there as well.

-- 
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<prasanna@in.ibm.com>

[-- Attachment #2: kprobes-exceptions-notifier-fix.patch --]
[-- Type: text/plain, Size: 18169 bytes --]


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 : Prasanna S Panchamukhi <prasanna@in.ibm.com>

---

---



---

 linux-2.6.9-rc2-prasanna/arch/i386/kernel/kprobes.c     |   10 ++---
 linux-2.6.9-rc2-prasanna/arch/i386/kernel/traps.c       |   18 +++++-----
 linux-2.6.9-rc2-prasanna/arch/i386/mm/fault.c           |    2 -
 linux-2.6.9-rc2-prasanna/arch/sparc64/kernel/kprobes.c  |   12 +++---
 linux-2.6.9-rc2-prasanna/arch/sparc64/kernel/traps.c    |   28 ++++++++--------
 linux-2.6.9-rc2-prasanna/arch/sparc64/mm/fault.c        |    4 +-
 linux-2.6.9-rc2-prasanna/arch/x86_64/kernel/kgdb_stub.c |    4 +-
 linux-2.6.9-rc2-prasanna/arch/x86_64/kernel/nmi.c       |    3 +
 linux-2.6.9-rc2-prasanna/arch/x86_64/kernel/traps.c     |   16 +++++----
 linux-2.6.9-rc2-prasanna/include/linux/notifier.h       |    4 ++
 linux-2.6.9-rc2-prasanna/kernel/kprobes.c               |    3 +
 11 files changed, 58 insertions(+), 46 deletions(-)

diff -puN arch/i386/kernel/kprobes.c~kprobes-exceptions-notifier-fix arch/i386/kernel/kprobes.c
--- linux-2.6.9-rc2/arch/i386/kernel/kprobes.c~kprobes-exceptions-notifier-fix	2004-09-27 11:55:57.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/arch/i386/kernel/kprobes.c	2004-09-27 11:55:57.000000000 +0530
@@ -267,26 +267,26 @@ int kprobe_exceptions_notify(struct noti
 	switch (val) {
 	case DIE_INT3:
 		if (kprobe_handler(args->regs))
-			return NOTIFY_OK;
+			return NOTIFY_STOP;
 		break;
 	case DIE_DEBUG:
 		if (post_kprobe_handler(args->regs))
-			return NOTIFY_OK;
+			return NOTIFY_STOP;
 		break;
 	case DIE_GPF:
 		if (kprobe_running() &&
 		    kprobe_fault_handler(args->regs, args->trapnr))
-			return NOTIFY_OK;
+			return NOTIFY_STOP;
 		break;
 	case DIE_PAGE_FAULT:
 		if (kprobe_running() &&
 		    kprobe_fault_handler(args->regs, args->trapnr))
-			return NOTIFY_OK;
+			return NOTIFY_STOP;
 		break;
 	default:
 		break;
 	}
-	return NOTIFY_BAD;
+	return NOTIFY_DONE;
 }
 
 int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
diff -puN arch/i386/kernel/traps.c~kprobes-exceptions-notifier-fix arch/i386/kernel/traps.c
--- linux-2.6.9-rc2/arch/i386/kernel/traps.c~kprobes-exceptions-notifier-fix	2004-09-27 11:55:57.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/arch/i386/kernel/traps.c	2004-09-27 11:55:57.000000000 +0530
@@ -464,7 +464,7 @@ asmlinkage void do_##name(struct pt_regs
 { \
 	CHK_REMOTE_DEBUG(trapnr,signr,error_code,regs,) \
 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
-						== NOTIFY_OK) \
+						== NOTIFY_STOP) \
 		return; \
 	do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
 }
@@ -478,7 +478,7 @@ asmlinkage void do_##name(struct pt_regs
 	info.si_code = sicode; \
 	info.si_addr = (void __user *)siaddr; \
 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
-						== NOTIFY_BAD) \
+						== NOTIFY_STOP) \
 		return; \
 	do_trap(trapnr, signr, str, 0, regs, error_code, &info); \
 }
@@ -488,7 +488,7 @@ asmlinkage void do_##name(struct pt_regs
 { \
 	CHK_REMOTE_DEBUG(trapnr, signr, error_code,regs, return) \
 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
-						== NOTIFY_OK) \
+						== NOTIFY_STOP) \
 		return; \
 	do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
 }
@@ -502,7 +502,7 @@ asmlinkage void do_##name(struct pt_regs
 	info.si_code = sicode; \
 	info.si_addr = (void __user *)siaddr; \
 	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
-						== NOTIFY_OK) \
+						== NOTIFY_STOP) \
 		return; \
 	do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
 }
@@ -572,7 +572,7 @@ gp_in_kernel:
 	if (!fixup_exception(regs)) {
  		CHK_REMOTE_DEBUG(13,SIGSEGV,error_code,regs,)
 		if (notify_die(DIE_GPF, "general protection fault", regs,
-				error_code, 13, SIGSEGV) == NOTIFY_OK);
+				error_code, 13, SIGSEGV) == NOTIFY_STOP);
 			return;
 		die("general protection fault", regs, error_code);
 	}
@@ -646,7 +646,7 @@ static void default_do_nmi(struct pt_reg
  
 	if (!(reason & 0xc0)) {
 		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
-							== NOTIFY_BAD)
+							== NOTIFY_STOP)
 			return;
 #ifdef CONFIG_X86_LOCAL_APIC
 		/*
@@ -661,7 +661,7 @@ static void default_do_nmi(struct pt_reg
 		unknown_nmi_error(reason, regs);
 		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;
 	if (reason & 0x80)
 		mem_parity_error(reason, regs);
@@ -718,7 +718,7 @@ void unset_nmi_callback(void)
 asmlinkage int do_int3(struct pt_regs *regs, long error_code)
 {
 	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
-			== NOTIFY_OK)
+			== NOTIFY_STOP)
 		return 1;
 	/* This is an interrupt gate, because kprobes wants interrupts
 	disabled.  Normal trap handlers don't. */
@@ -759,7 +759,7 @@ asmlinkage void do_debug(struct pt_regs 
 	__asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
 
 	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
-					SIGTRAP) == NOTIFY_OK)
+					SIGTRAP) == NOTIFY_STOP)
 		return;
 	/* It's safe to allow irq's after DR6 has been saved */
 	if (regs->eflags & X86_EFLAGS_IF)
diff -puN arch/i386/mm/fault.c~kprobes-exceptions-notifier-fix arch/i386/mm/fault.c
--- linux-2.6.9-rc2/arch/i386/mm/fault.c~kprobes-exceptions-notifier-fix	2004-09-27 11:55:57.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/arch/i386/mm/fault.c	2004-09-27 11:55:57.000000000 +0530
@@ -227,7 +227,7 @@ asmlinkage void do_page_fault(struct pt_
 	__asm__("movl %%cr2,%0":"=r" (address));
 
 	if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
-					SIGSEGV) == NOTIFY_OK)
+					SIGSEGV) == NOTIFY_STOP)
 		return;
 	/* It's safe to allow irq's after cr2 has been saved */
 	if (regs->eflags & (X86_EFLAGS_IF|VM_MASK))
diff -puN include/linux/notifier.h~kprobes-exceptions-notifier-fix include/linux/notifier.h
--- linux-2.6.9-rc2/include/linux/notifier.h~kprobes-exceptions-notifier-fix	2004-09-27 11:55:57.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/include/linux/notifier.h	2004-09-27 11:55:57.000000000 +0530
@@ -29,6 +29,10 @@ extern int notifier_call_chain(struct no
 #define NOTIFY_OK		0x0001		/* Suits me */
 #define NOTIFY_STOP_MASK	0x8000		/* Don't call further */
 #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
diff -puN kernel/kprobes.c~kprobes-exceptions-notifier-fix kernel/kprobes.c
--- linux-2.6.9-rc2/kernel/kprobes.c~kprobes-exceptions-notifier-fix	2004-09-27 11:55:57.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/kernel/kprobes.c	2004-09-27 11:55:57.000000000 +0530
@@ -25,6 +25,8 @@
  *		hlists and exceptions notifier as suggested by Andi Kleen.
  * 2004-July	Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
  *		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/spinlock.h>
@@ -108,6 +110,7 @@ void unregister_kprobe(struct kprobe *p)
 
 static struct notifier_block kprobe_exceptions_nb = {
 	.notifier_call = kprobe_exceptions_notify,
+	.priority = 0x7fffffff /* we need to notified first */
 };
 
 int register_jprobe(struct jprobe *jp)
diff -puN arch/x86_64/kernel/traps.c~kprobes-exceptions-notifier-fix arch/x86_64/kernel/traps.c
--- linux-2.6.9-rc2/arch/x86_64/kernel/traps.c~kprobes-exceptions-notifier-fix	2004-09-27 11:55:57.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/arch/x86_64/kernel/traps.c	2004-09-27 11:55:57.000000000 +0530
@@ -440,7 +440,8 @@ static void do_trap(int trapnr, int sign
 #define DO_ERROR(trapnr, signr, str, name) \
 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; \
 	do_trap(trapnr, signr, str, regs, error_code, NULL); \
 }
@@ -453,7 +454,8 @@ asmlinkage void do_##name(struct pt_regs
 	info.si_errno = 0; \
 	info.si_code = sicode; \
 	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; \
 	do_trap(trapnr, signr, str, regs, error_code, &info); \
 }
@@ -474,7 +476,8 @@ DO_ERROR(18, SIGSEGV, "reserved", reserv
 asmlinkage void *do_##name(struct pt_regs * regs, long error_code) \
 { \
 	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; \
 	if (regs->cs & 3) { \
 		memcpy(pr, regs, sizeof(struct pt_regs)); \
@@ -568,7 +571,8 @@ asmlinkage void default_do_nmi(struct pt
 	unsigned char reason = inb(0x61);
 
 	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;
 #ifdef CONFIG_X86_LOCAL_APIC
 		/*
@@ -583,7 +587,7 @@ asmlinkage void default_do_nmi(struct pt
 		unknown_nmi_error(reason, regs);
 		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; 
 	if (reason & 0x80)
 		mem_parity_error(reason, regs);
@@ -679,7 +683,7 @@ clear_TF_reenable:
 clear_TF:
 	/* RED-PEN could cause spurious errors */
 	if (notify_die(DIE_DEBUG, "debug2", regs, condition, 1, SIGTRAP) 
-	    != NOTIFY_BAD)
+								!= NOTIFY_STOP)
 	regs->eflags &= ~TF_MASK;
 	return regs;	
 }
diff -puN arch/x86_64/kernel/nmi.c~kprobes-exceptions-notifier-fix arch/x86_64/kernel/nmi.c
--- linux-2.6.9-rc2/arch/x86_64/kernel/nmi.c~kprobes-exceptions-notifier-fix	2004-09-27 11:55:57.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/arch/x86_64/kernel/nmi.c	2004-09-27 11:55:57.000000000 +0530
@@ -390,7 +390,8 @@ void nmi_watchdog_tick (struct pt_regs *
 		 */
 		alert_counter[cpu]++;
 		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; 
 				return;
 			} 
diff -puN arch/x86_64/kernel/kgdb_stub.c~kprobes-exceptions-notifier-fix arch/x86_64/kernel/kgdb_stub.c
--- linux-2.6.9-rc2/arch/x86_64/kernel/kgdb_stub.c~kprobes-exceptions-notifier-fix	2004-09-27 11:55:57.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/arch/x86_64/kernel/kgdb_stub.c	2004-09-27 11:55:57.000000000 +0530
@@ -2197,9 +2197,9 @@ static int kgdb_notify(struct notifier_b
 		return NOTIFY_DONE;
 	if (cmd == DIE_NMI_IPI) {
 		if (in_kgdb(d->regs))
-			return NOTIFY_BAD;
+			return NOTIFY_STOP;
 	} else if (kgdb_handle_exception(d->trapnr, d->signr, d->err, d->regs))
-		return NOTIFY_BAD; /* skip */
+		return NOTIFY_STOP; /* skip */
 
 	return NOTIFY_DONE;
 }
diff -puN arch/sparc64/kernel/kprobes.c~kprobes-exceptions-notifier-fix arch/sparc64/kernel/kprobes.c
--- linux-2.6.9-rc2/arch/sparc64/kernel/kprobes.c~kprobes-exceptions-notifier-fix	2004-09-27 11:55:57.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/arch/sparc64/kernel/kprobes.c	2004-09-27 11:55:57.000000000 +0530
@@ -179,26 +179,26 @@ int kprobe_exceptions_notify(struct noti
 	switch (val) {
 	case DIE_DEBUG:
 		if (kprobe_handler(args->regs))
-			return NOTIFY_OK;
+			return NOTIFY_STOP;
 		break;
 	case DIE_DEBUG_2:
 		if (post_kprobe_handler(args->regs))
-			return NOTIFY_OK;
+			return NOTIFY_STOP;
 		break;
 	case DIE_GPF:
 		if (kprobe_running() &&
 		    kprobe_fault_handler(args->regs, args->trapnr))
-			return NOTIFY_OK;
+			return NOTIFY_STOP;
 		break;
 	case DIE_PAGE_FAULT:
 		if (kprobe_running() &&
 		    kprobe_fault_handler(args->regs, args->trapnr))
-			return NOTIFY_OK;
+			return NOTIFY_STOP;
 		break;
 	default:
 		break;
 	}
-	return NOTIFY_BAD;
+	return NOTIFY_DONE;
 }
 
 asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs)
@@ -216,7 +216,7 @@ asmlinkage void kprobe_trap(unsigned lon
 	 */
 	if (notify_die((trap_level == 0x170) ? DIE_DEBUG : DIE_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);
 }
 
diff -puN arch/sparc64/kernel/traps.c~kprobes-exceptions-notifier-fix arch/sparc64/kernel/traps.c
--- linux-2.6.9-rc2/arch/sparc64/kernel/traps.c~kprobes-exceptions-notifier-fix	2004-09-27 11:55:57.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/arch/sparc64/kernel/traps.c	2004-09-27 11:55:57.000000000 +0530
@@ -96,7 +96,7 @@ void bad_trap(struct pt_regs *regs, long
 	siginfo_t info;
 
 	if (notify_die(DIE_TRAP, "bad trap", regs,
-		       0, lvl, SIGTRAP) == NOTIFY_OK)
+		       0, lvl, SIGTRAP) == NOTIFY_STOP)
 		return;
 
 	if (lvl < 0x100) {
@@ -126,7 +126,7 @@ void bad_trap_tl1(struct pt_regs *regs, 
 	char buffer[32];
 	
 	if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs,
-		       0, lvl, SIGTRAP) == NOTIFY_OK)
+		       0, lvl, SIGTRAP) == NOTIFY_STOP)
 		return;
 
 	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
@@ -149,7 +149,7 @@ void instruction_access_exception(struct
 	siginfo_t info;
 
 	if (notify_die(DIE_TRAP, "instruction access exception", regs,
-		       0, 0x8, SIGTRAP) == NOTIFY_OK)
+		       0, 0x8, SIGTRAP) == NOTIFY_STOP)
 		return;
 
 	if (regs->tstate & TSTATE_PRIV) {
@@ -173,7 +173,7 @@ void instruction_access_exception_tl1(st
 				      unsigned long sfsr, unsigned long sfar)
 {
 	if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs,
-		       0, 0x8, SIGTRAP) == NOTIFY_OK)
+		       0, 0x8, SIGTRAP) == NOTIFY_STOP)
 		return;
 
 	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
@@ -186,7 +186,7 @@ void data_access_exception(struct pt_reg
 	siginfo_t info;
 
 	if (notify_die(DIE_TRAP, "data access exception", regs,
-		       0, 0x30, SIGTRAP) == NOTIFY_OK)
+		       0, 0x30, SIGTRAP) == NOTIFY_STOP)
 		return;
 
 	if (regs->tstate & TSTATE_PRIV) {
@@ -260,7 +260,7 @@ void do_iae(struct pt_regs *regs)
 	spitfire_clean_and_reenable_l1_caches();
 
 	if (notify_die(DIE_TRAP, "instruction access exception", regs,
-		       0, 0x8, SIGTRAP) == NOTIFY_OK)
+		       0, 0x8, SIGTRAP) == NOTIFY_STOP)
 		return;
 
 	info.si_signo = SIGBUS;
@@ -292,7 +292,7 @@ void do_dae(struct pt_regs *regs)
 	spitfire_clean_and_reenable_l1_caches();
 
 	if (notify_die(DIE_TRAP, "data access exception", regs,
-		       0, 0x30, SIGTRAP) == NOTIFY_OK)
+		       0, 0x30, SIGTRAP) == NOTIFY_STOP)
 		return;
 
 	info.si_signo = SIGBUS;
@@ -1695,7 +1695,7 @@ void do_fpe_common(struct pt_regs *regs)
 void do_fpieee(struct pt_regs *regs)
 {
 	if (notify_die(DIE_TRAP, "fpu exception ieee", regs,
-		       0, 0x24, SIGFPE) == NOTIFY_OK)
+		       0, 0x24, SIGFPE) == NOTIFY_STOP)
 		return;
 
 	do_fpe_common(regs);
@@ -1709,7 +1709,7 @@ void do_fpother(struct pt_regs *regs)
 	int ret = 0;
 
 	if (notify_die(DIE_TRAP, "fpu exception other", regs,
-		       0, 0x25, SIGFPE) == NOTIFY_OK)
+		       0, 0x25, SIGFPE) == NOTIFY_STOP)
 		return;
 
 	switch ((current_thread_info()->xfsr[0] & 0x1c000)) {
@@ -1728,7 +1728,7 @@ void do_tof(struct pt_regs *regs)
 	siginfo_t info;
 
 	if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs,
-		       0, 0x26, SIGEMT) == NOTIFY_OK)
+		       0, 0x26, SIGEMT) == NOTIFY_STOP)
 		return;
 
 	if (regs->tstate & TSTATE_PRIV)
@@ -1750,7 +1750,7 @@ void do_div0(struct pt_regs *regs)
 	siginfo_t info;
 
 	if (notify_die(DIE_TRAP, "integer division by zero", regs,
-		       0, 0x28, SIGFPE) == NOTIFY_OK)
+		       0, 0x28, SIGFPE) == NOTIFY_STOP)
 		return;
 
 	if (regs->tstate & TSTATE_PRIV)
@@ -1936,7 +1936,7 @@ void do_illegal_instruction(struct pt_re
 	siginfo_t info;
 
 	if (notify_die(DIE_TRAP, "illegal instruction", regs,
-		       0, 0x10, SIGILL) == NOTIFY_OK)
+		       0, 0x10, SIGILL) == NOTIFY_STOP)
 		return;
 
 	if (tstate & TSTATE_PRIV)
@@ -1965,7 +1965,7 @@ void mem_address_unaligned(struct pt_reg
 	siginfo_t info;
 
 	if (notify_die(DIE_TRAP, "memory address unaligned", regs,
-		       0, 0x34, SIGSEGV) == NOTIFY_OK)
+		       0, 0x34, SIGSEGV) == NOTIFY_STOP)
 		return;
 
 	if (regs->tstate & TSTATE_PRIV) {
@@ -1991,7 +1991,7 @@ void do_privop(struct pt_regs *regs)
 	siginfo_t info;
 
 	if (notify_die(DIE_TRAP, "privileged operation", regs,
-		       0, 0x11, SIGILL) == NOTIFY_OK)
+		       0, 0x11, SIGILL) == NOTIFY_STOP)
 		return;
 
 	if (test_thread_flag(TIF_32BIT)) {
diff -puN arch/sparc64/mm/fault.c~kprobes-exceptions-notifier-fix arch/sparc64/mm/fault.c
--- linux-2.6.9-rc2/arch/sparc64/mm/fault.c~kprobes-exceptions-notifier-fix	2004-09-27 11:55:57.000000000 +0530
+++ linux-2.6.9-rc2-prasanna/arch/sparc64/mm/fault.c	2004-09-27 11:55:57.000000000 +0530
@@ -149,7 +149,7 @@ static void unhandled_fault(unsigned lon
 	       (tsk->mm ? (unsigned long) tsk->mm->pgd :
 		          (unsigned long) tsk->active_mm->pgd));
 	if (notify_die(DIE_GPF, "general protection fault", regs,
-		       0, 0, SIGSEGV) == NOTIFY_OK)
+		       0, 0, SIGSEGV) == NOTIFY_STOP)
 		return;
 	die_if_kernel("Oops", regs);
 }
@@ -325,7 +325,7 @@ asmlinkage void do_sparc64_fault(struct 
 	fault_code = get_thread_fault_code();
 
 	if (notify_die(DIE_PAGE_FAULT, "page_fault", regs,
-		       fault_code, 0, SIGSEGV) == NOTIFY_OK)
+		       fault_code, 0, SIGSEGV) == NOTIFY_STOP)
 		return;
 
 	si_code = SEGV_MAPERR;

_

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2004-09-27 12:10 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-09-23  5:30 [Patch] kprobes exception notifier fix 2.6.9-rc2 Prasanna S Panchamukhi
2004-09-23  8:06 ` Andi Kleen
2004-09-23  8:45   ` Prasanna S Panchamukhi
2004-09-23 19:32   ` David S. Miller
2004-09-27 12:10     ` Prasanna S Panchamukhi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox