summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorkiyin(尹亮) <kiyin@tencent.com>2020-11-04 08:23:22 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-11-10 12:36:02 +0100
commit29a975bcc107d68e379a55048813ddf3e7b120b8 (patch)
tree14b82973e794fbeaa8a5a959b37485a195462c10 /kernel
parent292e5700f4db841593141e9a3b1210e94bc8f74f (diff)
downloadlinux-stable-29a975bcc107d68e379a55048813ddf3e7b120b8.tar.gz
linux-stable-29a975bcc107d68e379a55048813ddf3e7b120b8.tar.bz2
linux-stable-29a975bcc107d68e379a55048813ddf3e7b120b8.zip
perf/core: Fix a memory leak in perf_event_parse_addr_filter()
commit 7bdb157cdebbf95a1cd94ed2e01b338714075d00 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: 375637bc5249 ("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>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/events/core.c12
1 files changed, 5 insertions, 7 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index a35d742b0ba8..8b94eb6437c1 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -9047,6 +9047,7 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
if (token == IF_SRC_FILE || token == IF_SRC_FILEADDR) {
int fpos = token == IF_SRC_FILE ? 2 : 1;
+ kfree(filename);
filename = match_strdup(&args[fpos]);
if (!filename) {
ret = -ENOMEM;
@@ -9093,16 +9094,13 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
*/
ret = -EOPNOTSUPP;
if (!event->ctx->task)
- goto fail_free_name;
+ goto fail;
/* look up the path and grab its inode */
ret = kern_path(filename, LOOKUP_FOLLOW,
&filter->path);
if (ret)
- goto fail_free_name;
-
- kfree(filename);
- filename = NULL;
+ goto fail;
ret = -EINVAL;
if (!filter->path.dentry ||
@@ -9122,13 +9120,13 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
if (state != IF_STATE_ACTION)
goto fail;
+ kfree(filename);
kfree(orig);
return 0;
-fail_free_name:
- kfree(filename);
fail:
+ kfree(filename);
free_filters_list(filters);
kfree(orig);