Skip to contentSkip to conversation

perf parse-events: fix memory leaks found on parse_events

PATCH Applied Ian Rogers 4 participants 12 messages Mar 19, 2020 – May 8, 2020 perf events

lore
Share & tools
lore

Ian Rogers

author reviewer
#0 lore raw

PATCH v2 1/2 perf parse-events: fix memory leaks found on parse_events

Memory leaks found by applying LLVM's libfuzzer on the parse_events function.

---
 tools/perf/util/parse-events.c | 2 ++
 tools/perf/util/parse-events.y | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +2 -0
index 593b6b03785d..1e0bec5c0846 100644
@@ -1482,6 +1482,8 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
 
 		list_for_each_entry_safe(pos, tmp, &config_terms, list) {
 			list_del_init(&pos->list);
+			if (pos->free_str)
+				free(pos->val.str);
 			free(pos);
 		}
 		return -EINVAL;
tools/perf/util/parse-events.y +2 -1
index 94f8bcd83582..8212cc771667 100644
@@ -44,7 +44,7 @@ static void free_list_evsel(struct list_head* list_evsel)
 
 	list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
 		list_del_init(&evsel->core.node);
-		perf_evsel__delete(evsel);
+		evsel__delete(evsel);
 	}
 	free(list_evsel);
 }
@@ -326,6 +326,7 @@ PE_NAME opt_pmu_config
 	}
 	parse_events_terms__delete($2);
 	parse_events_terms__delete(orig_terms);
+	free(pattern);
 	free($1);
 	$$ = list;
 #undef CLEANUP_YYABORT
Signature · 1 line
2.25.1.696.g5e7596f4ac-goog
author reviewer
#1 lore raw

PATCH v2 2/2 libperf evlist: fix memory leaks

Memory leaks found by applying LLVM's libfuzzer on the tools/perf parse_events function.

---
 tools/lib/perf/evlist.c | 2 ++
 1 file changed, 2 insertions(+)
tools/lib/perf/evlist.c +2 -0
index 5b9f2ca50591..6485d1438f75 100644
@@ -125,8 +125,10 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
 void perf_evlist__exit(struct perf_evlist *evlist)
 {
 	perf_cpu_map__put(evlist->cpus);
+	perf_cpu_map__put(evlist->all_cpus);
 	perf_thread_map__put(evlist->threads);
 	evlist->cpus = NULL;
+	evlist->all_cpus = NULL;
 	evlist->threads = NULL;
 	fdarray__exit(&evlist->pollfd);
 }
Signature · 1 line
2.25.1.696.g5e7596f4ac-goog
Acked-by on v2 2/2
#2 lore raw

Re: [PATCH v2 2/2] libperf evlist: fix memory leaks

Quoted 4 lines · Ian Rogers

Memory leaks found by applying LLVM's libfuzzer on the tools/perf parse_events function.

Arnaldo,
could you plz pull first:
https://lore.kernel.org/lkml/[email protected]/

and then merge in this one?

thanks,
jirka

Quoted 22 lines
---
 tools/lib/perf/evlist.c | 2 ++
 1 file changed, 2 insertions(+)
tools/lib/perf/evlist.c +2 -0
index 5b9f2ca50591..6485d1438f75 100644
@@ -125,8 +125,10 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
 void perf_evlist__exit(struct perf_evlist *evlist)
 {
 	perf_cpu_map__put(evlist->cpus);
+	perf_cpu_map__put(evlist->all_cpus);
 	perf_thread_map__put(evlist->threads);
 	evlist->cpus = NULL;
+	evlist->all_cpus = NULL;
 	evlist->threads = NULL;
 	fdarray__exit(&evlist->pollfd);
 }
Signature · 1 line
2.25.1.696.g5e7596f4ac-goog
merge bot Applied
#3 lore raw

[tip: perf/core] libperf evlist: Fix a refcount leak

In reply to Ian Rogers
The following commit has been merged into the perf/core branch of tip:

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     4599d292128d89e4cf866a0ea9a9b047a2de8418
Gitweb:        https://git.kernel.org/tip/4599d292128d89e4cf866a0ea9a9b047a2de8418
Author:        Ian Rogers <[email protected]>
AuthorDate:    Wed, 18 Mar 2020 19:31:01 -07:00
Committer:     Arnaldo Carvalho de Melo <[email protected]>
CommitterDate: Tue, 05 May 2020 16:35:29 -03:00

