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;
|
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,
|
static enum event_result parse_tracepoint_event(const char **strp,
|
||||||
struct perf_event_attr *attr)
|
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;
|
*strp += strlen(sys_name) + evt_length;
|
||||||
return parse_multiple_tracepoint_event(sys_name, evt_name,
|
return parse_multiple_tracepoint_event(sys_name, evt_name,
|
||||||
flags);
|
flags);
|
||||||
} else
|
} else {
|
||||||
|
if (store_event_type(evt_name) < 0)
|
||||||
|
return EVT_FAILED;
|
||||||
|
|
||||||
return parse_single_tracepoint_event(sys_name, evt_name,
|
return parse_single_tracepoint_event(sys_name, evt_name,
|
||||||
evt_length, attr, strp);
|
evt_length, attr, strp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum event_result
|
static enum event_result
|
||||||
@ -778,41 +807,11 @@ parse_event_symbols(const char **str, struct perf_event_attr *attr)
|
|||||||
return ret;
|
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)
|
int parse_events(const struct option *opt __used, const char *str, int unset __used)
|
||||||
{
|
{
|
||||||
struct perf_event_attr attr;
|
struct perf_event_attr attr;
|
||||||
enum event_result ret;
|
enum event_result ret;
|
||||||
|
|
||||||
if (strchr(str, ':'))
|
|
||||||
if (store_event_type(str) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
memset(&attr, 0, sizeof(attr));
|
memset(&attr, 0, sizeof(attr));
|
||||||
ret = parse_event_symbols(&str, &attr);
|
ret = parse_event_symbols(&str, &attr);
|
||||||
|
Loading…
Reference in New Issue
Block a user