forked from Minki/linux
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>
This commit is contained in:
parent
4b95f135f6
commit
f006d25a15
@ -490,6 +490,31 @@ parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp,
|
||||
return EVT_HANDLED_ALL;
|
||||
}
|
||||
|
||||
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 +558,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 +807,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 (;;) {
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
ret = parse_event_symbols(&str, &attr);
|
||||
|
Loading…
Reference in New Issue
Block a user