[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <1437119926-17022-1-git-send-email-wangnan0@huawei.com>
Date: Fri, 17 Jul 2015 07:58:46 +0000
From: Wang Nan <wangnan0@...wei.com>
To: <rostedt@...dmis.org>, <hekuang@...wei.com>
CC: <ast@...mgrid.com>, <acme@...nel.org>, <a.p.zijlstra@...llo.nl>,
<mingo@...hat.com>, <namhyung@...nel.org>, <jolsa@...nel.org>,
<pi3orama@....com>, <linux-kernel@...r.kernel.org>
Subject: [PATCH] tools lib traceevent: Fix double free corruption in error processing code
When kernel introduces new function to 'format' file before traceevent
update correspondingly, a double-free corruption occures if the newly
intorduced function resides in following format:
# cat /sys/kernel/debug/tracing/events/bpf/bpf_output_data/format
...
print fmt: "%s", __print_hex(__get_dynamic_array(buf), __get_dynamic_array_len(buf))
...
(where __get_dynamic_array_len is the new function)
And:
# perf record -e bpf:bpf_output_data ls
Warning: [bpf:bpf_output_data] function __get_dynamic_array_len not defined
Warning: Error: expected type 5 but read 0
*** Error in `/path/to/perf': double free or corruption (fasttop): 0x0000000001821210 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x6eeef)[0x7f86a4cf6eef]
/lib64/libc.so.6(+0x78cae)[0x7f86a4d00cae]
/lib64/libc.so.6(+0x79987)[0x7f86a4d01987]
/path/to/perf[0x51b0e2]
/path/to/perf[0x51afc2]
/path/to/perf[0x51fe67]
/path/to/perf[0x5200a5]
/path/to/perf(__pevent_parse_format+0x185)[0x525bc9]
/path/to/perf[0x525d82]
/path/to/perf(pevent_parse_format+0x3b)[0x525e15]
/path/to/perf[0x4ceb61]
/path/to/perf(perf_evsel__newtp_idx+0x9f)[0x48cabf]
/path/to/perf(parse_events_add_tracepoint+0x25b)[0x49782b]
/path/to/perf(parse_events_parse+0x10a3)[0x4c8243]
/path/to/perf(parse_events+0x75)[0x498ce5]
/path/to/perf(parse_events_option+0x41)[0x498df1]
/path/to/perf[0x493e9b]
/path/to/perf(parse_options+0x215)[0x4957c5]
/path/to/perf(cmd_record+0x6a)[0x43c4ba]
/path/to/perf[0x47b2a3]
/path/to/perf(main+0x5f6)[0x42fed6]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f86a4ca9bd5]
/path/to/perf[0x430005]
======= Memory map: ========
00400000-006b9000 r-xp 00000000 08:05 23596607 /path/to/perf
008b9000-00903000 rw-p 002b9000 08:05 23596607 /path/to/perf
This is caused by error processing code in process_hex() which frees
arg->hex.field but doesn't set it to NULL. When event_read_print_args()
freeing the hex arg, the dangling pointer will be free again and cause
the above error. process_int_array() has similar problem.
This patch fixes the dangling pointer problem by not setting them until
everything is okay.
Signed-off-by: Wang Nan <wangnan0@...wei.com>
Cc: Steven Rostedt <rostedt@...dmis.org>
Cc: Alexei Starovoitov <ast@...mgrid.com>
Cc: Arnaldo Carvalho de Melo <acme@...nel.org>
Cc: Peter Zijlstra <a.p.zijlstra@...llo.nl>
Cc: Ingo Molnar <mingo@...hat.com>
Cc: Namhyung Kim <namhyung@...nel.org>
Cc: Jiri Olsa <jolsa@...nel.org>
Cc: <pi3orama@....com>
---
tools/lib/traceevent/event-parse.c | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index cc25f05..8d662b5 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -2546,19 +2546,23 @@ out_free:
static enum event_type
process_hex(struct event_format *event, struct print_arg *arg, char **tok)
{
+ struct print_arg *field, *size;
+
memset(arg, 0, sizeof(*arg));
arg->type = PRINT_HEX;
- if (alloc_and_process_delim(event, ",", &arg->hex.field))
+ if (alloc_and_process_delim(event, ",", &field))
goto out;
- if (alloc_and_process_delim(event, ")", &arg->hex.size))
+ if (alloc_and_process_delim(event, ")", &size))
goto free_field;
+ arg->hex.field = field;
+ arg->hex.size = size;
return read_token_item(tok);
free_field:
- free_arg(arg->hex.field);
+ free_arg(field);
out:
*tok = NULL;
return EVENT_ERROR;
@@ -2567,24 +2571,29 @@ out:
static enum event_type
process_int_array(struct event_format *event, struct print_arg *arg, char **tok)
{
+ struct print_arg *field, *count, *el_size;
+
memset(arg, 0, sizeof(*arg));
arg->type = PRINT_INT_ARRAY;
- if (alloc_and_process_delim(event, ",", &arg->int_array.field))
+ if (alloc_and_process_delim(event, ",", &field))
goto out;
- if (alloc_and_process_delim(event, ",", &arg->int_array.count))
+ if (alloc_and_process_delim(event, ",", &count))
goto free_field;
- if (alloc_and_process_delim(event, ")", &arg->int_array.el_size))
+ if (alloc_and_process_delim(event, ")", &el_size))
goto free_size;
+ arg->int_array.field = field;
+ arg->int_array.count = count;
+ arg->int_array.el_size = el_size;
return read_token_item(tok);
free_size:
- free_arg(arg->int_array.count);
+ free_arg(count);
free_field:
- free_arg(arg->int_array.field);
+ free_arg(field);
out:
*tok = NULL;
return EVENT_ERROR;
--
1.8.3.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists