In __cmd_top(), perf_set_multithreaded() is used to enable
pthread_rwlock, thus down_read() and down_write () are not nops,
handling concurrency problems
Then 'perf top' uses perf_set_singlethreaded(), switching to the single
threaded phase, assuming that no thread concurrency will happen later.
However, a use after free problem could occur in the single threaded
phase, the concurrent procedure is this:
display_thread process_thread
-------------- --------------
thread__comm_len
-> thread__comm_str
-> __thread__comm_str(thread)
thread__delete
-> comm__free
-> comm_str__put
-> zfree(&cs->str)
-> thread->comm_len = strlen(comm);
Since in single thread phase, perf_singlethreaded is true, down_read()
and down_write() do nothing to avoid concurrency problems.
This patch moves the perf_set_singlethreaded() call to the function tail
to expand the multithreaded phase range, making display_thread() and
process_thread() concurrency safe.
Reviewed-by: Yunfeng Ye <[email protected]>
Signed-off-by: Hangliang Lai <[email protected]>
Co-developed-by: Wenyu Liu <[email protected]>
Acked-by: Namhyung Kim <[email protected]>
Cc: Adrian Hunter <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Christian Brauner <[email protected]>
Cc: Feilong Lin <[email protected]>
Cc: Hewenliang <[email protected]>
Cc: Ian Rogers <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mark Rutland <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
top->evlist->core.threads, true, false,
top->nr_threads_synthesize);
- if (top->nr_threads_synthesize > 1)
- perf_set_singlethreaded();
+ perf_set_multithreaded();
if (perf_hpp_list.socket) {
ret = perf_env__read_cpu_topology_map(&perf_env);
out_join_thread:
cond_signal(&top->qe.cond);
pthread_join(thread_process, NULL);
+ perf_set_singlethreaded();
return ret;
}