summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2026-07-22 21:59:44 -0700
committerNamhyung Kim <namhyung@kernel.org>2026-07-27 17:13:08 -0700
commitad7620a2b9455874884234b0cdae62e1be0ea1f3 (patch)
tree0d911b82ba471663566af29018e76d23abb3d972
parentb2d4225695e6977cd7802fe425d8caa5822a5e7d (diff)
downloadlinux-next-ad7620a2b9455874884234b0cdae62e1be0ea1f3.tar.gz
linux-next-ad7620a2b9455874884234b0cdae62e1be0ea1f3.zip
perf ui hists: Fix stack use-after-return in symbol_filter_str
In evsel__hists_browse(), the local stack array 'buf' is assigned directly to the persistent 'hists->symbol_filter_str' pointer. When the browser returns or is exited, this dangling pointer remains active in the 'hists' struct and is read asynchronously by the perf top background timer, triggering a stack use-after-return. Fix it by properly duplicating the input string using strdup(), safely invoking zfree() to prevent memory leaks when overwriting, and cleanly resetting and freeing the symbol filter string upon exiting the browser. Assisted-by: Antigravity:gemini-3.5-flash Signed-off-by: Ian Rogers <irogers@google.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-rw-r--r--tools/perf/builtin-report.c7
-rw-r--r--tools/perf/ui/browsers/hists.c5
-rw-r--r--tools/perf/util/hist.c1
3 files changed, 10 insertions, 3 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 10db1e5f1e6c..60d1f166629e 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -726,8 +726,11 @@ static int report__collapse_hists(struct report *rep)
evlist__for_each_entry(rep->session->evlist, pos) {
struct hists *hists = evsel__hists(pos);
- if (pos->core.idx == 0)
- hists->symbol_filter_str = rep->symbol_filter_str;
+ if (pos->core.idx == 0) {
+ hists->symbol_filter_str =
+ rep->symbol_filter_str ?
+ strdup(rep->symbol_filter_str) : NULL;
+ }
hists->socket_filter = rep->socket_filter;
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index b6002724bc3a..be8a6b169722 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -3220,7 +3220,10 @@ do_hotkey: // key came straight from options ui__popup_menu()
"To remove the filter later, press / + ENTER.",
buf, "ENTER: OK, ESC: Cancel",
delay_secs * 2) == K_ENTER) {
- hists->symbol_filter_str = *buf ? buf : NULL;
+ char *new_filter = *buf ? strdup(buf) : NULL;
+
+ zfree(&hists->symbol_filter_str);
+ hists->symbol_filter_str = new_filter;
hists__filter_by_symbol(hists);
hist_browser__reset(browser);
}
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index c93915625ee7..443694926f1a 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -3056,6 +3056,7 @@ static void hists_evsel__exit(struct evsel *evsel)
struct perf_hpp_list_node *node, *tmp;
hists__delete_all_entries(hists);
+ zfree(&hists->symbol_filter_str);
zfree(&hists->mem_stat_types);
zfree(&hists->mem_stat_total);