Kprobes: Print details of kretprobe on assertion failure
PATCH 1/1 Kprobes: Print details of kretprobe on assertion failure
From: Ananth N Mavinakayanahalli <[email protected]>
In certain cases like when the real return address can't be found or when the number of tracked calls to a kretprobed function is less than the number of returns, we may not be able to find the correct return address after processing a kretprobe. Currently we just do a BUG_ON, but no information is provided about the actual failing kretprobe.
Print out details of the kretprobe before calling BUG().
--- arch/i386/kernel/kprobes.c | 6 +++++- arch/ia64/kernel/kprobes.c | 7 ++++++- arch/powerpc/kernel/kprobes.c | 7 ++++++- arch/x86_64/kernel/kprobes.c | 7 ++++++- 4 files changed, 23 insertions(+), 4 deletions(-)
arch/i386/kernel/kprobes.c +5 -1
@@ -440,7 +440,11 @@ fastcall void *__kprobes trampoline_handbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +if (!orig_ret_address || (orig_ret_address == trampoline_address)) { +printk ("kretprobe BUG!: Processing kretprobe %p @ %p\n" , + ri->rp, ri->rp->kp.addr); +BUG (); + }spin_unlock_irqrestore (&kretprobe_lock, flags);
arch/ia64/kernel/kprobes.c +6 -1
@@ -444,7 +444,12 @@ int __kprobes trampoline_probe_handler(sbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +if (!orig_ret_address || (orig_ret_address == trampoline_address)) { +printk ("kretprobe BUG!: Processing kretprobe %p @ %p\n" , + ri->rp, ri->rp->kp.addr); +BUG (); + } + regs->cr_iip = orig_ret_address;reset_current_kprobe ();
arch/powerpc/kernel/kprobes.c +6 -1
@@ -293,7 +293,12 @@ int __kprobes trampoline_probe_handler(sbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +if (!orig_ret_address || (orig_ret_address == trampoline_address)) { +printk ("kretprobe BUG!: Processing kretprobe %p @ %p\n" , + ri->rp, ri->rp->kp.addr); +BUG (); + } + regs->nip = orig_ret_address;reset_current_kprobe ();
arch/x86_64/kernel/kprobes.c +6 -1
@@ -438,7 +438,12 @@ int __kprobes trampoline_probe_handler(sbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +if (!orig_ret_address || (orig_ret_address == trampoline_address)) { +printk ("kretprobe BUG!: Processing kretprobe %p @ %p\n" , + ri->rp, ri->rp->kp.addr); +BUG (); + } + regs->rip = orig_ret_address;reset_current_kprobe ();
Quoted 79 lines · On Mon, 2 Apr 2007 14:56:36 +0530 Ananth N Mavinakayanahalli…
From: Ananth N Mavinakayanahalli <[email protected]>
In certain cases like when the real return address can't be found or when the number of tracked calls to a kretprobed function is less than the number of returns, we may not be able to find the correct return address after processing a kretprobe. Currently we just do a
BUG_ON, but no information is provided about the actual failing kretprobe.Print out details of the kretprobe before calling
BUG().Signed-off-by Ananth N Mavinakayanahalli <[email protected]>--- arch/i386/kernel/kprobes.c | 6 +++++- arch/ia64/kernel/kprobes.c | 7 ++++++- arch/powerpc/kernel/kprobes.c | 7 ++++++- arch/x86_64/kernel/kprobes.c | 7 ++++++- 4 files changed, 23 insertions(+), 4 deletions(-)Index:
linux-2.6.21-rc5/arch/i386/kernel/kprobes.c
===================================================================arch/i386/kernel/kprobes.c +5
-1@@ -440,7 +440,11 @@ fastcall void *__kprobes trampoline_handbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +if (!orig_ret_address || (orig_ret_address == trampoline_address)) { +printk ("kretprobe BUG!: Processing kretprobe %p @ %p\n" , + ri->rp, ri->rp->kp.addr); +BUG (); + }spin_unlock_irqrestore (&kretprobe_lock, flags);Index:
linux-2.6.21-rc5/arch/ia64/kernel/kprobes.c
===================================================================arch/ia64/kernel/kprobes.c +6
-1@@ -444,7 +444,12 @@ int __kprobes trampoline_probe_handler(sbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +if (!orig_ret_address || (orig_ret_address == trampoline_address)) { +printk ("kretprobe BUG!: Processing kretprobe %p @ %p\n" , + ri->rp, ri->rp->kp.addr); +BUG (); + } + regs->cr_iip = orig_ret_address;reset_current_kprobe ();Index:
linux-2.6.21-rc5/arch/powerpc/kernel/kprobes.c
===================================================================arch/powerpc/kernel/kprobes.c +6
-1@@ -293,7 +293,12 @@ int __kprobes trampoline_probe_handler(sbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +if (!orig_ret_address || (orig_ret_address == trampoline_address)) { +printk ("kretprobe BUG!: Processing kretprobe %p @ %p\n" , + ri->rp, ri->rp->kp.addr); +BUG (); + } + regs->nip = orig_ret_address;reset_current_kprobe ();Index:
linux-2.6.21-rc5/arch/x86_64/kernel/kprobes.c
===================================================================arch/x86_64/kernel/kprobes.c +0
-0@@ -438,7 +438,12 @@ int __kprobes trampoline_probe_handler(sbreak ; }
arch/x86_64/kernel/kprobes.c int __kprobes trampoline_probe_handler(s · line 448
Quoted 10 lines
arch/x86_64/kernel/kprobes.c +6
-1-BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +if (!orig_ret_address || (orig_ret_address == trampoline_address)) { +printk ("kretprobe BUG!: Processing kretprobe %p @ %p\n" , + ri->rp, ri->rp->kp.addr); +BUG (); + } + regs->rip = orig_ret_address;
A lot of copying-and-pasting there. Would it be better if this assertion was performed in a library function in kernel/kprobes.c?
Quoted 83 lines · Andrew Morton
Quoted 80 lines · On Mon, 2 Apr 2007 14:56:36 +0530 Ananth N Mavinakayanahalli…
From: Ananth N Mavinakayanahalli <[email protected]>
In certain cases like when the real return address can't be found or when the number of tracked calls to a kretprobed function is less than the number of returns, we may not be able to find the correct return address after processing a kretprobe. Currently we just do a
BUG_ON, but no information is provided about the actual failing kretprobe.Print out details of the kretprobe before calling
BUG().Signed-off-by Ananth N Mavinakayanahalli <[email protected]>--- arch/i386/kernel/kprobes.c | 6 +++++- arch/ia64/kernel/kprobes.c | 7 ++++++- arch/powerpc/kernel/kprobes.c | 7 ++++++- arch/x86_64/kernel/kprobes.c | 7 ++++++- 4 files changed, 23 insertions(+), 4 deletions(-)Index:
linux-2.6.21-rc5/arch/i386/kernel/kprobes.c
===================================================================arch/i386/kernel/kprobes.c +5
-1@@ -440,7 +440,11 @@ fastcall void *__kprobes trampoline_handbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +if (!orig_ret_address || (orig_ret_address == trampoline_address)) { +printk ("kretprobe BUG!: Processing kretprobe %p @ %p\n" , + ri->rp, ri->rp->kp.addr); +BUG (); + }spin_unlock_irqrestore (&kretprobe_lock, flags);Index:
linux-2.6.21-rc5/arch/ia64/kernel/kprobes.c
===================================================================arch/ia64/kernel/kprobes.c +6
-1@@ -444,7 +444,12 @@ int __kprobes trampoline_probe_handler(sbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +if (!orig_ret_address || (orig_ret_address == trampoline_address)) { +printk ("kretprobe BUG!: Processing kretprobe %p @ %p\n" , + ri->rp, ri->rp->kp.addr); +BUG (); + } + regs->cr_iip = orig_ret_address;reset_current_kprobe ();Index:
linux-2.6.21-rc5/arch/powerpc/kernel/kprobes.c
===================================================================arch/powerpc/kernel/kprobes.c +6
-1@@ -293,7 +293,12 @@ int __kprobes trampoline_probe_handler(sbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +if (!orig_ret_address || (orig_ret_address == trampoline_address)) { +printk ("kretprobe BUG!: Processing kretprobe %p @ %p\n" , + ri->rp, ri->rp->kp.addr); +BUG (); + } + regs->nip = orig_ret_address;reset_current_kprobe ();Index:
linux-2.6.21-rc5/arch/x86_64/kernel/kprobes.c
===================================================================arch/x86_64/kernel/kprobes.c +0
-0@@ -438,7 +438,12 @@ int __kprobes trampoline_probe_handler(sbreak ; }
Quoted 12 lines
arch/x86_64/kernel/kprobes.c int __kprobes trampoline_probe_handler(s · line 448
Quoted 9 lines
arch/x86_64/kernel/kprobes.c +6
-1-BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +if (!orig_ret_address || (orig_ret_address == trampoline_address)) { +printk ("kretprobe BUG!: Processing kretprobe %p @ %p\n" , + ri->rp, ri->rp->kp.addr); +BUG (); + } + regs->rip = orig_ret_address;A lot of copying-and-pasting there. Would it be better if this assertion was performed in a library function in
kernel/kprobes.c?
Indeed. Here is the updated patch...
From: Ananth N Mavinakayanahalli <[email protected]>
In certain cases like when the real return address can't be found or when the number of tracked calls to a kretprobed function is less than the number of returns, we may not be able to find the correct return address after processing a kretprobe. Currently we just do a BUG_ON, but no information is provided about the actual failing kretprobe.
Print out details of the kretprobe before calling BUG().
--- arch/i386/kernel/kprobes.c | 3 +-- arch/ia64/kernel/kprobes.c | 3 ++- arch/powerpc/kernel/kprobes.c | 2 +- arch/x86_64/kernel/kprobes.c | 2 +- include/linux/kprobes.h | 10 ++++++++++ 5 files changed, 15 insertions(+), 5 deletions(-)
arch/i386/kernel/kprobes.c +1 -2
@@ -440,8 +440,7 @@ fastcall void *__kprobes trampoline_handbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); - +kretprobe_assert (ri, orig_ret_address, trampoline_address);spin_unlock_irqrestore (&kretprobe_lock, flags);hlist_for_each_entry_safe (ri, node, tmp, &empty_rp, hlist) {
arch/ia64/kernel/kprobes.c +2 -1
@@ -444,7 +444,8 @@ int __kprobes trampoline_probe_handler(sbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +kretprobe_assert (ri, orig_ret_address, trampoline_address); + regs->cr_iip = orig_ret_address;reset_current_kprobe ();
arch/powerpc/kernel/kprobes.c +1 -1
@@ -293,7 +293,7 @@ int __kprobes trampoline_probe_handler(sbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +kretprobe_assert (ri, orig_ret_address, trampoline_address); regs->nip = orig_ret_address;reset_current_kprobe ();
arch/x86_64/kernel/kprobes.c +1 -1
@@ -438,7 +438,7 @@ int __kprobes trampoline_probe_handler(sbreak ; } -BUG_ON (!orig_ret_address || (orig_ret_address == trampoline_address)); +kretprobe_assert (ri, orig_ret_address, trampoline_address); regs->rip = orig_ret_address;reset_current_kprobe ();
include/linux/kprobes.h +10 -0
@@ -158,6 +158,16 @@ struct kretprobe_instance {struct task_struct *task; }; +static inline void kretprobe_assert (struct kretprobe_instance *ri, +unsigned long orig_ret_address,unsigned long trampoline_address) +{ +if (!orig_ret_address || (orig_ret_address == trampoline_address)) { +printk ("kretprobe BUG!: Processing kretprobe %p @ %p\n" , + ri->rp, ri->rp->kp.addr); +BUG (); + } +} +extern spinlock_t kretprobe_lock;extern struct mutex kprobe_mutex;extern int arch_prepare_kprobe (struct kprobe *p);