perf: fix buffer overflow error caused by specifying all tracepoints with -e option
PATCH 1/1 perf: fix buffer overflow error caused by specifying all tracepoints with -e option
Hi,
I found specifying all tracepoints within one "-e" option to perf top, separating each other with commas, will trigger a buffer overflow.
The command line is:
./perf to -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 error messages are:
*** buffer overflow detected ***: ./perf terminated ======= Backtrace: ========= /lib64/libc.so.6(__fortify_fail+0x37)[0x382cefb2c7] /lib64/libc.so.6[0x382cef91c0] /lib64/libc.so.6[0x382cef82f4] ./perf[0x424f9e]
./perf[0x425966]
./perf[0x42422b]
./perf[0x424468]
./perf[0x424a30]
./perf[0x41539a]
./perf[0x4056d4]
./perf[0x406126] /lib64/libc.so.6(__libc_start_main+0xfd)[0x382ce1ec5d] ./perf[0x405409]
======= Memory map: ========
00400000-0051c000 r-xp 00000000 fd:06 4573758 /home/hpt/temp/linux/perf/linux-2.6/tools/perf/perf
0071b000-00733000 rwxp 0011b000 fd:06 4573758 /home/hpt/temp/linux/perf/linux-2.6/tools/perf/perf
00733000-00b90000 rwxp 00000000 00:00 0
024dc000-024fd000 rwxp 00000000 00:00 0 [heap]
... ...
And I have a patch for fixing this problem. Please review it. Thanks.
PATCH 1/1 perf: fix buffer overflow error caused by specifying all tracepoints with -e option
I found when specifying all tracepoints with -e to one of subcommand, such as 'top', the program will trigger a buffer overflow error, like this:
*** buffer overflow detected ***: ./perf terminated
======= Backtrace: =========
/lib64/libc.so.6(__fortify_fail+0x37)[0x382cefb2c7] /lib64/libc.so.6[0x382cef91c0]
/lib64/libc.so.6[0x382cef82f4]
./perf[0x4250ee]
./perf[0x425ab6]
./perf[0x42437b]
./perf[0x4245b8]
./perf[0x424b80]
./perf[0x41548a]
./perf[0x405764]
./perf[0x4061b6]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x382ce1ec5d]
./perf[0x405499]
======= Memory map: ========
00400000-0051d000 r-xp 00000000 fd:06 4573549 /home/hpt/temp/linux/perf/linux-2.6/tools/perf/perf
....
The tracepoints are separated by comma, something like this:
perf top -e ...,kmem:kmalloc,kmem:kfree,kmem:kmem_cache_free,...
This comment will fix this problem.
The root reason of this problem is that store_event_type() is called with all the events, and will overflow the 'filename' at
strncat(filename, orgname, strlen(orgname));
The comments will try to call store_event_type() when the event name has been found out.
--- tools/perf/util/parse-events.c | 62 ++++++++++++++++++++-------------------- 1 files changed, 31 insertions(+), 31 deletions(-)
tools/perf/util/parse-events.c +31 -31
@@ -491,6 +491,32 @@ parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp, } +static int store_event_type (const char *orgname) +{ +char filename[PATH_MAX ], *c; +FILE *file; +int id, n; + +sprintf (filename,"%s/" , debugfs_path); +strncat (filename, orgname,strlen (orgname)); +strcat (filename,"/id" ); + + c =strchr (filename,':' ); +if (c) + *c ='/' ; + + file =fopen (filename,"r" ); +if (!file) +return 0 ; + n =fscanf (file,"%i" , &id); +fclose (file); +if (n <1 ) { +pr_err ("cannot store event ID\n" ); +return -EINVAL ; + } +return perf_header__push_event (id, orgname); +} +static enum event_result parse_tracepoint_event (const char **strp,struct perf_event_attr *attr) {
@@ -533,9 +559,13 @@ static enum event_result parse_tracepoint_event(const char **strp, *strp +=strlen (sys_name) + evt_length;return parse_multiple_tracepoint_event (sys_name, evt_name, flags); - }else + }else { +if (store_event_type (evt_name) <0 ) +return EVT_FAILED ; +return parse_single_tracepoint_event (sys_name, evt_name, evt_length, attr, strp); + } } static enum event_result
@@ -778,41 +808,11 @@ modifier:return ret; } -static int store_event_type (const char *orgname) -{ -char filename[PATH_MAX ], *c; -FILE *file; -int id, n; - -sprintf (filename,"%s/" , debugfs_path); -strncat (filename, orgname,strlen (orgname)); -strcat (filename,"/id" ); - - c =strchr (filename,':' ); -if (c) - *c ='/' ; - - file =fopen (filename,"r" ); -if (!file) -return 0 ; - n =fscanf (file,"%i" , &id); -fclose (file); -if (n <1 ) { -pr_err ("cannot store event ID\n" ); -return -EINVAL ; - } -return perf_header__push_event (id, orgname); -} -int parse_events (const struct option *opt__used ,const char *str,int unset__used ) {struct perf_event_attr attr;enum event_result ret; -if (strchr (str,':' )) -if (store_event_type (str) <0 ) -return -1 ; -for (;;) {if (nr_counters ==MAX_COUNTERS )return -1 ;
Signature · 1 line
1.7.1