Skip to content

Commit 7bdb157

Browse files
kiyin(尹亮)Ingo Molnar
authored andcommitted
perf/core: Fix a memory leak in perf_event_parse_addr_filter()
As shown through runtime testing, the "filename" allocation is not always freed in perf_event_parse_addr_filter(). There are three possible ways that this could happen: - It could be allocated twice on subsequent iterations through the loop, - or leaked on the success path, - or on the failure path. Clean up the code flow to make it obvious that 'filename' is always freed in the reallocation path and in the two return paths as well. We rely on the fact that kfree(NULL) is NOP and filename is initialized with NULL. This fixes the leak. No other side effects expected. [ Dan Carpenter: cleaned up the code flow & added a changelog. ] [ Ingo Molnar: updated the changelog some more. ] Fixes: 375637b ("perf/core: Introduce address range filtering") Signed-off-by: "kiyin(尹亮)" <kiyin@tencent.com> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Cc: "Srivatsa S. Bhat" <srivatsa@csail.mit.edu> Cc: Anthony Liguori <aliguori@amazon.com> -- kernel/events/core.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
1 parent 659caaf commit 7bdb157

File tree

1 file changed

+5
-7
lines changed

1 file changed

+5
-7
lines changed

kernel/events/core.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10085,6 +10085,7 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
1008510085
if (token == IF_SRC_FILE || token == IF_SRC_FILEADDR) {
1008610086
int fpos = token == IF_SRC_FILE ? 2 : 1;
1008710087

10088+
kfree(filename);
1008810089
filename = match_strdup(&args[fpos]);
1008910090
if (!filename) {
1009010091
ret = -ENOMEM;
@@ -10131,16 +10132,13 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
1013110132
*/
1013210133
ret = -EOPNOTSUPP;
1013310134
if (!event->ctx->task)
10134-
goto fail_free_name;
10135+
goto fail;
1013510136

1013610137
/* look up the path and grab its inode */
1013710138
ret = kern_path(filename, LOOKUP_FOLLOW,
1013810139
&filter->path);
1013910140
if (ret)
10140-
goto fail_free_name;
10141-
10142-
kfree(filename);
10143-
filename = NULL;
10141+
goto fail;
1014410142

1014510143
ret = -EINVAL;
1014610144
if (!filter->path.dentry ||
@@ -10160,13 +10158,13 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
1016010158
if (state != IF_STATE_ACTION)
1016110159
goto fail;
1016210160

10161+
kfree(filename);
1016310162
kfree(orig);
1016410163

1016510164
return 0;
1016610165

10167-
fail_free_name:
10168-
kfree(filename);
1016910166
fail:
10167+
kfree(filename);
1017010168
free_filters_list(filters);
1017110169
kfree(orig);
1017210170

0 commit comments

Comments
 (0)