| From foo@baz Thu 30 Jul 2020 09:34:28 AM CEST |
| From: Masami Hiramatsu <mhiramat@kernel.org> |
| Date: Thu, 2 Jul 2020 21:41:42 +0900 |
| Subject: perf probe: Fix to check blacklist address correctly |
| To: stable@vger.kernel.org |
| Cc: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>, Changbin Du <changbin.du@gmail.com>, Jiri Olsa <jolsa@redhat.com>, Arnaldo Carvalho de Melo <acme@redhat.com>, mhiramat@kernel.org |
| Message-ID: <159369370274.82195.11710492245736974992.stgit@devnote2> |
| |
| From: Masami Hiramatsu <mhiramat@kernel.org> |
| |
| commit 80526491c2ca6abc028c0f0dbb0707a1f35fb18a upstream. |
| |
| Fix to check kprobe blacklist address correctly with relocated address |
| by adjusting debuginfo address. |
| |
| Since the address in the debuginfo is same as objdump, it is different |
| from relocated kernel address with KASLR. Thus, 'perf probe' always |
| misses to catch the blacklisted addresses. |
| |
| Without this patch, 'perf probe' can not detect the blacklist addresses |
| on a KASLR enabled kernel. |
| |
| # perf probe kprobe_dispatcher |
| Failed to write event: Invalid argument |
| Error: Failed to add events. |
| # |
| |
| With this patch, it correctly shows the error message. |
| |
| # perf probe kprobe_dispatcher |
| kprobe_dispatcher is blacklisted function, skip it. |
| Probe point 'kprobe_dispatcher' not found. |
| Error: Failed to add events. |
| # |
| |
| Fixes: 9aaf5a5f479b ("perf probe: Check kprobes blacklist when adding new events") |
| Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> |
| Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> |
| Cc: Jiri Olsa <jolsa@kernel.org> |
| Cc: Namhyung Kim <namhyung@kernel.org> |
| Cc: stable@vger.kernel.org |
| Link: http://lore.kernel.org/lkml/158763966411.30755.5882376357738273695.stgit@devnote2 |
| Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| tools/perf/util/probe-event.c | 21 +++++++++++++++------ |
| 1 file changed, 15 insertions(+), 6 deletions(-) |
| |
| --- a/tools/perf/util/probe-event.c |
| +++ b/tools/perf/util/probe-event.c |
| @@ -122,7 +122,7 @@ static struct symbol *__find_kernel_func |
| return machine__find_kernel_function(host_machine, addr, mapp, NULL); |
| } |
| |
| -static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) |
| +static struct ref_reloc_sym *kernel_get_ref_reloc_sym(struct map **pmap) |
| { |
| /* kmap->ref_reloc_sym should be set if host_machine is initialized */ |
| struct kmap *kmap; |
| @@ -134,6 +134,10 @@ static struct ref_reloc_sym *kernel_get_ |
| kmap = map__kmap(map); |
| if (!kmap) |
| return NULL; |
| + |
| + if (pmap) |
| + *pmap = map; |
| + |
| return kmap->ref_reloc_sym; |
| } |
| |
| @@ -145,7 +149,7 @@ static int kernel_get_symbol_address_by_ |
| struct map *map; |
| |
| /* ref_reloc_sym is just a label. Need a special fix*/ |
| - reloc_sym = kernel_get_ref_reloc_sym(); |
| + reloc_sym = kernel_get_ref_reloc_sym(NULL); |
| if (reloc_sym && strcmp(name, reloc_sym->name) == 0) |
| *addr = (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr; |
| else { |
| @@ -618,6 +622,7 @@ static int post_process_probe_trace_even |
| bool uprobe) |
| { |
| struct ref_reloc_sym *reloc_sym; |
| + struct map *map; |
| char *tmp; |
| int i, skipped = 0; |
| |
| @@ -628,7 +633,7 @@ static int post_process_probe_trace_even |
| if (module) |
| return add_module_to_probe_trace_events(tevs, ntevs, module); |
| |
| - reloc_sym = kernel_get_ref_reloc_sym(); |
| + reloc_sym = kernel_get_ref_reloc_sym(&map); |
| if (!reloc_sym) { |
| pr_warning("Relocated base symbol is not found!\n"); |
| return -EINVAL; |
| @@ -637,9 +642,13 @@ static int post_process_probe_trace_even |
| for (i = 0; i < ntevs; i++) { |
| if (!tevs[i].point.address || tevs[i].point.retprobe) |
| continue; |
| - /* If we found a wrong one, mark it by NULL symbol */ |
| + /* |
| + * If we found a wrong one, mark it by NULL symbol. |
| + * Since addresses in debuginfo is same as objdump, we need |
| + * to convert it to addresses on memory. |
| + */ |
| if (kprobe_warn_out_range(tevs[i].point.symbol, |
| - tevs[i].point.address)) { |
| + map__objdump_2mem(map, tevs[i].point.address))) { |
| tmp = NULL; |
| skipped++; |
| } else { |
| @@ -2553,7 +2562,7 @@ static int find_probe_trace_events_from_ |
| |
| /* Note that the symbols in the kmodule are not relocated */ |
| if (!pev->uprobes && !pp->retprobe && !pev->target) { |
| - reloc_sym = kernel_get_ref_reloc_sym(); |
| + reloc_sym = kernel_get_ref_reloc_sym(NULL); |
| if (!reloc_sym) { |
| pr_warning("Relocated base symbol is not found!\n"); |
| ret = -EINVAL; |