From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail9.hitachi.co.jp (mail9.hitachi.co.jp [133.145.228.44]) by lists.ozlabs.org (Postfix) with ESMTP id 422E61A00C1 for ; Thu, 17 Jul 2014 21:44:22 +1000 (EST) Subject: [PATCH v6] [BUGFIX] kprobes: Fix "Failed to find blacklist" error on ia64 and ppc64 From: Masami Hiramatsu To: Ingo Molnar Date: Thu, 17 Jul 2014 11:44:11 +0000 Message-ID: <20140717114411.13401.2632.stgit@kbuild-fedora.novalocal> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Cc: Jeremy Fitzhardinge , linux-ia64@vger.kernel.org, sparse@chrisli.org, Tony Luck , Paul Mackerras , "H. Peter Anvin" , Thomas Gleixner , linux-tip-commits@vger.kernel.org, anil.s.keshavamurthy@intel.com, "Suzuki K. Poulose" , Fenghua Yu , Arnd Bergmann , Rusty Russell , Chris Wright , yrl.pp-manager.tt@hitachi.com, akataria@vmware.com, Tony Luck , Kevin Hao , Linus Torvalds , rdunlap@infradead.org, Linux Kernel Mailing List , dl9pf@gmx.de, Andrew Morton , linuxppc-dev@lists.ozlabs.org, "David S. Miller" List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , 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 uses arch_deref_entry_point() to get the function entry address for kallsyms_lookup_size_offset() instead of the raw function pointer. Suzuki also pointed out that blacklist entries should also be updated by that too. Changes in v6: - Update patch description. - Remove "#include " which is no more needed because we don't use new function_entry() macro any more. Changes in v5: - Use arch_deref_entry_point() instead of function_entry(). Changes in v4: - Add kernel_text_address() check for verifying the address. - Moved on the latest linus tree. Changes in v3: - Fix a bug to get blacklist address based on function entry instead of function descriptor. (Suzuki's work, Thanks!) 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 Fixed-by: Suzuki K. Poulose Reported-by: Tony Luck Tested-by: Tony Luck Tested-by: Michael Ellerman Acked-by: Michael Ellerman (for powerpc) Acked-by: Benjamin Herrenschmidt Cc: Fenghua Yu Cc: Paul Mackerras Cc: Ananth N Mavinakayanahalli Cc: Kevin Hao Cc: linux-ia64@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org --- kernel/kprobes.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 3214289..734e9a7 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -2037,19 +2037,23 @@ static int __init populate_kprobe_blacklist(unsigned long *start, { unsigned long *iter; struct kprobe_blacklist_entry *ent; - unsigned long offset = 0, size = 0; + unsigned long entry, offset = 0, size = 0; for (iter = start; iter < end; iter++) { - if (!kallsyms_lookup_size_offset(*iter, &size, &offset)) { - pr_err("Failed to find blacklist %p\n", (void *)*iter); + entry = arch_deref_entry_point((void *)*iter); + + if (!kernel_text_address(entry) || + !kallsyms_lookup_size_offset(entry, &size, &offset)) { + pr_err("Failed to find blacklist at %p\n", + (void *)entry); continue; } 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; INIT_LIST_HEAD(&ent->list); list_add_tail(&ent->list, &kprobe_blacklist); }