Skip to content

Commit b7f7474

Browse files
kiyin(尹亮)gregkh
authored andcommitted
perf/core: Fix a memory leak in perf_event_parse_addr_filter()
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> -- kernel/events/core.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 21ab13a commit b7f7474

1 file changed

Lines changed: 5 additions & 7 deletions

File tree

kernel/events/core.c

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

9418+
kfree(filename);
94189419
filename = match_strdup(&args[fpos]);
94199420
if (!filename) {
94209421
ret = -ENOMEM;
@@ -9461,16 +9462,13 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
94619462
*/
94629463
ret = -EOPNOTSUPP;
94639464
if (!event->ctx->task)
9464-
goto fail_free_name;
9465+
goto fail;
94659466

94669467
/* look up the path and grab its inode */
94679468
ret = kern_path(filename, LOOKUP_FOLLOW,
94689469
&filter->path);
94699470
if (ret)
9470-
goto fail_free_name;
9471-
9472-
kfree(filename);
9473-
filename = NULL;
9471+
goto fail;
94749472

94759473
ret = -EINVAL;
94769474
if (!filter->path.dentry ||
@@ -9490,13 +9488,13 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
94909488
if (state != IF_STATE_ACTION)
94919489
goto fail;
94929490

9491+
kfree(filename);
94939492
kfree(orig);
94949493

94959494
return 0;
94969495

9497-
fail_free_name:
9498-
kfree(filename);
94999496
fail:
9497+
kfree(filename);
95009498
free_filters_list(filters);
95019499
kfree(orig);
95029500

0 commit comments

Comments
 (0)