lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
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

Powered by Openwall GNU/*/Linux Powered by OpenVZ