Re: [PATCH 1/3] [BUGFIX] tracing: Fix double free of event_trigger_data

From: Masami Hiramatsu
Date: Tue Jul 24 2018 - 21:16:59 EST


On Tue, 24 Jul 2018 19:13:31 -0400
Steven Rostedt <rostedt@xxxxxxxxxxx> wrote:

> On Tue, 24 Jul 2018 17:30:08 -0400
> Steven Rostedt <rostedt@xxxxxxxxxxx> wrote:
>
> > I don't see where ->reg() would return anything but 1 on success. Maybe
> > I'm missing something. I'll look some more, but I'm thinking of changing
> > ->reg() to return zero on all success, and negative on all errors and
> > just check those results.
>
> Yeah, I'm going to make these changes. That is, all struct
> event_command .reg functions will return negative on error, and
> zero or positive on everything else. All the checks are going to be
> only for the negative value.
>
> But for the bug fix itself, I believe this should do it. Masami, what
> do you think?

Hm, as far as I can see, when register_trigger() returns >= 0, it already
calls ->init the trigger_data. This means its refcount++, and in that
case, below patch will miss to free the trigger_data.
How about below for tentative fix?

if (!ret) {
ret = -ENOENT;
/* We have to forcibly free the trigger_data */
goto out_free;
} else if (ret > 0)
ret = 0;

Thank you,

>
> -- Steve
>
> diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c
> index d18249683682..8771a27ca60f 100644
> --- a/kernel/trace/trace_events_trigger.c
> +++ b/kernel/trace/trace_events_trigger.c
> @@ -679,6 +679,8 @@ event_trigger_callback(struct event_command *cmd_ops,
> goto out_free;
>
> out_reg:
> + /* Up the trigger_data count to make sure reg doesn't free it on failure */
> + event_trigger_init(trigger_ops, trigger_data);
> ret = cmd_ops->reg(glob, trigger_ops, trigger_data, file);
> /*
> * The above returns on success the # of functions enabled,
> @@ -687,10 +689,11 @@ event_trigger_callback(struct event_command *cmd_ops,
> */
> if (!ret) {
> ret = -ENOENT;
> - goto out_free;
> - } else if (ret < 0)
> - goto out_free;
> - ret = 0;
> + } else if (ret > 0)
> + ret = 0;
> +
> + /* Down the counter of trigger_data or free it if not used anymore */
> + event_trigger_free(trigger_ops, trigger_data);
> out:
> return ret;
>


--
Masami Hiramatsu <mhiramat@xxxxxxxxxx>