libperf evlist: Fix a refcount leak

Memory leaks found by applying LLVM's libfuzzer on the tools/perf parse_events function.

Cc Adrian Hunter <[email protected]>
Cc Alexander Shishkin <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Leo Yan <[email protected]>
Cc Mark Rutland <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Stephane Eranian <[email protected]>
[ Did a minor adjustment due to some other previous patch having already set evlist->all_cpus to NULL at perf_evlist__exit() ]
---
 tools/lib/perf/evlist.c | 1 +
 1 file changed, 1 insertion(+)
tools/lib/perf/evlist.c +1 -0
index c481b62..6a875a0 100644
@@ -123,6 +123,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
 void perf_evlist__exit(struct perf_evlist *evlist)
 {
 	perf_cpu_map__put(evlist->cpus);
+	perf_cpu_map__put(evlist->all_cpus);
 	perf_thread_map__put(evlist->threads);
 	evlist->cpus = NULL;
 	evlist->all_cpus = NULL;
Acked-by on v2 1/2
#4 lore raw
In reply to Ian Rogers
Quoted 4 lines · Ian Rogers

Memory leaks found by applying LLVM's libfuzzer on the parse_events function.

thanks,
jirka

Quoted 42 lines
---
 tools/perf/util/parse-events.c | 2 ++
 tools/perf/util/parse-events.y | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +2 -0
index 593b6b03785d..1e0bec5c0846 100644
@@ -1482,6 +1482,8 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
 
 		list_for_each_entry_safe(pos, tmp, &config_terms, list) {
 			list_del_init(&pos->list);
+			if (pos->free_str)
+				free(pos->val.str);
 			free(pos);
 		}
 		return -EINVAL;
tools/perf/util/parse-events.y +2 -1
index 94f8bcd83582..8212cc771667 100644
@@ -44,7 +44,7 @@ static void free_list_evsel(struct list_head* list_evsel)
 
 	list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
 		list_del_init(&evsel->core.node);
-		perf_evsel__delete(evsel);
+		evsel__delete(evsel);
 	}
 	free(list_evsel);
 }
@@ -326,6 +326,7 @@ PE_NAME opt_pmu_config
 	}
 	parse_events_terms__delete($2);
 	parse_events_terms__delete(orig_terms);
+	free(pattern);
 	free($1);
 	$$ = list;
 #undef CLEANUP_YYABORT
Signature · 1 line
2.25.1.696.g5e7596f4ac-goog
author reviewer
#5 lore raw
Quoted 11 lines · Jiri Olsa
Quoted 4 lines · Ian Rogers

Memory leaks found by applying LLVM's libfuzzer on the parse_events function.

thanks,
jirka

Ping.

Quoted 43 lines
Quoted 42 lines
---
 tools/perf/util/parse-events.c | 2 ++
 tools/perf/util/parse-events.y | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +2 -0
index 593b6b03785d..1e0bec5c0846 100644
@@ -1482,6 +1482,8 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
 
              list_for_each_entry_safe(pos, tmp, &config_terms, list) {
                      list_del_init(&pos->list);
+                     if (pos->free_str)
+                             free(pos->val.str);
                      free(pos);
              }
              return -EINVAL;
tools/perf/util/parse-events.y +2 -2
index 94f8bcd83582..8212cc771667 100644
@@ -44,7 +44,7 @@ static void free_list_evsel(struct list_head* list_evsel)
 
      list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
              list_del_init(&evsel->core.node);
-             perf_evsel__delete(evsel);
+             evsel__delete(evsel);
      }
      free(list_evsel);
 }
@@ -326,6 +326,7 @@ PE_NAME opt_pmu_config
      }
      parse_events_terms__delete($2);
      parse_events_terms__delete(orig_terms);
+     free(pattern);
      free($1);
      $$ = list;
 #undef CLEANUP_YYABORT
--

2.25.1.696.g5e7596f4ac-goog

#6 lore raw
In reply to Ian Rogers

Em Wed, Mar 18, 2020 at 07:31:00PM -0700, Ian Rogers escreveu:

Quoted 14 lines

