Re: [RFT PATCH -next v2] [BUGFIX] kprobes: Fix Failed to find blacklist error on ia64 and ppc64
On 05/27/2014 12:01 PM, Masami Hiramatsu wrote: On ia64 and ppc64, the function pointer does not point the entry address of the function, but the address of function discriptor (which contains the entry address and misc data.) Since the kprobes passes the function pointer stored by NOKPROBE_SYMBOL() to kallsyms_lookup_size_offset() for initalizing its blacklist, it fails and reports many errors as below. Failed to find blacklist 000101316830 Failed to find blacklist 0001013000f0a000 Failed to find blacklist 000101315f70a000 Failed to find blacklist 000101324c80a000 Failed to find blacklist 0001013063f0a000 Failed to find blacklist 000101327800a000 Failed to find blacklist 0001013277f0a000 Failed to find blacklist 000101315a70a000 Failed to find blacklist 0001013277e0a000 Failed to find blacklist 000101305a20a000 Failed to find blacklist 0001013277d0a000 Failed to find blacklist 00010130bdc0a000 Failed to find blacklist 00010130dc20a000 Failed to find blacklist 000101309a00a000 Failed to find blacklist 0001013277c0a000 Failed to find blacklist 0001013277b0a000 Failed to find blacklist 0001013277a0a000 Failed to find blacklist 000101327790a000 Failed to find blacklist 000101303140a000 Failed to find blacklist 0001013a3280a000 To fix this bug, this introduces function_entry() macro to retrieve the entry address from the given function pointer, and uses for kallsyms_lookup_size_offset() while initializing blacklist. Changes in V2: - Use function_entry() macro when lookin up symbols instead of storing it. - Update for the latest -next. Signed-off-by: Masami Hiramatsu masami.hiramatsu...@hitachi.com Reported-by: Tony Luck tony.l...@gmail.com Cc: Suzuki K. Poulose suz...@in.ibm.com Cc: Tony Luck tony.l...@intel.com Cc: Fenghua Yu fenghua...@intel.com Cc: Benjamin Herrenschmidt b...@kernel.crashing.org Cc: Paul Mackerras pau...@samba.org Cc: Ananth N Mavinakayanahalli ana...@in.ibm.com Cc: Kevin Hao haoke...@gmail.com Cc: linux-i...@vger.kernel.org Cc: linux-ker...@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org --- arch/ia64/include/asm/types.h|2 ++ arch/powerpc/include/asm/types.h | 11 +++ include/linux/types.h|4 kernel/kprobes.c |4 +++- 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/arch/ia64/include/asm/types.h b/arch/ia64/include/asm/types.h index 4c351b1..95279dd 100644 --- a/arch/ia64/include/asm/types.h +++ b/arch/ia64/include/asm/types.h @@ -27,5 +27,7 @@ struct fnptr { unsigned long gp; }; +#define function_entry(fn) (((struct fnptr *)(fn))-ip) + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_IA64_TYPES_H */ diff --git a/arch/powerpc/include/asm/types.h b/arch/powerpc/include/asm/types.h index bfb6ded..8b89d65 100644 --- a/arch/powerpc/include/asm/types.h +++ b/arch/powerpc/include/asm/types.h @@ -25,6 +25,17 @@ typedef struct { unsigned long env; } func_descr_t; +#if defined(CONFIG_PPC64) (!defined(_CALL_ELF) || _CALL_ELF == 1) +/* + * On PPC64 ABIv1 the function pointer actually points to the + * function's descriptor. The first entry in the descriptor is the + * address of the function text. + */ +#define function_entry(fn) (((func_descr_t *)(fn))-entry) +#else +#define function_entry(fn) ((unsigned long)(fn)) +#endif + #endif /* __ASSEMBLY__ */ #endif /* _ASM_POWERPC_TYPES_H */ diff --git a/include/linux/types.h b/include/linux/types.h index a0bb704..3b95369 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -213,5 +213,9 @@ struct callback_head { }; #define rcu_head callback_head +#ifndef function_entry +#define function_entry(fn) ((unsigned long)(fn)) +#endif + #endif /* __ASSEMBLY__ */ #endif /* _LINUX_TYPES_H */ diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 2ac9f13..3859c88 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -32,6 +32,7 @@ * prasa...@in.ibm.com added function-return probes. */ #include linux/kprobes.h +#include linux/types.h #include linux/hash.h #include linux/init.h #include linux/slab.h @@ -2042,7 +2043,8 @@ static int __init populate_kprobe_blacklist(unsigned long *start, unsigned long offset = 0, size = 0; for (iter = start; iter end; iter++) { - if (!kallsyms_lookup_size_offset(*iter, size, offset)) { + if (!kallsyms_lookup_size_offset(function_entry(*iter), + size, offset)) { On powerpc we will be able to resolve the *iter to func_descr and won't get the below error with/without this patch. So we have to actually verify the kprobe_blacklist contents to make sure everything is alright. pr_err(Failed to find blacklist %p\n, (void *)*iter); continue; } There is a bug here. You need to set
Re: [RFT PATCH -next v2] [BUGFIX] kprobes: Fix Failed to find blacklist error on ia64 and ppc64
(2014/05/30 4:13), Suzuki K. Poulose wrote: @@ -2042,7 +2043,8 @@ static int __init populate_kprobe_blacklist(unsigned long *start, unsigned long offset = 0, size = 0; for (iter = start; iter end; iter++) { -if (!kallsyms_lookup_size_offset(*iter, size, offset)) { +if (!kallsyms_lookup_size_offset(function_entry(*iter), + size, offset)) { On powerpc we will be able to resolve the *iter to func_descr and won't get the below error with/without this patch. So we have to actually verify the kprobe_blacklist contents to make sure everything is alright. pr_err(Failed to find blacklist %p\n, (void *)*iter); continue; } There is a bug here. You need to set the ent-start using the function_entry(*iter) and not *iter. Or else you just avoid the 'Warning' and still have an invalid black list. As shown below : 2e:mon ls kprobe_blacklist kprobe_blacklist: c104dad0 2e:mon d c104dad0 10 c104dad0: c003aff800a0 c003aff809a0 2e:mon d c003aff800a0 20 (struct kprobe_blacklist *) c003aff800a0: c003aff800c0 c104dad0 c003aff800b0: c10ef138 c10ef188 start ^^ end ^^ 2e:mon la c10ef138 (start) c10ef138: notify_die+0x0/0x10 - still points to the function descriptor 2e:mon la c10ef188 (end) c10ef188: __blocking_notifier_call_chain+0x0/0x10 Following patch fixes the issue, with the patch : 1:mon ls kprobe_blacklist kprobe_blacklist: c104dad0 1:mon d c104dad0 10 c104dad0: c003ae1a00a0 c003ae1a09a0 1:mon d c003ae1a00a0 20 (struct kprobe_blacklist *) c003ae1a00a0: c003ae1a00c0 c104dad0 c003ae1a00b0: c00b14d0 c00b1520 start ^^ end ^^ 1:mon la c00b14d0 c00b14d0: .notify_die+0x0/0x50 1:mon la c00b1520 c00b1520: .atomic_notifier_chain_register+0x0/0xa0 1:mon di c00b14d0 10 (.notify_die) c00b14d0 7c0802a6mflrr0 c00b14d4 7c691b78mr r9,r3 commit ed51674aca8e0496641f565421ab6691a873e80a Author: Suzuki K. Poulose suz...@in.ibm.com Date: Fri May 30 00:23:01 2014 +0530 diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 3859c88..b81d626 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -2043,7 +2043,8 @@ static int __init populate_kprobe_blacklist(unsigned long *start, unsigned long offset = 0, size = 0; for (iter = start; iter end; iter++) { - if (!kallsyms_lookup_size_offset(function_entry(*iter), + unsigned long entry = function_entry(*iter); + if (!kallsyms_lookup_size_offset(entry, size, offset)) { pr_err(Failed to find blacklist %p\n, (void *)*iter); continue; @@ -2052,8 +2053,8 @@ static int __init populate_kprobe_blacklist(unsigned long *start, ent = kmalloc(sizeof(*ent), GFP_KERNEL); if (!ent) return -ENOMEM; - ent-start_addr = *iter; - ent-end_addr = *iter + size; + ent-start_addr = entry; + ent-end_addr = entry + size; Oops! right, I missed it :( I'll update the patch including your fix and signed-off-by. thank you! -- Masami HIRAMATSU Software Platform Research Dept. Linux Technology Research Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: masami.hiramatsu...@hitachi.com ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[RFT PATCH -next v2] [BUGFIX] kprobes: Fix Failed to find blacklist error on ia64 and ppc64
On ia64 and ppc64, the function pointer does not point the entry address of the function, but the address of function discriptor (which contains the entry address and misc data.) Since the kprobes passes the function pointer stored by NOKPROBE_SYMBOL() to kallsyms_lookup_size_offset() for initalizing its blacklist, it fails and reports many errors as below. Failed to find blacklist 000101316830 Failed to find blacklist 0001013000f0a000 Failed to find blacklist 000101315f70a000 Failed to find blacklist 000101324c80a000 Failed to find blacklist 0001013063f0a000 Failed to find blacklist 000101327800a000 Failed to find blacklist 0001013277f0a000 Failed to find blacklist 000101315a70a000 Failed to find blacklist 0001013277e0a000 Failed to find blacklist 000101305a20a000 Failed to find blacklist 0001013277d0a000 Failed to find blacklist 00010130bdc0a000 Failed to find blacklist 00010130dc20a000 Failed to find blacklist 000101309a00a000 Failed to find blacklist 0001013277c0a000 Failed to find blacklist 0001013277b0a000 Failed to find blacklist 0001013277a0a000 Failed to find blacklist 000101327790a000 Failed to find blacklist 000101303140a000 Failed to find blacklist 0001013a3280a000 To fix this bug, this introduces function_entry() macro to retrieve the entry address from the given function pointer, and uses for kallsyms_lookup_size_offset() while initializing blacklist. Changes in V2: - Use function_entry() macro when lookin up symbols instead of storing it. - Update for the latest -next. Signed-off-by: Masami Hiramatsu masami.hiramatsu...@hitachi.com Reported-by: Tony Luck tony.l...@gmail.com Cc: Suzuki K. Poulose suz...@in.ibm.com Cc: Tony Luck tony.l...@intel.com Cc: Fenghua Yu fenghua...@intel.com Cc: Benjamin Herrenschmidt b...@kernel.crashing.org Cc: Paul Mackerras pau...@samba.org Cc: Ananth N Mavinakayanahalli ana...@in.ibm.com Cc: Kevin Hao haoke...@gmail.com Cc: linux-i...@vger.kernel.org Cc: linux-ker...@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org --- arch/ia64/include/asm/types.h|2 ++ arch/powerpc/include/asm/types.h | 11 +++ include/linux/types.h|4 kernel/kprobes.c |4 +++- 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/arch/ia64/include/asm/types.h b/arch/ia64/include/asm/types.h index 4c351b1..95279dd 100644 --- a/arch/ia64/include/asm/types.h +++ b/arch/ia64/include/asm/types.h @@ -27,5 +27,7 @@ struct fnptr { unsigned long gp; }; +#define function_entry(fn) (((struct fnptr *)(fn))-ip) + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_IA64_TYPES_H */ diff --git a/arch/powerpc/include/asm/types.h b/arch/powerpc/include/asm/types.h index bfb6ded..8b89d65 100644 --- a/arch/powerpc/include/asm/types.h +++ b/arch/powerpc/include/asm/types.h @@ -25,6 +25,17 @@ typedef struct { unsigned long env; } func_descr_t; +#if defined(CONFIG_PPC64) (!defined(_CALL_ELF) || _CALL_ELF == 1) +/* + * On PPC64 ABIv1 the function pointer actually points to the + * function's descriptor. The first entry in the descriptor is the + * address of the function text. + */ +#define function_entry(fn) (((func_descr_t *)(fn))-entry) +#else +#define function_entry(fn) ((unsigned long)(fn)) +#endif + #endif /* __ASSEMBLY__ */ #endif /* _ASM_POWERPC_TYPES_H */ diff --git a/include/linux/types.h b/include/linux/types.h index a0bb704..3b95369 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -213,5 +213,9 @@ struct callback_head { }; #define rcu_head callback_head +#ifndef function_entry +#define function_entry(fn) ((unsigned long)(fn)) +#endif + #endif /* __ASSEMBLY__ */ #endif /* _LINUX_TYPES_H */ diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 2ac9f13..3859c88 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -32,6 +32,7 @@ * prasa...@in.ibm.com added function-return probes. */ #include linux/kprobes.h +#include linux/types.h #include linux/hash.h #include linux/init.h #include linux/slab.h @@ -2042,7 +2043,8 @@ static int __init populate_kprobe_blacklist(unsigned long *start, unsigned long offset = 0, size = 0; for (iter = start; iter end; iter++) { - if (!kallsyms_lookup_size_offset(*iter, size, offset)) { + if (!kallsyms_lookup_size_offset(function_entry(*iter), +size, offset)) { pr_err(Failed to find blacklist %p\n, (void *)*iter); continue; } ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev