Re: [PATCH v7 2/5] perf cpumap: Add reference count checking

From: Arnaldo Carvalho de Melo
Date: Mon Apr 17 2023 - 11:50:03 EST


Em Fri, Apr 07, 2023 at 04:04:02PM -0700, Ian Rogers escreveu:
> Enabled when REFCNT_CHECKING is defined. The change adds a memory
> allocated pointer that is interposed between the reference counted
> cpu map at a get and freed by a put. The pointer replaces the original
> perf_cpu_map struct, so use of the perf_cpu_map via APIs remains
> unchanged. Any use of the cpu map without the API requires two versions,
> handled via the RC_CHK_ACCESS macro.
>
> This change is intended to catch:
> - use after put: using a cpumap after you have put it will cause a
> segv.
> - unbalanced puts: two puts for a get will result in a double free
> that can be captured and reported by tools like address sanitizer,
> including with the associated stack traces of allocation and frees.
> - missing puts: if a put is missing then the get turns into a memory
> leak that can be reported by leak sanitizer, including the stack
> trace at the point the get occurs.
>
> Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
> ---
> tools/lib/perf/Makefile | 2 +-
> tools/lib/perf/cpumap.c | 94 +++++++++++++-----------
> tools/lib/perf/include/internal/cpumap.h | 4 +-
> tools/perf/tests/cpumap.c | 4 +-
> tools/perf/util/cpumap.c | 40 +++++-----
> tools/perf/util/pmu.c | 8 +-
> 6 files changed, 81 insertions(+), 71 deletions(-)
>
> diff --git a/tools/lib/perf/Makefile b/tools/lib/perf/Makefile
> index d8cad124e4c5..3a9b2140aa04 100644
> --- a/tools/lib/perf/Makefile
> +++ b/tools/lib/perf/Makefile
> @@ -188,7 +188,7 @@ install_lib: libs
> cp -fpR $(LIBPERF_ALL) $(DESTDIR)$(libdir_SQ)
>
> HDRS := bpf_perf.h core.h cpumap.h threadmap.h evlist.h evsel.h event.h mmap.h
> -INTERNAL_HDRS := cpumap.h evlist.h evsel.h lib.h mmap.h threadmap.h xyarray.h
> +INTERNAL_HDRS := cpumap.h evlist.h evsel.h lib.h mmap.h rc_check.h threadmap.h xyarray.h
>
> INSTALL_HDRS_PFX := $(DESTDIR)$(prefix)/include/perf
> INSTALL_HDRS := $(addprefix $(INSTALL_HDRS_PFX)/, $(HDRS))
> diff --git a/tools/lib/perf/cpumap.c b/tools/lib/perf/cpumap.c
> index 6cd0be7c1bb4..56eed1ac80d9 100644
> --- a/tools/lib/perf/cpumap.c
> +++ b/tools/lib/perf/cpumap.c
> @@ -10,16 +10,16 @@
> #include <ctype.h>
> #include <limits.h>
>
> -static struct perf_cpu_map *perf_cpu_map__alloc(int nr_cpus)
> +struct perf_cpu_map *perf_cpu_map__alloc(int nr_cpus)
> {
> - struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(struct perf_cpu) * nr_cpus);
> -
> - if (cpus != NULL) {
> + struct perf_cpu_map *result;
> + RC_STRUCT(perf_cpu_map) *cpus =
> + malloc(sizeof(*cpus) + sizeof(struct perf_cpu) * nr_cpus);
> + if (ADD_RC_CHK(result, cpus)) {
> cpus->nr = nr_cpus;
> refcount_set(&cpus->refcnt, 1);
> -
> }
> - return cpus;
> + return result;
> }
>
> struct perf_cpu_map *perf_cpu_map__dummy_new(void)
> @@ -27,7 +27,7 @@ struct perf_cpu_map *perf_cpu_map__dummy_new(void)
> struct perf_cpu_map *cpus = perf_cpu_map__alloc(1);
>
> if (cpus)
> - cpus->map[0].cpu = -1;
> + RC_CHK_ACCESS(cpus)->map[0].cpu = -1;

One more: