2022-04-22 19:31:11

by Keita Suzuki

[permalink] [raw]
Subject: [PATCH] tracing: Fix potential double free in create_var_ref()

In create_var_ref(), init_var_ref() is called to initialize the fields
of variable ref_field, which is allocated in the previous function call
to create_hist_field(). Function init_var_ref() allocates the
corresponding fields such as ref_field->system, but frees these fields
when the function encounters an error. The caller later calls
destroy_hist_field() to conduct error handling, which frees the fields
and the variable itself. This results in double free of the fields which
are already freed in the previous function.

Fix this by storing NULL to the corresponding fields when they are freed
in init_var_ref().

Signed-off-by: Keita Suzuki <[email protected]>
---
kernel/trace/trace_events_hist.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index 44db5ba9cabb..a0e41906d9ce 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -2093,8 +2093,11 @@ static int init_var_ref(struct hist_field *ref_field,
return err;
free:
kfree(ref_field->system);
+ ref_field->system = NULL;
kfree(ref_field->event_name);
+ ref_field->event_name = NULL;
kfree(ref_field->name);
+ ref_field->name = NULL;

goto out;
}
--
2.25.1


2022-04-22 21:45:43

by Masami Hiramatsu

[permalink] [raw]
Subject: Re: [PATCH] tracing: Fix potential double free in create_var_ref()

Hi Keita,

On Fri, 22 Apr 2022 06:00:25 +0000
Keita Suzuki <[email protected]> wrote:

> In create_var_ref(), init_var_ref() is called to initialize the fields
> of variable ref_field, which is allocated in the previous function call
> to create_hist_field(). Function init_var_ref() allocates the
> corresponding fields such as ref_field->system, but frees these fields
> when the function encounters an error. The caller later calls
> destroy_hist_field() to conduct error handling, which frees the fields
> and the variable itself. This results in double free of the fields which
> are already freed in the previous function.
>
> Fix this by storing NULL to the corresponding fields when they are freed
> in init_var_ref().
>

Good catch! this looks good to me.

Reviewed-by: Masami Hiramatsu <[email protected]>


BTW, could you Cc the original code authoer and if you fix a bug and
add Fixes: tag? That will help the original author can check the bug and
help stable kernel maintainers to pick the patch. :)

To find the original commit, you can use the 'git blame'.

$ git blame kernel/trace/trace_events_hist.c -L 2093,2100
067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2093) return err;
067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2094) free:
067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2095) kfree(ref_field->system);
067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2096) kfree(ref_field->event_name);
067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2097) kfree(ref_field->name);
067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2098)
067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2099) goto out;
067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2100) }

Then, git show will tell you the original author.
$ git show 067fe038e70f6

And get the format of the commit for Fixes tag.

$ git --no-pager show -s --abbrev-commit --abbrev=12 --pretty=format:"%h (\"%s\")%n" 067fe038e70f6
067fe038e70f ("tracing: Add variable reference handling to hist triggers")

Then you can add lines like:

Fixes: 067fe038e70f ("tracing: Add variable reference handling to hist triggers")
Cc: [email protected]

Thank you,

> Signed-off-by: Keita Suzuki <[email protected]>
> ---
> kernel/trace/trace_events_hist.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
> index 44db5ba9cabb..a0e41906d9ce 100644
> --- a/kernel/trace/trace_events_hist.c
> +++ b/kernel/trace/trace_events_hist.c
> @@ -2093,8 +2093,11 @@ static int init_var_ref(struct hist_field *ref_field,
> return err;
> free:
> kfree(ref_field->system);
> + ref_field->system = NULL;
> kfree(ref_field->event_name);
> + ref_field->event_name = NULL;
> kfree(ref_field->name);
> + ref_field->name = NULL;
>
> goto out;
> }
> --
> 2.25.1
>


--
Masami Hiramatsu <[email protected]>

2022-04-25 14:36:12

by Keita Suzuki

[permalink] [raw]
Subject: [PATCH V2] tracing: Fix potential double free in create_var_ref()

In create_var_ref(), init_var_ref() is called to initialize the fields
of variable ref_field, which is allocated in the previous function call
to create_hist_field(). Function init_var_ref() allocates the
corresponding fields such as ref_field->system, but frees these fields
when the function encounters an error. The caller later calls
destroy_hist_field() to conduct error handling, which frees the fields
and the variable itself. This results in double free of the fields which
are already freed in the previous function.

Fix this by storing NULL to the corresponding fields when they are freed
in init_var_ref().

