kprobes: Fix "Failed to find blacklist" probing errors on ia64 and ppc64

On ia64 and ppc64, function pointers do not point to the
entry address of the function, but to the address of a
function descriptor (which contains the entry address and misc
data).

Since the kprobes code passes the function pointer stored
by NOKPROBE_SYMBOL() to kallsyms_lookup_size_offset() for
initalizing its blacklist, it fails and reports many errors,
such as:

Failed to find blacklist 0001013168300000
Failed to find blacklist 0001013000f0a000
[...]

To fix this bug, use 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 as well.

Reported-by: Tony Luck <tony.luck@gmail.com>
Fixed-by: Suzuki K. Poulose <suzuki@in.ibm.com>
Tested-by: Tony Luck <tony.luck@intel.com>
Tested-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Acked-by: Michael Ellerman <mpe@ellerman.id.au> (for powerpc)
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: sparse@chrisli.org
Cc: Paul Mackerras <paulus@samba.org>
Cc: akataria@vmware.com
Cc: anil.s.keshavamurthy@intel.com
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: yrl.pp-manager.tt@hitachi.com
Cc: Kevin Hao <haokexin@gmail.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: rdunlap@infradead.org
Cc: dl9pf@gmx.de
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: David S. Miller <davem@davemloft.net>
Cc: linux-ia64@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Link: http://lkml.kernel.org/r/20140717114411.13401.2632.stgit@kbuild-fedora.novalocal
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by Masami Hiramatsu and committed by Ingo Molnar d81b4253 0cdd192c

Changed files
+9 -5
kernel
+9 -5
kernel/kprobes.c
··· 2037 2037 { 2038 2038 unsigned long *iter; 2039 2039 struct kprobe_blacklist_entry *ent; 2040 - unsigned long offset = 0, size = 0; 2040 + unsigned long entry, offset = 0, size = 0; 2041 2041 2042 2042 for (iter = start; iter < end; iter++) { 2043 - if (!kallsyms_lookup_size_offset(*iter, &size, &offset)) { 2044 - pr_err("Failed to find blacklist %p\n", (void *)*iter); 2043 + entry = arch_deref_entry_point((void *)*iter); 2044 + 2045 + if (!kernel_text_address(entry) || 2046 + !kallsyms_lookup_size_offset(entry, &size, &offset)) { 2047 + pr_err("Failed to find blacklist at %p\n", 2048 + (void *)entry); 2045 2049 continue; 2046 2050 } 2047 2051 2048 2052 ent = kmalloc(sizeof(*ent), GFP_KERNEL); 2049 2053 if (!ent) 2050 2054 return -ENOMEM; 2051 - ent->start_addr = *iter; 2052 - ent->end_addr = *iter + size; 2055 + ent->start_addr = entry; 2056 + ent->end_addr = entry + size; 2053 2057 INIT_LIST_HEAD(&ent->list); 2054 2058 list_add_tail(&ent->list, &kprobe_blacklist); 2055 2059 }