Skip to content

Commit 31d68e7

Browse files
committed
perf annotate: Validate addr in symbol__inc_addr_samples
This routine was checking only if the provided address was after sym->end, not if it was before sym->start. Fix that by checking for both and return in both cases -ERANGE, so that tools can communicate this to the user properly, or if they chose so, to abort. This problem was reported previously but the fixes involved either doing what was being done for the > end case, i.e. silently drop the sample, returning 0, or aborting at this function, which is in a lib (or better, is slated to be at some point) and shouldn't abort. The 'report' tool already checks this value and uses pr_debug to warn the user. This patch makes the 'top' tool check it too and warn once per map where such range problem takes place. Reported-by: David Miller <[email protected]> Reported-by: Sorin Dumitru <[email protected]> Reported-by: Stephane Eranian <[email protected]> Cc: David Ahern <[email protected]> Cc: Frederic Weisbecker <[email protected]> Cc: Mike Galbraith <[email protected]> Cc: Paul Mackerras <[email protected]> Cc: Peter Zijlstra <[email protected]> Link: http://lkml.kernel.org/n/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 8493fe1 commit 31d68e7

File tree

4 files changed

+38
-3
lines changed

4 files changed

+38
-3
lines changed

tools/perf/builtin-top.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "util/debug.h"
4343

4444
#include <assert.h>
45+
#include <elf.h>
4546
#include <fcntl.h>
4647

4748
#include <stdio.h>
@@ -59,6 +60,7 @@
5960
#include <sys/prctl.h>
6061
#include <sys/wait.h>
6162
#include <sys/uio.h>
63+
#include <sys/utsname.h>
6264
#include <sys/mman.h>
6365

6466
#include <linux/unistd.h>
@@ -162,12 +164,40 @@ static void __zero_source_counters(struct hist_entry *he)
162164
symbol__annotate_zero_histograms(sym);
163165
}
164166

167+
static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
168+
{
169+
struct utsname uts;
170+
int err = uname(&uts);
171+
172+
ui__warning("Out of bounds address found:\n\n"
173+
"Addr: %" PRIx64 "\n"
174+
"DSO: %s %c\n"
175+
"Map: %" PRIx64 "-%" PRIx64 "\n"
176+
"Symbol: %" PRIx64 "-%" PRIx64 " %c %s\n"
177+
"Arch: %s\n"
178+
"Kernel: %s\n"
179+
"Tools: %s\n\n"
180+
"Not all samples will be on the annotation output.\n\n"
181+
"Please report to [email protected]\n",
182+
ip, map->dso->long_name, dso__symtab_origin(map->dso),
183+
map->start, map->end, sym->start, sym->end,
184+
sym->binding == STB_GLOBAL ? 'g' :
185+
sym->binding == STB_LOCAL ? 'l' : 'w', sym->name,
186+
err ? "[unknown]" : uts.machine,
187+
err ? "[unknown]" : uts.release, perf_version_string);
188+
if (use_browser <= 0)
189+
sleep(5);
190+
191+
map->erange_warned = true;
192+
}
193+
165194
static void perf_top__record_precise_ip(struct perf_top *top,
166195
struct hist_entry *he,
167196
int counter, u64 ip)
168197
{
169198
struct annotation *notes;
170199
struct symbol *sym;
200+
int err;
171201

172202
if (he == NULL || he->ms.sym == NULL ||
173203
((top->sym_filter_entry == NULL ||
@@ -189,9 +219,12 @@ static void perf_top__record_precise_ip(struct perf_top *top,
189219
}
190220

191221
ip = he->ms.map->map_ip(he->ms.map, ip);
192-
symbol__inc_addr_samples(sym, he->ms.map, counter, ip);
222+
err = symbol__inc_addr_samples(sym, he->ms.map, counter, ip);
193223

194224
pthread_mutex_unlock(&notes->lock);
225+
226+
if (err == -ERANGE && !he->ms.map->erange_warned)
227+
ui__warn_map_erange(he->ms.map, sym, ip);
195228
}
196229

197230
static void perf_top__show_details(struct perf_top *top)

tools/perf/util/annotate.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
6464

6565
pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
6666

67-
if (addr > sym->end)
68-
return 0;
67+
if (addr < sym->start || addr > sym->end)
68+
return -ERANGE;
6969

7070
offset = addr - sym->start;
7171
h = annotation__histogram(notes, evidx);

tools/perf/util/map.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ void map__init(struct map *self, enum map_type type,
3838
RB_CLEAR_NODE(&self->rb_node);
3939
self->groups = NULL;
4040
self->referenced = false;
41+
self->erange_warned = false;
4142
}
4243

4344
struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,

tools/perf/util/map.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct map {
3333
u64 end;
3434
u8 /* enum map_type */ type;
3535
bool referenced;
36+
bool erange_warned;
3637
u32 priv;
3738
u64 pgoff;
3839

0 commit comments

Comments
 (0)