| From foo@baz Thu 30 Jul 2020 09:36:06 AM CEST |
| From: Masami Hiramatsu <mhiramat@kernel.org> |
| Date: Tue, 30 Jun 2020 23:45:40 +0900 |
| Subject: perf probe: Fix to check blacklist address correctly |
| To: stable@vger.kernel.org |
| Cc: Changbin Du <changbin.du@gmail.com>, Jiri Olsa <jolsa@redhat.com>, Arnaldo Carvalho de Melo <acme@redhat.com>, mhiramat@kernel.org |
| Message-ID: <159352834007.45385.3483905196357537826.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 |
| @@ -118,7 +118,7 @@ static struct symbol *__find_kernel_func |
| return machine__find_kernel_function(host_machine, addr, mapp); |
| } |
| |
| -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; |
| @@ -130,6 +130,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; |
| } |
| |
| @@ -141,7 +145,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 { |
| @@ -742,6 +746,7 @@ post_process_kernel_probe_trace_events(s |
| int ntevs) |
| { |
| struct ref_reloc_sym *reloc_sym; |
| + struct map *map; |
| char *tmp; |
| int i, skipped = 0; |
| |
| @@ -750,7 +755,7 @@ post_process_kernel_probe_trace_events(s |
| return post_process_offline_probe_trace_events(tevs, ntevs, |
| symbol_conf.vmlinux_name); |
| |
| - 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; |
| @@ -759,9 +764,13 @@ post_process_kernel_probe_trace_events(s |
| 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 { |
| @@ -2850,7 +2859,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; |