Memory leaks found by applying LLVM's libfuzzer on the parse_events function.

---
 tools/perf/util/parse-events.c | 2 ++
 tools/perf/util/parse-events.y | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +0 -0
index 593b6b03785d..1e0bec5c0846 100644

tools/perf/util/parse-events.c int parse_events_add_pmu(struct parse_events_state *parse_state, · line 1486

Quoted 5 lines
tools/perf/util/parse-events.c +2 -0
@@ -1482,6 +1482,8 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
 
 		list_for_each_entry_safe(pos, tmp, &config_terms, list) {
 			list_del_init(&pos->list);
+			if (pos->free_str)
+				free(pos->val.str);

I'm applying it but only after changing it to zfree(&pos->free_str), to make sure that any othe rcode that may still hold a pointer to pos will see a NULL in ->free_str and crash sooner rather than later.

tools/perf/util/parse-events.c int parse_events_add_pmu(struct parse_events_state *parse_state, · line 1489

Quoted 3 lines
tools/perf/util/parse-events.c +0 -0
 			free(pos);
 		}
 		return -EINVAL;

And the following should be in a different patch

tools/perf/util/parse-events.y static void free_list_evsel(struct list_head* list_evsel) · line 50

Quoted 13 lines
tools/perf/util/parse-events.y +1 -1
index 94f8bcd83582..8212cc771667 100644
@@ -44,7 +44,7 @@ static void free_list_evsel(struct list_head* list_evsel)
 
 	list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
 		list_del_init(&evsel->core.node);
-		perf_evsel__delete(evsel);
+		evsel__delete(evsel);
 	}
 	free(list_evsel);
 }

And this one in another, I'll fix this up, but please try in the future to provide different patches for different fixes, so that if we eventually find out that one of the unrelated fixes is wrong, then we can revert the patch more easily with 'git revert' instead of having to do a patch that reverts just part of the bigger hodge-podge patch.

If you go and have a track record of doing this as piecemeal as possible, I will in turn feel more confident of processing your patches in a faster fashion ;-) :-)

Thanks,

- Arnaldo

Quoted 11 lines
tools/perf/util/parse-events.y +1 -0
@@ -326,6 +326,7 @@ PE_NAME opt_pmu_config
 	}
 	parse_events_terms__delete($2);
 	parse_events_terms__delete(orig_terms);
+	free(pattern);
 	free($1);
 	$$ = list;
 #undef CLEANUP_YYABORT
Signature · 1 line
2.25.1.696.g5e7596f4ac-goog
Signature · 1 line
- Arnaldo
author reviewer
#7 lore raw
Quoted 52 lines · Arnaldo Carvalho de Melo

Em Wed, Mar 18, 2020 at 07:31:00PM -0700, Ian Rogers escreveu:

Quoted 14 lines

Memory leaks found by applying LLVM's libfuzzer on the parse_events function.

---
 tools/perf/util/parse-events.c | 2 ++
 tools/perf/util/parse-events.y | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +0 -0
index 593b6b03785d..1e0bec5c0846 100644

tools/perf/util/parse-events.c int parse_events_add_pmu(struct parse_events_state *parse_state, · line 1486

Quoted 5 lines
tools/perf/util/parse-events.c +2 -0
@@ -1482,6 +1482,8 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
 
              list_for_each_entry_safe(pos, tmp, &config_terms, list) {
                      list_del_init(&pos->list);
+                     if (pos->free_str)
+                             free(pos->val.str);

I'm applying it but only after changing it to zfree(&pos->free_str), to make sure that any othe rcode that may still hold a pointer to pos will see a NULL in ->free_str and crash sooner rather than later.

tools/perf/util/parse-events.c int parse_events_add_pmu(struct parse_events_state *parse_state, · line 1489

Quoted 3 lines
tools/perf/util/parse-events.c +0 -0
                      free(pos);
              }
              return -EINVAL;

And the following should be in a different patch

tools/perf/util/parse-events.y static void free_list_evsel(struct list_head* list_evsel) · line 50

Quoted 13 lines
tools/perf/util/parse-events.y +1 -1
index 94f8bcd83582..8212cc771667 100644
@@ -44,7 +44,7 @@ static void free_list_evsel(struct list_head* list_evsel)
 
      list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
              list_del_init(&evsel->core.node);
-             perf_evsel__delete(evsel);
+             evsel__delete(evsel);
      }
      free(list_evsel);
 }

