From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752153AbaE0Gbk (ORCPT ); Tue, 27 May 2014 02:31:40 -0400 Received: from mail7.hitachi.co.jp ([133.145.228.42]:40754 "EHLO mail7.hitachi.co.jp" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751218AbaE0Gbe (ORCPT ); Tue, 27 May 2014 02:31:34 -0400 Subject: [RFT PATCH -next v2] [BUGFIX] kprobes: Fix "Failed to find blacklist" error on ia64 and ppc64 From: Masami Hiramatsu To: Benjamin Herrenschmidt , Paul Mackerras , Tony Luck Cc: Jeremy Fitzhardinge , linux-ia64@vger.kernel.org, sparse@chrisli.org, "H. Peter Anvin" , Ingo Molnar , linux-tip-commits@vger.kernel.org, akataria@vmware.com, anil.s.keshavamurthy@intel.com, "Suzuki K. Poulose" , Fenghua Yu , Arnd Bergmann , Rusty Russell , Chris Wright , yrl.pp-manager.tt@hitachi.com, Thomas Gleixner , Tony Luck , Kevin Hao , Ananth N Mavinakayanahalli , linuxppc-dev@lists.ozlabs.org, rdunlap@infradead.org, Linux Kernel Mailing List , dl9pf@gmx.de, Andrew Morton , Linus Torvalds , "David S. Miller" Date: Tue, 27 May 2014 15:31:21 +0900 Message-ID: <20140527063121.4399.38014.stgit@ltc230.yrl.intra.hitachi.co.jp> In-Reply-To: <5383249A.6060407@in.ibm.com> References: <5383249A.6060407@in.ibm.com> User-Agent: StGit/0.17-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 0001013168300000 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 Reported-by: Tony Luck Cc: Suzuki K. Poulose Cc: Tony Luck Cc: Fenghua Yu Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Ananth N Mavinakayanahalli Cc: Kevin Hao Cc: linux-ia64@vger.kernel.org Cc: linux-kernel@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 @@ * added function-return probes. */ #include +#include #include #include #include @@ -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; }