]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
4a59b8473280ecfc280c705be156048dbb4ea4c5
[thirdparty/kernel/stable-queue.git] /
1 From d5962fb7d69073bf68fb647531cfd4f0adf84be3 Mon Sep 17 00:00:00 2001
2 From: Dario Petrillo <dario.pk1@gmail.com>
3 Date: Mon, 10 Jan 2022 00:44:41 +0100
4 Subject: perf annotate: Avoid TUI crash when navigating in the annotation of recursive functions
5
6 From: Dario Petrillo <dario.pk1@gmail.com>
7
8 commit d5962fb7d69073bf68fb647531cfd4f0adf84be3 upstream.
9
10 In 'perf report', entering a recursive function from inside of itself
11 (either directly of indirectly through some other function) results in
12 calling symbol__annotate2 multiple() times, and freeing the whole
13 disassembly when exiting from the innermost instance.
14
15 The first issue causes the function's disassembly to be duplicated, and
16 the latter a heap use-after-free (and crash) when trying to access the
17 disassembly again.
18
19 I reproduced the bug on perf 5.11.22 (Ubuntu 20.04.3 LTS) and 5.16.rc8
20 with the following testcase (compile with gcc recursive.c -o recursive).
21 To reproduce:
22
23 - perf record ./recursive
24 - perf report
25 - enter fibonacci and annotate it
26 - move the cursor on one of the "callq fibonacci" instructions and press enter
27 - at this point there will be two copies of the function in the disassembly
28 - go back by pressing q, and perf will crash
29
30 #include <stdio.h>
31
32 int fibonacci(int n)
33 {
34 if(n <= 2) return 1;
35 return fibonacci(n-1) + fibonacci(n-2);
36 }
37
38 int main()
39 {
40 printf("%d\n", fibonacci(40));
41 }
42
43 This patch addresses the issue by annotating a function and freeing the
44 associated memory on exit only if no annotation is already present, so
45 that a recursive function is only annotated on entry.
46
47 Signed-off-by: Dario Petrillo <dario.pk1@gmail.com>
48 Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
49 Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
50 Cc: Jiri Olsa <jolsa@redhat.com>
51 Cc: Mark Rutland <mark.rutland@arm.com>
52 Cc: Namhyung Kim <namhyung@kernel.org>
53 Cc: Peter Zijlstra <peterz@infradead.org>
54 Cc: stable@kernel.org
55 Link: http://lore.kernel.org/lkml/20220109234441.325106-1-dario.pk1@gmail.com
56 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
57 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
58 ---
59 tools/perf/ui/browsers/annotate.c | 23 ++++++++++++++---------
60 1 file changed, 14 insertions(+), 9 deletions(-)
61
62 --- a/tools/perf/ui/browsers/annotate.c
63 +++ b/tools/perf/ui/browsers/annotate.c
64 @@ -966,6 +966,7 @@ int symbol__tui_annotate(struct map_symb
65 .opts = opts,
66 };
67 int ret = -1, err;
68 + int not_annotated = list_empty(&notes->src->source);
69
70 if (sym == NULL)
71 return -1;
72 @@ -973,13 +974,15 @@ int symbol__tui_annotate(struct map_symb
73 if (ms->map->dso->annotate_warned)
74 return -1;
75
76 - err = symbol__annotate2(ms, evsel, opts, &browser.arch);
77 - if (err) {
78 - char msg[BUFSIZ];
79 - ms->map->dso->annotate_warned = true;
80 - symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
81 - ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
82 - goto out_free_offsets;
83 + if (not_annotated) {
84 + err = symbol__annotate2(ms, evsel, opts, &browser.arch);
85 + if (err) {
86 + char msg[BUFSIZ];
87 + ms->map->dso->annotate_warned = true;
88 + symbol__strerror_disassemble(ms, err, msg, sizeof(msg));
89 + ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
90 + goto out_free_offsets;
91 + }
92 }
93
94 ui_helpline__push("Press ESC to exit");
95 @@ -994,9 +997,11 @@ int symbol__tui_annotate(struct map_symb
96
97 ret = annotate_browser__run(&browser, evsel, hbt);
98
99 - annotated_source__purge(notes->src);
100 + if(not_annotated)
101 + annotated_source__purge(notes->src);
102
103 out_free_offsets:
104 - zfree(&notes->offsets);
105 + if(not_annotated)
106 + zfree(&notes->offsets);
107 return ret;
108 }