2011-02-22 09:10:37

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [tip:perf/core] perf probe: Fix error propagation leading to segfault

Commit-ID: fbee632d0ca9f4073a3fefb9a843eac8af036b0f
Gitweb: http://git.kernel.org/tip/fbee632d0ca9f4073a3fefb9a843eac8af036b0f
Author: Arnaldo Carvalho de Melo <[email protected]>
AuthorDate: Mon, 21 Feb 2011 13:23:57 -0300
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Mon, 21 Feb 2011 22:21:27 -0300

perf probe: Fix error propagation leading to segfault

There are two hunks in this patch that stops probe processing as soon as one
error is found, breaking out of loops, the other fix an error propagation that
should return a negative error number but instead was returning the result of
"ret < 0", which is 1 and thus made several error checks fail because they test
agains < 0.

The problem could be triggered by asking for a variable that was optimized out,
fact that should stop the whole probe processing but instead was segfaulting
while installing broken probes:

[root@emilia ~]# probe perf_mmap:55 user_lock_limit
Failed to find the location of user_lock_limit at this address.
Perhaps, it has been optimized out.
Failed to find 'user_lock_limit' in this function.
Add new events:
probe:perf_mmap (on perf_mmap:55 with user_lock_limit)
probe:perf_mmap_1 (on perf_mmap:55 with user_lock_limit)
Segmentation fault (core dumped)
[root@emilia ~]# perf probe -l
probe:perf_mmap (on perf_mmap:55@git/linux/kernel/perf_event.c with user_lock_limit)
probe:perf_mmap_1 (on perf_mmap:55@git/linux/kernel/perf_event.c with user_lock_limit)
[root@emilia ~]#

After the fix:

[root@emilia ~]# probe perf_mmap:55 user_lock_limit
Failed to find the location of user_lock_limit at this address.
Perhaps, it has been optimized out.
Failed to find 'user_lock_limit' in this function.
Error: Failed to add events. (-2)
[root@emilia ~]#

Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Cc: Tom Zanussi <[email protected]>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/probe-event.c | 5 ++++-
tools/perf/util/probe-finder.c | 4 +++-
2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 0e3ea13..369ddc6 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1832,9 +1832,12 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
}

/* Loop 2: add all events */
- for (i = 0; i < npevs && ret >= 0; i++)
+ for (i = 0; i < npevs && ret >= 0; i++) {
ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
pkgs[i].ntevs, force_add);
+ if (ret < 0)
+ break;
+ }
end:
/* Loop 3: cleanup and free trace events */
for (i = 0; i < npevs; i++) {
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index fe461f6..eecbdca 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1262,7 +1262,7 @@ static int probe_point_line_walker(const char *fname, int lineno,
ret = call_probe_finder(NULL, pf);

/* Continue if no error, because the line will be in inline function */
- return ret < 0 ?: 0;
+ return ret < 0 ? ret : 0;
}

/* Find probe point from its line number */
@@ -1484,6 +1484,8 @@ static int find_probes(int fd, struct probe_finder *pf)
pf->lno = pp->line;
ret = find_probe_point_by_line(pf);
}
+ if (ret != DWARF_CB_OK)
+ break;
}
off = noff;
}