And this one in another, I'll fix this up, but please try in the future to provide different patches for different fixes, so that if we eventually find out that one of the unrelated fixes is wrong, then we can revert the patch more easily with 'git revert' instead of having to do a patch that reverts just part of the bigger hodge-podge patch.

Quoted 3 lines

If you go and have a track record of doing this as piecemeal as possible, I will in turn feel more confident of processing your patches in a faster fashion ;-) :-)

Thanks, at some point I'd like to get libfuzzer with asan working for more than just me so that we don't backslide. It'd also make the reproductions easier to share.

Ian

Quoted 19 lines

Thanks,

- Arnaldo

Quoted 11 lines
tools/perf/util/parse-events.y +1 -1
@@ -326,6 +326,7 @@ PE_NAME opt_pmu_config
      }
      parse_events_terms__delete($2);
      parse_events_terms__delete(orig_terms);
+     free(pattern);
      free($1);
      $$ = list;
 #undef CLEANUP_YYABORT
--

2.25.1.696.g5e7596f4ac-goog

--

- Arnaldo

#8 lore raw

Em Thu, Apr 30, 2020 at 02:39:14PM -0700, Ian Rogers escreveu:

Quoted 54 lines
Quoted 52 lines · Arnaldo Carvalho de Melo

Em Wed, Mar 18, 2020 at 07:31:00PM -0700, Ian Rogers escreveu:

Quoted 14 lines

Memory leaks found by applying LLVM's libfuzzer on the parse_events function.

---
 tools/perf/util/parse-events.c | 2 ++
 tools/perf/util/parse-events.y | 3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)
tools/perf/util/parse-events.c +0 -0
index 593b6b03785d..1e0bec5c0846 100644

tools/perf/util/parse-events.c int parse_events_add_pmu(struct parse_events_state *parse_state, · line 1486

Quoted 5 lines
tools/perf/util/parse-events.c +2 -0
@@ -1482,6 +1482,8 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
 
              list_for_each_entry_safe(pos, tmp, &config_terms, list) {
                      list_del_init(&pos->list);
+                     if (pos->free_str)
+                             free(pos->val.str);

I'm applying it but only after changing it to zfree(&pos->free_str), to make sure that any othe rcode that may still hold a pointer to pos will see a NULL in ->free_str and crash sooner rather than later.

tools/perf/util/parse-events.c int parse_events_add_pmu(struct parse_events_state *parse_state, · line 1489

Quoted 3 lines
tools/perf/util/parse-events.c +0 -0
                      free(pos);
              }
              return -EINVAL;

And the following should be in a different patch

tools/perf/util/parse-events.y static void free_list_evsel(struct list_head* list_evsel) · line 50

Quoted 13 lines
tools/perf/util/parse-events.y +1 -1
index 94f8bcd83582..8212cc771667 100644
@@ -44,7 +44,7 @@ static void free_list_evsel(struct list_head* list_evsel)
 
      list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
              list_del_init(&evsel->core.node);
-             perf_evsel__delete(evsel);
+             evsel__delete(evsel);
      }
      free(list_evsel);
 }

And this one in another, I'll fix this up, but please try in the future to provide different patches for different fixes, so that if we eventually find out that one of the unrelated fixes is wrong, then we can revert the patch more easily with 'git revert' instead of having to do a patch that reverts just part of the bigger hodge-podge patch.

Quoted 7 lines
Quoted 3 lines

If you go and have a track record of doing this as piecemeal as possible, I will in turn feel more confident of processing your patches in a faster fashion ;-) :-)

Thanks, at some point I'd like to get libfuzzer with asan working for more than just me so that we don't backslide. It'd also make the reproductions easier to share.

If we can detect the presence of the needed components, libraries, compiler with the right feature set, yeah, a 'perf test' built under such environment surely would benefit from having further tests,

- Arnaldo

merge bot Applied
#9 lore raw

[tip: perf/core] perf parse-events: Fix another memory leaks found on parse_events()

