Skip to content

Commit ea53664

Browse files
kiyin(尹亮)shiloong
authored andcommitted
perf/core: Fix a memory leak in perf_event_parse_addr_filter()
to #31887426 commit 7bdb157 upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Fixes: CVE-2020-25704 Signed-off-by: Shile Zhang <shile.zhang@linux.alibaba.com> Acked-by: Michael Wang <yun.wang@linux.alibaba.com>
1 parent e07a49d commit ea53664

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
@@ -9034,6 +9034,7 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
90349034
if (token == IF_SRC_FILE || token == IF_SRC_FILEADDR) {
90359035
int fpos = token == IF_SRC_FILE ? 2 : 1;
90369036

9037+
kfree(filename);
90379038
filename = match_strdup(&args[fpos]);
90389039
if (!filename) {
90399040
ret = -ENOMEM;
@@ -9080,16 +9081,13 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
90809081
*/
90819082
ret = -EOPNOTSUPP;
90829083
if (!event->ctx->task)
9083-
goto fail_free_name;
9084+
goto fail;
90849085

90859086
/* look up the path and grab its inode */
90869087
ret = kern_path(filename, LOOKUP_FOLLOW,
90879088
&filter->path);
90889089
if (ret)
9089-
goto fail_free_name;
9090-
9091-
kfree(filename);
9092-
filename = NULL;
9090+
goto fail;
90939091

90949092
ret = -EINVAL;
90959093
if (!filter->path.dentry ||
@@ -9109,13 +9107,13 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
91099107
if (state != IF_STATE_ACTION)
91109108
goto fail;
91119109

9110+
kfree(filename);
91129111
kfree(orig);
91139112

91149113
return 0;
91159114

9116-
fail_free_name:
9117-
kfree(filename);
91189115
fail:
9116+
kfree(filename);
91199117
free_filters_list(filters);
91209118
kfree(orig);
91219119

0 commit comments

Comments
 (0)