Fixes: 067fe038e70f ("tracing: Add variable reference handling to hist triggers")
CC: [email protected]
Signed-off-by: Keita Suzuki <[email protected]>
Reviewed-by: Masami Hiramatsu <[email protected]>
---
kernel/trace/trace_events_hist.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index 44db5ba9cabb..a0e41906d9ce 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -2093,8 +2093,11 @@ static int init_var_ref(struct hist_field *ref_field,
return err;
free:
kfree(ref_field->system);
+ ref_field->system = NULL;
kfree(ref_field->event_name);
+ ref_field->event_name = NULL;
kfree(ref_field->name);
+ ref_field->name = NULL;

goto out;
}
--
2.25.1

2022-04-25 20:39:02

by Keita Suzuki

[permalink] [raw]
Subject: Re: [PATCH] tracing: Fix potential double free in create_var_ref()

Hi Masami,

Thanks for the review!
I'll add the info and resend the patch.

Thanks,
Keita

2022年4月23日(土) 0:13 Masami Hiramatsu <[email protected]>:
>
> Hi Keita,
>
> On Fri, 22 Apr 2022 06:00:25 +0000
> Keita Suzuki <[email protected]> wrote:
>
> > In create_var_ref(), init_var_ref() is called to initialize the fields
> > of variable ref_field, which is allocated in the previous function call
> > to create_hist_field(). Function init_var_ref() allocates the
> > corresponding fields such as ref_field->system, but frees these fields
> > when the function encounters an error. The caller later calls
> > destroy_hist_field() to conduct error handling, which frees the fields
> > and the variable itself. This results in double free of the fields which
> > are already freed in the previous function.
> >
> > Fix this by storing NULL to the corresponding fields when they are freed
> > in init_var_ref().
> >
>
> Good catch! this looks good to me.
>
> Reviewed-by: Masami Hiramatsu <[email protected]>
>
>
> BTW, could you Cc the original code authoer and if you fix a bug and
> add Fixes: tag? That will help the original author can check the bug and
> help stable kernel maintainers to pick the patch. :)
>
> To find the original commit, you can use the 'git blame'.
>
> $ git blame kernel/trace/trace_events_hist.c -L 2093,2100
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2093) return err;
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2094) free:
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2095) kfree(ref_field->system);
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2096) kfree(ref_field->event_name);
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2097) kfree(ref_field->name);
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2098)
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2099) goto out;
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2100) }
>
> Then, git show will tell you the original author.
> $ git show 067fe038e70f6
>
> And get the format of the commit for Fixes tag.
>
> $ git --no-pager show -s --abbrev-commit --abbrev=12 --pretty=format:"%h (\"%s\")%n" 067fe038e70f6
> 067fe038e70f ("tracing: Add variable reference handling to hist triggers")
>
> Then you can add lines like:
>
> Fixes: 067fe038e70f ("tracing: Add variable reference handling to hist triggers")
> Cc: [email protected]
>
> Thank you,
>
> > Signed-off-by: Keita Suzuki <[email protected]>
> > ---
> > kernel/trace/trace_events_hist.c | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
> > index 44db5ba9cabb..a0e41906d9ce 100644
> > --- a/kernel/trace/trace_events_hist.c
> > +++ b/kernel/trace/trace_events_hist.c
> > @@ -2093,8 +2093,11 @@ static int init_var_ref(struct hist_field *ref_field,
> > return err;
> > free:
> > kfree(ref_field->system);
> > + ref_field->system = NULL;
> > kfree(ref_field->event_name);
> > + ref_field->event_name = NULL;
> > kfree(ref_field->name);
> > + ref_field->name = NULL;
> >
> > goto out;
> > }
> > --
> > 2.25.1
> >
>
>
> --
> Masami Hiramatsu <[email protected]>

2022-04-26 00:17:39

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH V2] tracing: Fix potential double free in create_var_ref()

On Mon, 25 Apr 2022 06:37:38 +0000
Keita Suzuki <[email protected]> wrote:

FYI, always send a new version of a patch as a separate thread, never as a
reply-to of a previous version. That breaks tools like patchwork which will
not show this version of the patch.