In reply to Ian Rogers
The following commit has been merged into the perf/core branch of tip:

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     ba08829aace99b23da31b9b71d8ed5d40a44ed49
Gitweb:        https://git.kernel.org/tip/ba08829aace99b23da31b9b71d8ed5d40a44ed49
Author:        Ian Rogers <[email protected]>
AuthorDate:    Wed, 18 Mar 2020 19:31:00 -07:00
Committer:     Arnaldo Carvalho de Melo <[email protected]>
CommitterDate: Tue, 05 May 2020 16:35:29 -03:00

perf parse-events: Fix another memory leaks found on parse_events()

Fix another memory leak found by applying LLVM's libfuzzer on parse_events().

Cc Adrian Hunter <[email protected]>
Cc Alexander Shishkin <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Leo Yan <[email protected]>
Cc Mark Rutland <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Stephane Eranian <[email protected]>
[ split from a larger patch ]
---
 tools/perf/util/parse-events.y | 1 +
 1 file changed, 1 insertion(+)
tools/perf/util/parse-events.y +1 -0
index 6ece67e..c4ca932 100644
@@ -326,6 +326,7 @@ PE_NAME opt_pmu_config
 	}
 	parse_events_terms__delete($2);
 	parse_events_terms__delete(orig_terms);
+	free(pattern);
 	free($1);
 	$$ = list;
 #undef CLEANUP_YYABORT
merge bot Applied
#10 lore raw

[tip: perf/core] perf parse-events: Fix memory leaks found on parse_events

In reply to Ian Rogers
The following commit has been merged into the perf/core branch of tip:

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     672f707ef55f0a56b9bb67c3cfbdcab85c233796
Gitweb:        https://git.kernel.org/tip/672f707ef55f0a56b9bb67c3cfbdcab85c233796
Author:        Ian Rogers <[email protected]>
AuthorDate:    Wed, 18 Mar 2020 19:31:00 -07:00
Committer:     Arnaldo Carvalho de Melo <[email protected]>
CommitterDate: Tue, 05 May 2020 16:35:29 -03:00

perf parse-events: Fix memory leaks found on parse_events

free_list_evsel() deals with tools/perf/ evsels, not with libperf perf_evsels, use the right destructor and avoid a leak, as evsel__delete() will delete something perf_evsel__delete() doesn't.

Cc Adrian Hunter <[email protected]>
Cc Alexander Shishkin <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Leo Yan <[email protected]>
Cc Mark Rutland <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Stephane Eranian <[email protected]>
[ split from a larger patch ]
---
 tools/perf/util/parse-events.y | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/parse-events.y +1 -1
index e879eb2..6ece67e 100644
@@ -44,7 +44,7 @@ static void free_list_evsel(struct list_head* list_evsel)
 
 	list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
 		list_del_init(&evsel->core.node);
-		perf_evsel__delete(evsel);
+		evsel__delete(evsel);
 	}
 	free(list_evsel);
 }
merge bot Applied
#11 lore raw

[tip: perf/core] perf parse-events: Fix memory leaks found on parse_events

In reply to Ian Rogers
The following commit has been merged into the perf/core branch of tip:

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     e8dfb81838b14f82521968343884665b996646ef
Gitweb:        https://git.kernel.org/tip/e8dfb81838b14f82521968343884665b996646ef
Author:        Ian Rogers <[email protected]>
AuthorDate:    Wed, 18 Mar 2020 19:31:00 -07:00
Committer:     Arnaldo Carvalho de Melo <[email protected]>
CommitterDate: Tue, 05 May 2020 16:35:29 -03:00

perf parse-events: Fix memory leaks found on parse_events

Fix a memory leak found by applying LLVM's libfuzzer on parse_events().

Cc Adrian Hunter <[email protected]>
Cc Alexander Shishkin <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Leo Yan <[email protected]>
Cc Mark Rutland <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Stephane Eranian <[email protected]>
[ split from a larger patch, use zfree() ]
---
 tools/perf/util/parse-events.c | 1 +
 1 file changed, 1 insertion(+)
tools/perf/util/parse-events.c +1 -0
index 5795f3a..6dc9e57 100644
@@ -1482,6 +1482,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
 
 		list_for_each_entry_safe(pos, tmp, &config_terms, list) {
 			list_del_init(&pos->list);
+			zfree(&pos->val.str);
 			free(pos);
 		}
 		return -EINVAL;