diff options
author | Han Pingtian <phan@redhat.com> | 2011-01-06 04:39:22 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-06 15:04:46 -0500 |
commit | f006d25a15216a483cec71e886786874f66f9452 (patch) | |
tree | 66420a0098c774f4d8c29bb43f81e2ba967c59cb /tools/perf | |
parent | 4b95f135f606c87e4056b6d7fd3c5781c818858b (diff) |
perf tools: Fix buffer overflow error when specifying all tracepoints
I found when specifying all tracepoints with -e to one of subcommand,
such as 'stat', the program will trigger a buffer overflow error, like
this:
*** buffer overflow detected ***: ./perf terminated
======= Backtrace: =========
/lib64/libc.so.6(__fortify_fail+0x37)[0x382cefb2c7]
....
The tracepoints are separated by comma, something like this:
$ perf stat -a -e `perf list |grep Tracepoint|awk -F'[' '{gsub(/[[:space:]]+/,"",$1);array[FNR]=$1}END{outputs=array[1];for (i=2;i<=FNR;i++){ outputs=outputs "," array[i];};print outputs}'`
The root reason of this problem is that store_event_type() is called for all
events, and will overflow the 'filename' at:
strncat(filename, orgname, strlen(orgname));
This patch fixes it by calling store_event_type() only when the event name has
been found.
LKML-Reference: <20110106093922.GB6713@hpt.nay.redhat.com>
Signed-off-by: Han Pingtian <phan@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/util/parse-events.c | 61 |
1 files changed, 30 insertions, 31 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 649083f27e08..917a0ca521c1 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -490,6 +490,31 @@ parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp, | |||
490 | return EVT_HANDLED_ALL; | 490 | return EVT_HANDLED_ALL; |
491 | } | 491 | } |
492 | 492 | ||
493 | static int store_event_type(const char *orgname) | ||
494 | { | ||
495 | char filename[PATH_MAX], *c; | ||
496 | FILE *file; | ||
497 | int id, n; | ||
498 | |||
499 | sprintf(filename, "%s/", debugfs_path); | ||
500 | strncat(filename, orgname, strlen(orgname)); | ||
501 | strcat(filename, "/id"); | ||
502 | |||
503 | c = strchr(filename, ':'); | ||
504 | if (c) | ||
505 | *c = '/'; | ||
506 | |||
507 | file = fopen(filename, "r"); | ||
508 | if (!file) | ||
509 | return 0; | ||
510 | n = fscanf(file, "%i", &id); | ||
511 | fclose(file); | ||
512 | if (n < 1) { | ||
513 | pr_err("cannot store event ID\n"); | ||
514 | return -EINVAL; | ||
515 | } | ||
516 | return perf_header__push_event(id, orgname); | ||
517 | } | ||
493 | 518 | ||
494 | static enum event_result parse_tracepoint_event(const char **strp, | 519 | static enum event_result parse_tracepoint_event(const char **strp, |
495 | struct perf_event_attr *attr) | 520 | struct perf_event_attr *attr) |
@@ -533,9 +558,13 @@ static enum event_result parse_tracepoint_event(const char **strp, | |||
533 | *strp += strlen(sys_name) + evt_length; | 558 | *strp += strlen(sys_name) + evt_length; |
534 | return parse_multiple_tracepoint_event(sys_name, evt_name, | 559 | return parse_multiple_tracepoint_event(sys_name, evt_name, |
535 | flags); | 560 | flags); |
536 | } else | 561 | } else { |
562 | if (store_event_type(evt_name) < 0) | ||
563 | return EVT_FAILED; | ||
564 | |||
537 | return parse_single_tracepoint_event(sys_name, evt_name, | 565 | return parse_single_tracepoint_event(sys_name, evt_name, |
538 | evt_length, attr, strp); | 566 | evt_length, attr, strp); |
567 | } | ||
539 | } | 568 | } |
540 | 569 | ||
541 | static enum event_result | 570 | static enum event_result |
@@ -778,41 +807,11 @@ modifier: | |||
778 | return ret; | 807 | return ret; |
779 | } | 808 | } |
780 | 809 | ||
781 | static int store_event_type(const char *orgname) | ||
782 | { | ||
783 | char filename[PATH_MAX], *c; | ||
784 | FILE *file; | ||
785 | int id, n; | ||
786 | |||
787 | sprintf(filename, "%s/", debugfs_path); | ||
788 | strncat(filename, orgname, strlen(orgname)); | ||
789 | strcat(filename, "/id"); | ||
790 | |||
791 | c = strchr(filename, ':'); | ||
792 | if (c) | ||
793 | *c = '/'; | ||
794 | |||
795 | file = fopen(filename, "r"); | ||
796 | if (!file) | ||
797 | return 0; | ||
798 | n = fscanf(file, "%i", &id); | ||
799 | fclose(file); | ||
800 | if (n < 1) { | ||
801 | pr_err("cannot store event ID\n"); | ||
802 | return -EINVAL; | ||
803 | } | ||
804 | return perf_header__push_event(id, orgname); | ||
805 | } | ||
806 | |||
807 | int parse_events(const struct option *opt __used, const char *str, int unset __used) | 810 | int parse_events(const struct option *opt __used, const char *str, int unset __used) |
808 | { | 811 | { |
809 | struct perf_event_attr attr; | 812 | struct perf_event_attr attr; |
810 | enum event_result ret; | 813 | enum event_result ret; |
811 | 814 | ||
812 | if (strchr(str, ':')) | ||
813 | if (store_event_type(str) < 0) | ||
814 | return -1; | ||
815 | |||
816 | for (;;) { | 815 | for (;;) { |
817 | memset(&attr, 0, sizeof(attr)); | 816 | memset(&attr, 0, sizeof(attr)); |
818 | ret = parse_event_symbols(&str, &attr); | 817 | ret = parse_event_symbols(&str, &attr); |