> In create_var_ref(), init_var_ref() is called to initialize the fields
> of variable ref_field, which is allocated in the previous function call
> to create_hist_field(). Function init_var_ref() allocates the
> corresponding fields such as ref_field->system, but frees these fields
> when the function encounters an error. The caller later calls
> destroy_hist_field() to conduct error handling, which frees the fields
> and the variable itself. This results in double free of the fields which
> are already freed in the previous function.
>
> Fix this by storing NULL to the corresponding fields when they are freed
> in init_var_ref().
>
> Fixes: 067fe038e70f ("tracing: Add variable reference handling to hist triggers")
> CC: [email protected]
> Signed-off-by: Keita Suzuki <[email protected]>
> Reviewed-by: Masami Hiramatsu <[email protected]>
> ---
> kernel/trace/trace_events_hist.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
> index 44db5ba9cabb..a0e41906d9ce 100644
> --- a/kernel/trace/trace_events_hist.c
> +++ b/kernel/trace/trace_events_hist.c
> @@ -2093,8 +2093,11 @@ static int init_var_ref(struct hist_field *ref_field,
> return err;
> free:
> kfree(ref_field->system);
> + ref_field->system = NULL;
> kfree(ref_field->event_name);
> + ref_field->event_name = NULL;
> kfree(ref_field->name);
> + ref_field->name = NULL;

Nit, but it would look nicer as:

kfree(ref_field->system);
kfree(ref_field->event_name);
kfree(ref_field->name);

ref_field->system = NULL;
ref_field->event_name = NULL;
ref_field->name = NULL;


-- Steve

>
> goto out;
> }

2022-04-26 08:53:06

by Tom Zanussi

[permalink] [raw]
Subject: Re: [PATCH] tracing: Fix potential double free in create_var_ref()

On Sat, 2022-04-23 at 00:13 +0900, Masami Hiramatsu wrote:
> Hi Keita,
>
> On Fri, 22 Apr 2022 06:00:25 +0000
> Keita Suzuki <[email protected]> wrote:
>
> > In create_var_ref(), init_var_ref() is called to initialize the
> > fields
> > of variable ref_field, which is allocated in the previous function
> > call
> > to create_hist_field(). Function init_var_ref() allocates the
> > corresponding fields such as ref_field->system, but frees these
> > fields
> > when the function encounters an error. The caller later calls
> > destroy_hist_field() to conduct error handling, which frees the
> > fields
> > and the variable itself. This results in double free of the fields
> > which
> > are already freed in the previous function.
> >
> > Fix this by storing NULL to the corresponding fields when they are
> > freed
> > in init_var_ref().
> >
>
> Good catch! this looks good to me.
>
> Reviewed-by: Masami Hiramatsu <[email protected]>


Looks fine to me too, thanks,

Reviewed-by: Tom Zanussi <[email protected]>


>
>
> BTW, could you Cc the original code authoer and if you fix a bug and
> add Fixes: tag? That will help the original author can check the bug
> and
> help stable kernel maintainers to pick the patch. :)
>
> To find the original commit, you can use the 'git blame'.
>
> $ git blame kernel/trace/trace_events_hist.c -L 2093,2100
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600
> 2093) return err;
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2094) free:
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600
> 2095) kfree(ref_field->system);
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600
> 2096) kfree(ref_field->event_name);
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600
> 2097) kfree(ref_field->name);
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2098)
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2099) goto
> out;
> 067fe038e70f6 (Tom Zanussi 2018-01-15 20:51:56 -0600 2100) }
>
> Then, git show will tell you the original author.
> $ git show 067fe038e70f6
>
> And get the format of the commit for Fixes tag.
>
> $ git --no-pager show -s --abbrev-commit --abbrev=12 --
> pretty=format:"%h (\"%s\")%n" 067fe038e70f6
> 067fe038e70f ("tracing: Add variable reference handling to hist
> triggers")
>
> Then you can add lines like:
>
> Fixes: 067fe038e70f ("tracing: Add variable reference handling to
> hist triggers")
> Cc: [email protected]
>
> Thank you,
>
> > Signed-off-by: Keita Suzuki <[email protected]>
> > ---
> > kernel/trace/trace_events_hist.c | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/kernel/trace/trace_events_hist.c
> > b/kernel/trace/trace_events_hist.c
> > index 44db5ba9cabb..a0e41906d9ce 100644
> > --- a/kernel/trace/trace_events_hist.c
> > +++ b/kernel/trace/trace_events_hist.c
> > @@ -2093,8 +2093,11 @@ static int init_var_ref(struct hist_field
> > *ref_field,
> > return err;
> > free:
> > kfree(ref_field->system);
> > + ref_field->system = NULL;
> > kfree(ref_field->event_name);
> > + ref_field->event_name = NULL;
> > kfree(ref_field->name);
> > + ref_field->name = NULL;
> >
> > goto out;
> > }
> > --
> > 2.25.1
> >
>
>