[PATCH 3.16 296/366] tracing: Fix possible double free in event_enable_trigger_func()
From: Ben Hutchings
Date: Sun Nov 11 2018 - 15:35:05 EST
3.16.61-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: "Steven Rostedt (VMware)" <rostedt@xxxxxxxxxxx>
commit 15cc78644d0075e76d59476a4467e7143860f660 upstream.
There was a case that triggered a double free in event_trigger_callback()
due to the called reg() function freeing the trigger_data and then it
getting freed again by the error return by the caller. The solution there
was to up the trigger_data ref count.
Code inspection found that event_enable_trigger_func() has the same issue,
but is not as easy to trigger (requires harder to trigger failures). It
needs to be solved slightly different as it needs more to clean up when the
reg() function fails.
Link: http://lkml.kernel.org/r/20180725124008.7008e586@xxxxxxxxxxxxxxxxxx
Fixes: 7862ad1846e99 ("tracing: Add 'enable_event' and 'disable_event' event trigger commands")
Reivewed-by: Masami Hiramatsu <mhiramat@xxxxxxxxxx>
Signed-off-by: Steven Rostedt (VMware) <rostedt@xxxxxxxxxxx>
Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx>
---
kernel/trace/trace_events_trigger.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/kernel/trace/trace_events_trigger.c
+++ b/kernel/trace/trace_events_trigger.c
@@ -1231,6 +1231,9 @@ event_enable_trigger_func(struct event_c
goto out;
}
+ /* Up the trigger_data count to make sure nothing frees it on failure */
+ event_trigger_init(trigger_ops, trigger_data);
+
if (trigger) {
number = strsep(&trigger, ":");
@@ -1281,6 +1284,7 @@ event_enable_trigger_func(struct event_c
goto out_disable;
/* Just return zero, not the number of enabled functions */
ret = 0;
+ event_trigger_free(trigger_ops, trigger_data);
out:
return ret;
@@ -1291,7 +1295,7 @@ event_enable_trigger_func(struct event_c
out_free:
if (cmd_ops->set_filter)
cmd_ops->set_filter(NULL, trigger_data, NULL);
- kfree(trigger_data);
+ event_trigger_free(trigger_ops, trigger_data);
kfree(enable_data);
goto out;
}