From nobody Tue Jun 30 04:30:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 48A19C433F5 for ; Tue, 25 Jan 2022 20:46:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232495AbiAYUqS (ORCPT ); Tue, 25 Jan 2022 15:46:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40386 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232449AbiAYUqK (ORCPT ); Tue, 25 Jan 2022 15:46:10 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 79863C061744 for ; Tue, 25 Jan 2022 12:46:10 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id a4-20020a5b0ec4000000b00615dc8c1623so6258436ybs.17 for ; Tue, 25 Jan 2022 12:46:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=0TMY5o/dyQ5SuId4r0p3cjinmuagpPVpu9HxaMjlyFs=; b=Mo14bqF9hJDiq78yUjHWRuutj+izM6WTHiqrMaeQAC7nsDfVlyO6nwOLnKUL1kS9ga 2ktDHGGDolGzKWrCANph+FtkL4MCS2+h3jEy8mkxei3QOuENhJhxZ7Oh4XwoIC4uiyk+ WzY97kK1oi14s2y8W7RkLXgpVY5Je/PjafkxubjCEKm5pDMtFtrTds1HwKiJMMPgkpwb hs8rrOQE7FZBXdrm8Qx+MngjSps45P45HXbS0cU+Sc6VCMHGopOp7bUpX2Q5A2+hDWqv KVBn6omssXm6svz2an52H0izS4rxhe5IQieft7HWV0Bv56GtF5A58DmA/5bpI6RI4sBp gxtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=0TMY5o/dyQ5SuId4r0p3cjinmuagpPVpu9HxaMjlyFs=; b=2GDB+c9eFKWpV7KgaqX4FnW/0/zvJebYOXmYavsgq0+WVRrvQmY5TNevdPe3BceMh7 X0mGxPM73v1azk05BEsOuBmNfflzqisplNyzLyB62+N7Xa+rIFnT3qTktxgoRm9KR80K uiLvlMoqrDxVms73Mo0LWf+t0hFkBcplcQs4N0Ak3fbr/QHJqtP9G4AfydHnTApVOcL5 g0HCDJQSXPNBDxXbolkxhDcM+F6jRKJ/zGg2ZuRi1b/znYx9Z5bd8FpJYhL+VSrCRbfW WdddRsfB4j4UFcOZapQSYeXUSy1t6+KIWP3JuR7sZ+9pe+ttS9AgEE1S5Rn6+1TCDeOF HWEw== X-Gm-Message-State: AOAM530NMChBMakV/X/n0/UZnhH4/xzLZbmIlihec1HF562FUuL3/FXi 7DIMAWI1ip6HBwC3RGyYZ2Kj9ADlGAki X-Google-Smtp-Source: ABdhPJw59QY6jcdpKguI5Jw6FcaxKkT4Bl+bhYCmXnOqBuLXteeajaCZq6etrab+enN8qc3QTyuCh+0E57Qa X-Received: from irogers.svl.corp.google.com ([2620:15c:2cd:202:1a99:924a:8878:c44a]) (user=irogers job=sendgmr) by 2002:a25:244b:: with SMTP id k72mr33548861ybk.638.1643143569588; Tue, 25 Jan 2022 12:46:09 -0800 (PST) Date: Tue, 25 Jan 2022 12:45:59 -0800 In-Reply-To: <20220125204602.4137477-1-irogers@google.com> Message-Id: <20220125204602.4137477-2-irogers@google.com> Mime-Version: 1.0 References: <20220125204602.4137477-1-irogers@google.com> X-Mailer: git-send-email 2.35.0.rc0.227.g00780c9af4-goog Subject: [PATCH v2 1/4] perf cpumap: Add reference count checking From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Darren Hart , Davidlohr Bueso , "=?UTF-8?q?Andr=C3=A9=20Almeida?=" , James Clark , John Garry , Riccardo Mancini , Yury Norov , Andy Shevchenko , Andrew Morton , Jin Yao , Adrian Hunter , Leo Yan , Andi Kleen , Thomas Richter , Kan Liang , Madhavan Srinivasan , Shunsuke Nakamura , Song Liu , Masami Hiramatsu , Steven Rostedt , Miaoqian Lin , Stephen Brennan , Kajol Jain , Alexey Bayduraev , German Gomez , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Dumazet , Dmitry Vyukov Cc: eranian@google.com, Ian Rogers Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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, typically handled via an UNWRAP 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 --- tools/lib/perf/cpumap.c | 120 ++++++++++++++++------- tools/lib/perf/include/internal/cpumap.h | 14 ++- tools/perf/tests/cpumap.c | 20 ++-- tools/perf/util/cpumap.c | 42 ++++---- tools/perf/util/pmu.c | 24 +++-- 5 files changed, 146 insertions(+), 74 deletions(-) diff --git a/tools/lib/perf/cpumap.c b/tools/lib/perf/cpumap.c index ee66760f1e63..d401d133f84b 100644 --- a/tools/lib/perf/cpumap.c +++ b/tools/lib/perf/cpumap.c @@ -10,10 +10,16 @@ #include #include =20 -static struct perf_cpu_map *perf_cpu_map__alloc(int nr_cpus) +#ifndef REFCNT_CHECKING +#define UNWRAP_MAP(x) x +#else +#define UNWRAP_MAP(x) x->orig +#endif + +#ifndef REFCNT_CHECKING +struct perf_cpu_map *perf_cpu_map__alloc(int nr_cpus) { struct perf_cpu_map *cpus =3D malloc(sizeof(*cpus) + sizeof(struct perf_c= pu) * nr_cpus); - if (cpus !=3D NULL) { cpus->nr =3D nr_cpus; refcount_set(&cpus->refcnt, 1); @@ -21,13 +27,31 @@ static struct perf_cpu_map *perf_cpu_map__alloc(int nr_= cpus) } return cpus; } +#else +struct perf_cpu_map *perf_cpu_map__alloc(int nr_cpus) +{ + struct perf_cpu_map *wrapped_cpus =3D NULL; + struct original_perf_cpu_map *cpus =3D + malloc(sizeof(*cpus) + sizeof(struct perf_cpu) * nr_cpus); + if (cpus !=3D NULL) { + cpus->nr =3D nr_cpus; + refcount_set(&cpus->refcnt, 1); + wrapped_cpus =3D malloc(sizeof(*wrapped_cpus)); + if (wrapped_cpus !=3D NULL) + wrapped_cpus->orig =3D cpus; + else + free(cpus); + } + return wrapped_cpus; +} +#endif =20 struct perf_cpu_map *perf_cpu_map__dummy_new(void) { struct perf_cpu_map *cpus =3D perf_cpu_map__alloc(1); =20 if (cpus) - cpus->map[0].cpu =3D -1; + UNWRAP_MAP(cpus)->map[0].cpu =3D -1; =20 return cpus; } @@ -35,23 +59,45 @@ struct perf_cpu_map *perf_cpu_map__dummy_new(void) static void cpu_map__delete(struct perf_cpu_map *map) { if (map) { - WARN_ONCE(refcount_read(&map->refcnt) !=3D 0, + WARN_ONCE(refcount_read(&UNWRAP_MAP(map)->refcnt) !=3D 0, "cpu_map refcnt unbalanced\n"); +#ifdef REFCNT_CHECKING + free(map->orig); + map->orig =3D NULL; +#endif free(map); } } =20 struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map) { - if (map) - refcount_inc(&map->refcnt); + if (map) { +#ifdef REFCNT_CHECKING + struct perf_cpu_map *new_wrapper; +#endif + refcount_inc(&UNWRAP_MAP(map)->refcnt); +#ifdef REFCNT_CHECKING + new_wrapper =3D malloc(sizeof(*new_wrapper)); + new_wrapper->orig =3D map->orig; + map =3D new_wrapper; +#endif + } return map; } =20 void perf_cpu_map__put(struct perf_cpu_map *map) { - if (map && refcount_dec_and_test(&map->refcnt)) - cpu_map__delete(map); + if (map) { + if (refcount_dec_and_test(&UNWRAP_MAP(map)->refcnt)) + cpu_map__delete(map); + else { +#ifdef REFCNT_CHECKING + /* Free the wrapper object but the reference counted object remains. */ + map->orig =3D NULL; + free(map); +#endif + } + } } =20 static struct perf_cpu_map *cpu_map__default_new(void) @@ -68,7 +114,7 @@ static struct perf_cpu_map *cpu_map__default_new(void) int i; =20 for (i =3D 0; i < nr_cpus; ++i) - cpus->map[i].cpu =3D i; + UNWRAP_MAP(cpus)->map[i].cpu =3D i; } =20 return cpus; @@ -94,15 +140,16 @@ static struct perf_cpu_map *cpu_map__trim_new(int nr_c= pus, const struct perf_cpu int i, j; =20 if (cpus !=3D NULL) { - memcpy(cpus->map, tmp_cpus, payload_size); - qsort(cpus->map, nr_cpus, sizeof(struct perf_cpu), cmp_cpu); + memcpy(UNWRAP_MAP(cpus)->map, tmp_cpus, payload_size); + qsort(UNWRAP_MAP(cpus)->map, nr_cpus, sizeof(struct perf_cpu), cmp_cpu); /* Remove dups */ j =3D 0; for (i =3D 0; i < nr_cpus; i++) { - if (i =3D=3D 0 || cpus->map[i].cpu !=3D cpus->map[i - 1].cpu) - cpus->map[j++].cpu =3D cpus->map[i].cpu; + if (i =3D=3D 0 || + UNWRAP_MAP(cpus)->map[i].cpu !=3D UNWRAP_MAP(cpus)->map[i - 1].cpu) + UNWRAP_MAP(cpus)->map[j++].cpu =3D UNWRAP_MAP(cpus)->map[i].cpu; } - cpus->nr =3D j; + UNWRAP_MAP(cpus)->nr =3D j; assert(j <=3D nr_cpus); } return cpus; @@ -263,20 +310,20 @@ struct perf_cpu perf_cpu_map__cpu(const struct perf_c= pu_map *cpus, int idx) .cpu =3D -1 }; =20 - if (cpus && idx < cpus->nr) - return cpus->map[idx]; + if (cpus && idx < UNWRAP_MAP(cpus)->nr) + return UNWRAP_MAP(cpus)->map[idx]; =20 return result; } =20 int perf_cpu_map__nr(const struct perf_cpu_map *cpus) { - return cpus ? cpus->nr : 1; + return cpus ? UNWRAP_MAP(cpus)->nr : 1; } =20 bool perf_cpu_map__empty(const struct perf_cpu_map *map) { - return map ? map->map[0].cpu =3D=3D -1 : true; + return map ? UNWRAP_MAP(map)->map[0].cpu =3D=3D -1 : true; } =20 int perf_cpu_map__idx(const struct perf_cpu_map *cpus, struct perf_cpu cpu) @@ -287,10 +334,10 @@ int perf_cpu_map__idx(const struct perf_cpu_map *cpus= , struct perf_cpu cpu) return -1; =20 low =3D 0; - high =3D cpus->nr; + high =3D UNWRAP_MAP(cpus)->nr; while (low < high) { int idx =3D (low + high) / 2; - struct perf_cpu cpu_at_idx =3D cpus->map[idx]; + struct perf_cpu cpu_at_idx =3D UNWRAP_MAP(cpus)->map[idx]; =20 if (cpu_at_idx.cpu =3D=3D cpu.cpu) return idx; @@ -316,7 +363,7 @@ struct perf_cpu perf_cpu_map__max(struct perf_cpu_map *= map) }; =20 // cpu_map__trim_new() qsort()s it, cpu_map__default_new() sorts it as we= ll. - return map->nr > 0 ? map->map[map->nr - 1] : result; + return UNWRAP_MAP(map)->nr > 0 ? UNWRAP_MAP(map)->map[UNWRAP_MAP(map)->nr= - 1] : result; } =20 /* @@ -337,37 +384,36 @@ struct perf_cpu_map *perf_cpu_map__merge(struct perf_= cpu_map *orig, =20 if (!orig && !other) return NULL; - if (!orig) { - perf_cpu_map__get(other); - return other; - } + if (!orig) + return perf_cpu_map__get(other); if (!other) return orig; - if (orig->nr =3D=3D other->nr && - !memcmp(orig->map, other->map, orig->nr * sizeof(struct perf_cpu))) + if (UNWRAP_MAP(orig)->nr =3D=3D UNWRAP_MAP(other)->nr && + !memcmp(UNWRAP_MAP(orig)->map, UNWRAP_MAP(other)->map, + UNWRAP_MAP(orig)->nr * sizeof(struct perf_cpu))) return orig; =20 - tmp_len =3D orig->nr + other->nr; + tmp_len =3D UNWRAP_MAP(orig)->nr + UNWRAP_MAP(other)->nr; tmp_cpus =3D malloc(tmp_len * sizeof(struct perf_cpu)); if (!tmp_cpus) return NULL; =20 /* Standard merge algorithm from wikipedia */ i =3D j =3D k =3D 0; - while (i < orig->nr && j < other->nr) { - if (orig->map[i].cpu <=3D other->map[j].cpu) { - if (orig->map[i].cpu =3D=3D other->map[j].cpu) + while (i < UNWRAP_MAP(orig)->nr && j < UNWRAP_MAP(other)->nr) { + if (UNWRAP_MAP(orig)->map[i].cpu <=3D UNWRAP_MAP(other)->map[j].cpu) { + if (UNWRAP_MAP(orig)->map[i].cpu =3D=3D UNWRAP_MAP(other)->map[j].cpu) j++; - tmp_cpus[k++] =3D orig->map[i++]; + tmp_cpus[k++] =3D UNWRAP_MAP(orig)->map[i++]; } else - tmp_cpus[k++] =3D other->map[j++]; + tmp_cpus[k++] =3D UNWRAP_MAP(other)->map[j++]; } =20 - while (i < orig->nr) - tmp_cpus[k++] =3D orig->map[i++]; + while (i < UNWRAP_MAP(orig)->nr) + tmp_cpus[k++] =3D UNWRAP_MAP(orig)->map[i++]; =20 - while (j < other->nr) - tmp_cpus[k++] =3D other->map[j++]; + while (j < UNWRAP_MAP(other)->nr) + tmp_cpus[k++] =3D UNWRAP_MAP(other)->map[j++]; assert(k <=3D tmp_len); =20 merged =3D cpu_map__trim_new(k, tmp_cpus); diff --git a/tools/lib/perf/include/internal/cpumap.h b/tools/lib/perf/incl= ude/internal/cpumap.h index 581f9ffb4237..64ad56d167a0 100644 --- a/tools/lib/perf/include/internal/cpumap.h +++ b/tools/lib/perf/include/internal/cpumap.h @@ -16,7 +16,12 @@ struct perf_cpu { * gaps if CPU numbers were used. For events associated with a pid, rather= than * a CPU, a single dummy map with an entry of -1 is used. */ -struct perf_cpu_map { +#ifndef REFCNT_CHECKING +struct perf_cpu_map +#else +struct original_perf_cpu_map +#endif +{ refcount_t refcnt; /** Length of the map array. */ int nr; @@ -24,10 +29,17 @@ struct perf_cpu_map { struct perf_cpu map[]; }; =20 +#ifdef REFCNT_CHECKING +struct perf_cpu_map { + struct original_perf_cpu_map *orig; +}; +#endif + #ifndef MAX_NR_CPUS #define MAX_NR_CPUS 2048 #endif =20 +struct perf_cpu_map *perf_cpu_map__alloc(int nr_cpus); int perf_cpu_map__idx(const struct perf_cpu_map *cpus, struct perf_cpu cpu= ); =20 #endif /* __LIBPERF_INTERNAL_CPUMAP_H */ diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c index 84e87e31f119..65d9546aec6e 100644 --- a/tools/perf/tests/cpumap.c +++ b/tools/perf/tests/cpumap.c @@ -11,6 +11,12 @@ =20 struct machine; =20 +#ifndef REFCNT_CHECKING +#define UNWRAP_CPUMAP(x) x +#else +#define UNWRAP_CPUMAP(x) x->orig +#endif + static int process_event_mask(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample __maybe_unused, @@ -35,10 +41,10 @@ static int process_event_mask(struct perf_tool *tool __= maybe_unused, } =20 map =3D cpu_map__new_data(data); - TEST_ASSERT_VAL("wrong nr", map->nr =3D=3D 20); + TEST_ASSERT_VAL("wrong nr", perf_cpu_map__nr(map) =3D=3D 20); =20 for (i =3D 0; i < 20; i++) { - TEST_ASSERT_VAL("wrong cpu", map->map[i].cpu =3D=3D i); + TEST_ASSERT_VAL("wrong cpu", perf_cpu_map__cpu(map, i).cpu =3D=3D i); } =20 perf_cpu_map__put(map); @@ -66,10 +72,10 @@ static int process_event_cpus(struct perf_tool *tool __= maybe_unused, TEST_ASSERT_VAL("wrong cpu", cpus->cpu[1] =3D=3D 256); =20 map =3D cpu_map__new_data(data); - TEST_ASSERT_VAL("wrong nr", map->nr =3D=3D 2); - TEST_ASSERT_VAL("wrong cpu", map->map[0].cpu =3D=3D 1); - TEST_ASSERT_VAL("wrong cpu", map->map[1].cpu =3D=3D 256); - TEST_ASSERT_VAL("wrong refcnt", refcount_read(&map->refcnt) =3D=3D 1); + TEST_ASSERT_VAL("wrong nr", perf_cpu_map__nr(map) =3D=3D 2); + TEST_ASSERT_VAL("wrong cpu", perf_cpu_map__cpu(map, 0).cpu =3D=3D 1); + TEST_ASSERT_VAL("wrong cpu", perf_cpu_map__cpu(map, 1).cpu =3D=3D 256); + TEST_ASSERT_VAL("wrong refcnt", refcount_read(&UNWRAP_CPUMAP(map)->refcnt= ) =3D=3D 1); perf_cpu_map__put(map); return 0; } @@ -130,7 +136,7 @@ static int test__cpu_map_merge(struct test_suite *test = __maybe_unused, int subte struct perf_cpu_map *c =3D perf_cpu_map__merge(a, b); char buf[100]; =20 - TEST_ASSERT_VAL("failed to merge map: bad nr", c->nr =3D=3D 5); + TEST_ASSERT_VAL("failed to merge map: bad nr", perf_cpu_map__nr(c) =3D=3D= 5); cpu_map__snprint(c, buf, sizeof(buf)); TEST_ASSERT_VAL("failed to merge map: bad result", !strcmp(buf, "1-2,4-5,= 7")); perf_cpu_map__put(b); diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 12b2243222b0..e9976ca238fc 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -22,6 +22,12 @@ static int max_node_num; */ static int *cpunode_map; =20 +#ifndef REFCNT_CHECKING +#define UNWRAP_MAP(x) x +#else +#define UNWRAP_MAP(x) x->orig +#endif + static struct perf_cpu_map *cpu_map__from_entries(struct cpu_map_entries *= cpus) { struct perf_cpu_map *map; @@ -37,9 +43,9 @@ static struct perf_cpu_map *cpu_map__from_entries(struct = cpu_map_entries *cpus) * otherwise it would become 65535. */ if (cpus->cpu[i] =3D=3D (u16) -1) - map->map[i].cpu =3D -1; + UNWRAP_MAP(map)->map[i].cpu =3D -1; else - map->map[i].cpu =3D (int) cpus->cpu[i]; + UNWRAP_MAP(map)->map[i].cpu =3D (int) cpus->cpu[i]; } } =20 @@ -58,7 +64,7 @@ static struct perf_cpu_map *cpu_map__from_mask(struct per= f_record_record_cpu_map int cpu, i =3D 0; =20 for_each_set_bit(cpu, mask->mask, nbits) - map->map[i++].cpu =3D cpu; + UNWRAP_MAP(map)->map[i++].cpu =3D cpu; } return map; =20 @@ -84,16 +90,13 @@ size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE = *fp) =20 struct perf_cpu_map *perf_cpu_map__empty_new(int nr) { - struct perf_cpu_map *cpus =3D malloc(sizeof(*cpus) + sizeof(int) * nr); + struct perf_cpu_map *cpus =3D perf_cpu_map__alloc(nr); =20 if (cpus !=3D NULL) { int i; =20 - cpus->nr =3D nr; for (i =3D 0; i < nr; i++) - cpus->map[i].cpu =3D -1; - - refcount_set(&cpus->refcnt, 1); + UNWRAP_MAP(cpus)->map[i].cpu =3D -1; } =20 return cpus; @@ -163,7 +166,7 @@ struct cpu_aggr_map *cpu_aggr_map__new(const struct per= f_cpu_map *cpus, { int idx; struct perf_cpu cpu; - struct cpu_aggr_map *c =3D cpu_aggr_map__empty_new(cpus->nr); + struct cpu_aggr_map *c =3D cpu_aggr_map__empty_new(perf_cpu_map__nr(cpus)= ); =20 if (!c) return NULL; @@ -187,7 +190,7 @@ struct cpu_aggr_map *cpu_aggr_map__new(const struct per= f_cpu_map *cpus, } } /* Trim. */ - if (c->nr !=3D cpus->nr) { + if (c->nr !=3D perf_cpu_map__nr(cpus)) { struct cpu_aggr_map *trimmed_c =3D realloc(c, sizeof(struct cpu_aggr_map) + sizeof(struct aggr_cpu_id) * c->nr); @@ -494,31 +497,32 @@ size_t cpu_map__snprint(struct perf_cpu_map *map, cha= r *buf, size_t size) =20 #define COMMA first ? "" : "," =20 - for (i =3D 0; i < map->nr + 1; i++) { + for (i =3D 0; i < perf_cpu_map__nr(map) + 1; i++) { struct perf_cpu cpu =3D { .cpu =3D INT_MAX }; - bool last =3D i =3D=3D map->nr; + bool last =3D i =3D=3D perf_cpu_map__nr(map); =20 if (!last) - cpu =3D map->map[i]; + cpu =3D perf_cpu_map__cpu(map, i); =20 if (start =3D=3D -1) { start =3D i; if (last) { ret +=3D snprintf(buf + ret, size - ret, "%s%d", COMMA, - map->map[i].cpu); + perf_cpu_map__cpu(map, i).cpu); } - } else if (((i - start) !=3D (cpu.cpu - map->map[start].cpu)) || last) { + } else if (((i - start) !=3D (cpu.cpu - perf_cpu_map__cpu(map, start).cp= u)) || last) { int end =3D i - 1; =20 if (start =3D=3D end) { ret +=3D snprintf(buf + ret, size - ret, "%s%d", COMMA, - map->map[start].cpu); + perf_cpu_map__cpu(map, start).cpu); } else { ret +=3D snprintf(buf + ret, size - ret, "%s%d-%d", COMMA, - map->map[start].cpu, map->map[end].cpu); + perf_cpu_map__cpu(map, start).cpu, + perf_cpu_map__cpu(map, end).cpu); } first =3D false; start =3D i; @@ -545,7 +549,7 @@ size_t cpu_map__snprint_mask(struct perf_cpu_map *map, = char *buf, size_t size) int i, cpu; char *ptr =3D buf; unsigned char *bitmap; - struct perf_cpu last_cpu =3D perf_cpu_map__cpu(map, map->nr - 1); + struct perf_cpu last_cpu =3D perf_cpu_map__cpu(map, perf_cpu_map__nr(map)= - 1); =20 if (buf =3D=3D NULL) return 0; @@ -556,7 +560,7 @@ size_t cpu_map__snprint_mask(struct perf_cpu_map *map, = char *buf, size_t size) return 0; } =20 - for (i =3D 0; i < map->nr; i++) { + for (i =3D 0; i < perf_cpu_map__nr(map); i++) { cpu =3D perf_cpu_map__cpu(map, i).cpu; bitmap[cpu / 8] |=3D 1 << (cpu % 8); } diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 8dfbba15aeb8..1649321fe86f 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -1992,13 +1992,20 @@ int perf_pmu__match(char *pattern, char *name, char= *tok) return 0; } =20 +#ifndef REFCNT_CHECKING +#define UNWRAP_CPUMAP(x) x +#else +#define UNWRAP_CPUMAP(x) x->orig +#endif + int perf_pmu__cpus_match(struct perf_pmu *pmu, struct perf_cpu_map *cpus, struct perf_cpu_map **mcpus_ptr, struct perf_cpu_map **ucpus_ptr) { struct perf_cpu_map *pmu_cpus =3D pmu->cpus; struct perf_cpu_map *matched_cpus, *unmatched_cpus; - int matched_nr =3D 0, unmatched_nr =3D 0; + struct perf_cpu cpu; + int i, matched_nr =3D 0, unmatched_nr =3D 0; =20 matched_cpus =3D perf_cpu_map__default_new(); if (!matched_cpus) @@ -2010,18 +2017,15 @@ int perf_pmu__cpus_match(struct perf_pmu *pmu, stru= ct perf_cpu_map *cpus, return -1; } =20 - for (int i =3D 0; i < cpus->nr; i++) { - int cpu; - - cpu =3D perf_cpu_map__idx(pmu_cpus, cpus->map[i]); - if (cpu =3D=3D -1) - unmatched_cpus->map[unmatched_nr++] =3D cpus->map[i]; + perf_cpu_map__for_each_cpu(cpu, i, cpus) { + if (!perf_cpu_map__has(pmu_cpus, cpu)) + UNWRAP_CPUMAP(unmatched_cpus)->map[unmatched_nr++] =3D cpu; else - matched_cpus->map[matched_nr++] =3D cpus->map[i]; + UNWRAP_CPUMAP(matched_cpus)->map[matched_nr++] =3D cpu; } =20 - unmatched_cpus->nr =3D unmatched_nr; - matched_cpus->nr =3D matched_nr; + UNWRAP_CPUMAP(unmatched_cpus)->nr =3D unmatched_nr; + UNWRAP_CPUMAP(matched_cpus)->nr =3D matched_nr; *mcpus_ptr =3D matched_cpus; *ucpus_ptr =3D unmatched_cpus; return 0; --=20 2.35.0.rc0.227.g00780c9af4-goog From nobody Tue Jun 30 04:30:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8A523C433FE for ; Tue, 25 Jan 2022 20:46:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232511AbiAYUqT (ORCPT ); Tue, 25 Jan 2022 15:46:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40398 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232463AbiAYUqN (ORCPT ); Tue, 25 Jan 2022 15:46:13 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EDFA8C061749 for ; Tue, 25 Jan 2022 12:46:12 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id g7-20020a25bdc7000000b00611c616bc76so43746626ybk.5 for ; Tue, 25 Jan 2022 12:46:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=100W4F2SZe3IWptV5RcjIMfgKhxT7aMM0DwnzM2uSwI=; b=AtZRyMJoLmRfImn6GijY+LOfXNuW5R979dWq2WEKkjVF5oC8JztYwcYuD2rH/cYe0p xiYe8ye9PRjpjWl5ItXl+LHdIwsUlUI5120zvJJsZuykYVj1PrfN1GGKtBQ8RcRSfMZq +SOGEc2PV7Wz4dtW5kXTrLPa68rmovr5r4PPcZAHxAYJ0Nd3OcCdvmcFQka3qp3oJBAO RVrxhaRUw4oDWPeJJbj3xxN/7NmqykbwzQwqsaKz79O5kFiAcLAEcHBHnb8cWj1MZVFW FHYtiMjMxghS6EkcvScsLJrBfT5C2ub634yFZs7q7Aq5RV4ZAZpWYfwq1gqr+ZjVinaA l4mA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=100W4F2SZe3IWptV5RcjIMfgKhxT7aMM0DwnzM2uSwI=; b=NILn+/lGCOEG8xZF4u8Ls5YSmVG1EgyjB2XbXm1/jVnCatLELcObZUguZo5YiRxsWj JgPJK5VoQtPr91fsroLfsTDj3P90YGT44/S80uygXvd5oEluzgI5w1EBWbGA3IJih2kv N1Cr8/XC99IPlQjvw51K0OFeGM1Bzeff/8JuDyBZT9PIiUYv3XYHhrPz40uJkb94MSzj kgQO88g5Q5MD5GM9UGXPHmXZkC16E6hlk6/jibz5N8i5c9xsmCjqvveZUyuwg11hTTFm NwWqi1pX1OoJPGjB2wqeuJV2+R3PgiXEZ4VeNql8HhcDUgt7cQXT5yjj/XWCpIrl/BUV 8Nlw== X-Gm-Message-State: AOAM531Fu6fjL97se8Z/pcDxVdBQr48P8w4w+MrYG8ipRhqNGDaZjgbJ DaB6ku/txVyDVKBKpbf2sAtfIxMtXmNe X-Google-Smtp-Source: ABdhPJz2AIIoZgVx9s5C8xIPQXRhGrzFQOIyFCz9l/0X/Qe4+Z88KgE1Z4u1cAGgzmMAEZwt+iZ+joHSwBBP X-Received: from irogers.svl.corp.google.com ([2620:15c:2cd:202:1a99:924a:8878:c44a]) (user=irogers job=sendgmr) by 2002:a25:a102:: with SMTP id z2mr32541998ybh.100.1643143572035; Tue, 25 Jan 2022 12:46:12 -0800 (PST) Date: Tue, 25 Jan 2022 12:46:00 -0800 In-Reply-To: <20220125204602.4137477-1-irogers@google.com> Message-Id: <20220125204602.4137477-3-irogers@google.com> Mime-Version: 1.0 References: <20220125204602.4137477-1-irogers@google.com> X-Mailer: git-send-email 2.35.0.rc0.227.g00780c9af4-goog Subject: [PATCH v2 2/4] perf dso: Make lock error check and add BUG_ONs From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Darren Hart , Davidlohr Bueso , "=?UTF-8?q?Andr=C3=A9=20Almeida?=" , James Clark , John Garry , Riccardo Mancini , Yury Norov , Andy Shevchenko , Andrew Morton , Jin Yao , Adrian Hunter , Leo Yan , Andi Kleen , Thomas Richter , Kan Liang , Madhavan Srinivasan , Shunsuke Nakamura , Song Liu , Masami Hiramatsu , Steven Rostedt , Miaoqian Lin , Stephen Brennan , Kajol Jain , Alexey Bayduraev , German Gomez , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Dumazet , Dmitry Vyukov Cc: eranian@google.com, Ian Rogers Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Make the pthread mutex on dso use the error check type. This allows deadlock checking via the return type. Assert the returned value from mutex lock is always 0. Signed-off-by: Ian Rogers --- tools/perf/util/dso.c | 12 +++++++++--- tools/perf/util/symbol.c | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 9cc8a1772b4b..6beccffeef7b 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -784,7 +784,7 @@ dso_cache__free(struct dso *dso) struct rb_root *root =3D &dso->data.cache; struct rb_node *next =3D rb_first(root); =20 - pthread_mutex_lock(&dso->lock); + BUG_ON(pthread_mutex_lock(&dso->lock) !=3D 0); while (next) { struct dso_cache *cache; =20 @@ -830,7 +830,7 @@ dso_cache__insert(struct dso *dso, struct dso_cache *ne= w) struct dso_cache *cache; u64 offset =3D new->offset; =20 - pthread_mutex_lock(&dso->lock); + BUG_ON(pthread_mutex_lock(&dso->lock) !=3D 0); while (*p !=3D NULL) { u64 end; =20 @@ -1259,6 +1259,8 @@ struct dso *dso__new_id(const char *name, struct dso_= id *id) struct dso *dso =3D calloc(1, sizeof(*dso) + strlen(name) + 1); =20 if (dso !=3D NULL) { + pthread_mutexattr_t lock_attr; + strcpy(dso->name, name); if (id) dso->id =3D *id; @@ -1286,8 +1288,12 @@ struct dso *dso__new_id(const char *name, struct dso= _id *id) dso->root =3D NULL; INIT_LIST_HEAD(&dso->node); INIT_LIST_HEAD(&dso->data.open_entry); - pthread_mutex_init(&dso->lock, NULL); + pthread_mutexattr_init(&lock_attr); + pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_ERRORCHECK); + pthread_mutex_init(&dso->lock, &lock_attr); + pthread_mutexattr_destroy(&lock_attr); refcount_set(&dso->refcnt, 1); + } =20 return dso; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index b2ed3140a1fa..43f47532696f 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1783,7 +1783,7 @@ int dso__load(struct dso *dso, struct map *map) } =20 nsinfo__mountns_enter(dso->nsinfo, &nsc); - pthread_mutex_lock(&dso->lock); + BUG_ON(pthread_mutex_lock(&dso->lock) !=3D 0); =20 /* check again under the dso->lock */ if (dso__loaded(dso)) { --=20 2.35.0.rc0.227.g00780c9af4-goog From nobody Tue Jun 30 04:30:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 987CFC43219 for ; Tue, 25 Jan 2022 20:47:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232552AbiAYUq4 (ORCPT ); Tue, 25 Jan 2022 15:46:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40416 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232481AbiAYUqQ (ORCPT ); Tue, 25 Jan 2022 15:46:16 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E4729C061748 for ; Tue, 25 Jan 2022 12:46:15 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id 2-20020a251302000000b006118f867dadso43799976ybt.12 for ; Tue, 25 Jan 2022 12:46:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Ttw3ezZDXz3Bj8XRopBgxWgM5+jUj8lF7+ns5vhVDzI=; b=q9vPMTSBJEIPFSMydYOZD0ou+ODqQP2XwKBHHFSrtjlSHcmC9J/wEx8GIPkmUXLq8r xAFbn9jg6LgL03xx8Wbw0xKUyr7Zvfd8u2YK+ajPGIFuhzqRH6Kgc+ubkfclW+aD1ho0 7374Wh71EihFa3vJriEMdBO6t/9mgjV8lPZ1DsnM8ha7bI8MrkBhLmXfLaquGoeHAHFw ZXn/7x3WsVCfpgq+/Eundzc1eHkxRUk9ETDNR6XX93J9FTBIQNpPKaOsFrJEKcX8VypX Wipfk+09v3YiGaF0eaDjwWMv/JFt3EP+SfLA2CtIDCruo9X3IDLxTi0EmyqMqc6wpogr ubyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Ttw3ezZDXz3Bj8XRopBgxWgM5+jUj8lF7+ns5vhVDzI=; b=Z3wzLH8gWpY1kC+iSpGHIqZxnRQ8SzlyaClV8V4oJx2pdpcK0R0sDUKYbRj2yRxb+D Crss69OFThR9I2LntD60dt46VfmR6+5bXfCxMn5iSQTQoXRNLTeahwEQmm42vjddf2NA +YPdO2keLtnPSMzNUiKbTIE+EWLLk5T84O5VVS9CnRvrxn6gnE4ZO15zwoY8g/bU3qQu EqEKZcvii57U8KBn0M+7wY/mIFPezN6i//T+wRGctck0zzS4WT9Qagn3ke3JmGHCd64p un3s9A/kwdyoKjvY0zzxiYOfpouQphpFsqVuM7Vm729aiVMhKDOBTTS3++NLf0zcKAu3 oxDA== X-Gm-Message-State: AOAM532kdPlydSotTqM9klY1xrKpVNQLaRPXlYDudukt6AJSZWftGHcC Sy0LWm2Cmgqq2LhgCyA981IR5kHIv08l X-Google-Smtp-Source: ABdhPJxz475DQvm3Ccjx6M6G/w3kNupgMy08j/dfoAoF5agDnv2WwaHQH+svvED7I/79eEm2U9W7U4khslx1 X-Received: from irogers.svl.corp.google.com ([2620:15c:2cd:202:1a99:924a:8878:c44a]) (user=irogers job=sendgmr) by 2002:a81:1906:0:b0:2ca:287c:6c58 with SMTP id 00721157ae682-2ca287c6ea4mr6642117b3.253.1643143574688; Tue, 25 Jan 2022 12:46:14 -0800 (PST) Date: Tue, 25 Jan 2022 12:46:01 -0800 In-Reply-To: <20220125204602.4137477-1-irogers@google.com> Message-Id: <20220125204602.4137477-4-irogers@google.com> Mime-Version: 1.0 References: <20220125204602.4137477-1-irogers@google.com> X-Mailer: git-send-email 2.35.0.rc0.227.g00780c9af4-goog Subject: [PATCH v2 3/4] perf dso: Hold lock when accessing nsinfo From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Darren Hart , Davidlohr Bueso , "=?UTF-8?q?Andr=C3=A9=20Almeida?=" , James Clark , John Garry , Riccardo Mancini , Yury Norov , Andy Shevchenko , Andrew Morton , Jin Yao , Adrian Hunter , Leo Yan , Andi Kleen , Thomas Richter , Kan Liang , Madhavan Srinivasan , Shunsuke Nakamura , Song Liu , Masami Hiramatsu , Steven Rostedt , Miaoqian Lin , Stephen Brennan , Kajol Jain , Alexey Bayduraev , German Gomez , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Dumazet , Dmitry Vyukov Cc: eranian@google.com, Ian Rogers Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" There may be threads racing to update dso->nsinfo: https://lore.kernel.org/linux-perf-users/CAP-5=3DfWZH20L4kv-BwVtGLwR=3DEm3A= OOT+Q4QGivvQuYn5AsPRg@mail.gmail.com/ Holding the dso->lock avoids use-after-free, memory leaks and other such bugs. Apply the fix in: https://lore.kernel.org/linux-perf-users/20211118193714.2293728-1-irogers@g= oogle.com/ of there being a missing nsinfo__put now that the accesses are data race free. Signed-off-by: Ian Rogers --- tools/perf/builtin-inject.c | 4 ++++ tools/perf/util/dso.c | 5 ++++- tools/perf/util/map.c | 3 +++ tools/perf/util/probe-event.c | 2 ++ tools/perf/util/symbol.c | 2 +- 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index fbf43a454cba..bede332bf0e2 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -363,8 +363,10 @@ static struct dso *findnew_dso(int pid, int tid, const= char *filename, } =20 if (dso) { + BUG_ON(pthread_mutex_lock(&dso->lock) !=3D 0); nsinfo__put(dso->nsinfo); dso->nsinfo =3D nsi; + pthread_mutex_unlock(&dso->lock); } else nsinfo__put(nsi); =20 @@ -547,7 +549,9 @@ static int dso__read_build_id(struct dso *dso) if (dso->has_build_id) return 0; =20 + BUG_ON(pthread_mutex_lock(&dso->lock) !=3D 0); nsinfo__mountns_enter(dso->nsinfo, &nsc); + pthread_mutex_unlock(&dso->lock); if (filename__read_build_id(dso->long_name, &dso->bid) > 0) dso->has_build_id =3D true; nsinfo__mountns_exit(&nsc); diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 6beccffeef7b..b2f570adba35 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -548,8 +548,11 @@ static int open_dso(struct dso *dso, struct machine *m= achine) int fd; struct nscookie nsc; =20 - if (dso->binary_type !=3D DSO_BINARY_TYPE__BUILD_ID_CACHE) + if (dso->binary_type !=3D DSO_BINARY_TYPE__BUILD_ID_CACHE) { + BUG_ON(pthread_mutex_lock(&dso->lock) !=3D 0); nsinfo__mountns_enter(dso->nsinfo, &nsc); + pthread_mutex_unlock(&dso->lock); + } fd =3D __open_dso(dso, machine); if (dso->binary_type !=3D DSO_BINARY_TYPE__BUILD_ID_CACHE) nsinfo__mountns_exit(&nsc); diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 8af693d9678c..ae99b52502d5 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -192,7 +192,10 @@ struct map *map__new(struct machine *machine, u64 star= t, u64 len, if (!(prot & PROT_EXEC)) dso__set_loaded(dso); } + BUG_ON(pthread_mutex_lock(&dso->lock) !=3D 0); + nsinfo__put(dso->nsinfo); dso->nsinfo =3D nsi; + pthread_mutex_unlock(&dso->lock); =20 if (build_id__is_defined(bid)) dso__set_build_id(dso, bid); diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index a834918a0a0d..7444e689ece7 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -180,8 +180,10 @@ struct map *get_target_map(const char *target, struct = nsinfo *nsi, bool user) =20 map =3D dso__new_map(target); if (map && map->dso) { + BUG_ON(pthread_mutex_lock(&map->dso->lock) !=3D 0); nsinfo__put(map->dso->nsinfo); map->dso->nsinfo =3D nsinfo__get(nsi); + pthread_mutex_unlock(&map->dso->lock); } return map; } else { diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 43f47532696f..a504346feb05 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1774,6 +1774,7 @@ int dso__load(struct dso *dso, struct map *map) char newmapname[PATH_MAX]; const char *map_path =3D dso->long_name; =20 + BUG_ON(pthread_mutex_lock(&dso->lock) !=3D 0); perfmap =3D strncmp(dso->name, "/tmp/perf-", 10) =3D=3D 0; if (perfmap) { if (dso->nsinfo && (dso__find_perf_map(newmapname, @@ -1783,7 +1784,6 @@ int dso__load(struct dso *dso, struct map *map) } =20 nsinfo__mountns_enter(dso->nsinfo, &nsc); - BUG_ON(pthread_mutex_lock(&dso->lock) !=3D 0); =20 /* check again under the dso->lock */ if (dso__loaded(dso)) { --=20 2.35.0.rc0.227.g00780c9af4-goog From nobody Tue Jun 30 04:30:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 885DFC433FE for ; Tue, 25 Jan 2022 20:47:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232512AbiAYUqx (ORCPT ); Tue, 25 Jan 2022 15:46:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40398 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232499AbiAYUqS (ORCPT ); Tue, 25 Jan 2022 15:46:18 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6B0B2C061748 for ; Tue, 25 Jan 2022 12:46:18 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id a4-20020a5b0ec4000000b00615dc8c1623so6259022ybs.17 for ; Tue, 25 Jan 2022 12:46:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Krzq0l2cuCvov6m4mTyGKggqBY2ioOeKFOBwv0ymBmQ=; b=tM+76O8WxuPtMZ+BsXvTTLDSQUzg3CE0Zl5nKI/b3BitnA8Lv9Jz62IIh4xsUgIad1 +ba7WV47ICrcGzuV/05z8ez6depcz9wHYLcp/3ixYB+ta0crHl9olLTwBKkVNaQXGkR4 stXMbLE7CbU12NDMiV4N2+4LAWDZL2fEsyYrdQVm/T7vggileAojt3V9jpj32qamj9TB PuYp2506wTTcF8fe996h5kz3hkY1H/qJdlwC0NXsrUk8vazI6zYllG5vrdedREydznBM VvTsk60d8yDStDwOWnMD7AHArxXh1IdcsnB1S6rAJkZ6V7Jv/WkM42kjdWnnQCfiD0vl 8sHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Krzq0l2cuCvov6m4mTyGKggqBY2ioOeKFOBwv0ymBmQ=; b=dVNgUL6i2i1WUFbGxdTokRZa1Aak5UdGJm2U8ZhFjbsiCmVkjUM2S/oketJbpUU6RE QKUw/vT8EZ4IaOmNmBCWxC8f4xFDVpgKrp90548TTEcbpeOhhM4c/7S3Tel6C8ivaetI lRapAw36+LSAO1tmKb99cXuu4vqAVcvcY+dXqKxD9PoL8IMQ4EyTBcgw5XX4iNJl+yZ0 3kD2Sdx5kuAe3jALG7nQJ9HbaTQ686n+XRm4pz2ztfRPr+124arfMZq4HyNL93f+1AyO 4W+s8YwhOHkWqooZOciCi1+74DFQ7CK92r84aCOUkNGwV3+WKMEDl7z6I8V147sInKKw +wqw== X-Gm-Message-State: AOAM531E6TTQcE32VKbR0txXezOJGLrp0AY5EkHJIwtfWWb+yHVyNTqa IqOqqKk91q9FgOleiA3QO9Etx1VSSgBM X-Google-Smtp-Source: ABdhPJzOYkUsznrcF1fdWmKRRvWJ0yFtI9yedtEBzGE2Dt/5pAMC8O5oR+Fhy/mso+2l2DB68WeMa5ZFO9Mo X-Received: from irogers.svl.corp.google.com ([2620:15c:2cd:202:1a99:924a:8878:c44a]) (user=irogers job=sendgmr) by 2002:a05:6902:1243:: with SMTP id t3mr20862509ybu.304.1643143577536; Tue, 25 Jan 2022 12:46:17 -0800 (PST) Date: Tue, 25 Jan 2022 12:46:02 -0800 In-Reply-To: <20220125204602.4137477-1-irogers@google.com> Message-Id: <20220125204602.4137477-5-irogers@google.com> Mime-Version: 1.0 References: <20220125204602.4137477-1-irogers@google.com> X-Mailer: git-send-email 2.35.0.rc0.227.g00780c9af4-goog Subject: [PATCH v2 4/4] perf namespaces: Add reference count checking From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Thomas Gleixner , Darren Hart , Davidlohr Bueso , "=?UTF-8?q?Andr=C3=A9=20Almeida?=" , James Clark , John Garry , Riccardo Mancini , Yury Norov , Andy Shevchenko , Andrew Morton , Jin Yao , Adrian Hunter , Leo Yan , Andi Kleen , Thomas Richter , Kan Liang , Madhavan Srinivasan , Shunsuke Nakamura , Song Liu , Masami Hiramatsu , Steven Rostedt , Miaoqian Lin , Stephen Brennan , Kajol Jain , Alexey Bayduraev , German Gomez , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Dumazet , Dmitry Vyukov Cc: eranian@google.com, Ian Rogers Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add reference count checking controlled by REFCNT_CHECKING ifdef. The reference count checking interposes an allocated pointer between the reference counted struct on a get and frees the pointer on a put. Accesses after a put cause faults and use after free, missed puts are caughts as leaks and double puts are double frees. This checking helped resolve a memory leak and use after free: https://lore.kernel.org/linux-perf-users/CAP-5=3DfWZH20L4kv-BwVtGLwR=3DEm3A= OOT+Q4QGivvQuYn5AsPRg@mail.gmail.com/ Signed-off-by: Ian Rogers --- tools/perf/builtin-inject.c | 2 +- tools/perf/builtin-probe.c | 2 +- tools/perf/util/build-id.c | 4 +- tools/perf/util/jitdump.c | 10 +- tools/perf/util/map.c | 4 +- tools/perf/util/namespaces.c | 187 +++++++++++++++++++++++++---------- tools/perf/util/namespaces.h | 23 ++++- tools/perf/util/symbol.c | 8 +- 8 files changed, 168 insertions(+), 72 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index bede332bf0e2..f7917c390e96 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -354,7 +354,7 @@ static struct dso *findnew_dso(int pid, int tid, const = char *filename, nnsi =3D nsinfo__copy(nsi); if (nnsi) { nsinfo__put(nsi); - nnsi->need_setns =3D false; + nsinfo__clear_need_setns(nnsi); nsi =3D nnsi; } dso =3D machine__findnew_vdso(machine, thread); diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index c31627af75d4..f62298f5db3b 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -217,7 +217,7 @@ static int opt_set_target_ns(const struct option *opt _= _maybe_unused, return ret; } nsip =3D nsinfo__new(ns_pid); - if (nsip && nsip->need_setns) + if (nsip && nsinfo__need_setns(nsip)) params.nsi =3D nsinfo__get(nsip); nsinfo__put(nsip); =20 diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index e32e8f2ff3bd..7a5821c87f94 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -706,7 +706,7 @@ build_id_cache__add(const char *sbuild_id, const char *= name, const char *realnam if (is_kallsyms) { if (copyfile("/proc/kallsyms", filename)) goto out_free; - } else if (nsi && nsi->need_setns) { + } else if (nsi && nsinfo__need_setns(nsi)) { if (copyfile_ns(name, filename, nsi)) goto out_free; } else if (link(realname, filename) && errno !=3D EEXIST && @@ -730,7 +730,7 @@ build_id_cache__add(const char *sbuild_id, const char *= name, const char *realnam goto out_free; } if (access(filename, F_OK)) { - if (nsi && nsi->need_setns) { + if (nsi && nsinfo__need_setns(nsi)) { if (copyfile_ns(debugfile, filename, nsi)) goto out_free; diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 917a9c707371..a23255773c60 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -382,15 +382,15 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_= event *event) =20 static pid_t jr_entry_pid(struct jit_buf_desc *jd, union jr_entry *jr) { - if (jd->nsi && jd->nsi->in_pidns) - return jd->nsi->tgid; + if (jd->nsi && nsinfo__in_pidns(jd->nsi)) + return nsinfo__tgid(jd->nsi); return jr->load.pid; } =20 static pid_t jr_entry_tid(struct jit_buf_desc *jd, union jr_entry *jr) { - if (jd->nsi && jd->nsi->in_pidns) - return jd->nsi->pid; + if (jd->nsi && nsinfo__in_pidns(jd->nsi)) + return nsinfo__pid(jd->nsi); return jr->load.tid; } =20 @@ -779,7 +779,7 @@ jit_detect(char *mmap_name, pid_t pid, struct nsinfo *n= si) * pid does not match mmap pid * pid=3D=3D0 in system-wide mode (synthesized) */ - if (pid && pid2 !=3D nsi->nstgid) + if (pid && pid2 !=3D nsinfo__nstgid(nsi)) return -1; /* * validate suffix diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index ae99b52502d5..5b93a91bb0f9 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -151,7 +151,7 @@ struct map *map__new(struct machine *machine, u64 start= , u64 len, =20 if ((anon || no_dso) && nsi && (prot & PROT_EXEC)) { snprintf(newfilename, sizeof(newfilename), - "/tmp/perf-%d.map", nsi->pid); + "/tmp/perf-%d.map", nsinfo__pid(nsi)); filename =3D newfilename; } =20 @@ -168,7 +168,7 @@ struct map *map__new(struct machine *machine, u64 start= , u64 len, nnsi =3D nsinfo__copy(nsi); if (nnsi) { nsinfo__put(nsi); - nnsi->need_setns =3D false; + nsinfo__clear_need_setns(nnsi); nsi =3D nnsi; } pgoff =3D 0; diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c index 48aa3217300b..4187179107ec 100644 --- a/tools/perf/util/namespaces.c +++ b/tools/perf/util/namespaces.c @@ -30,6 +30,12 @@ static const char *perf_ns__names[] =3D { [CGROUP_NS_INDEX] =3D "cgroup", }; =20 +#ifndef REFCNT_CHECKING +#define UNWRAP_NSI(x) x +#else +#define UNWRAP_NSI(x) x->orig +#endif + const char *perf_ns__name(unsigned int id) { if (id >=3D ARRAY_SIZE(perf_ns__names)) @@ -60,7 +66,7 @@ void namespaces__free(struct namespaces *namespaces) free(namespaces); } =20 -static int nsinfo__get_nspid(struct nsinfo *nsi, const char *path) +static int nsinfo__get_nspid(pid_t *tgid, pid_t *nstgid, bool *in_pidns, c= onst char *path) { FILE *f =3D NULL; char *statln =3D NULL; @@ -74,19 +80,18 @@ static int nsinfo__get_nspid(struct nsinfo *nsi, const = char *path) while (getline(&statln, &linesz, f) !=3D -1) { /* Use tgid if CONFIG_PID_NS is not defined. */ if (strstr(statln, "Tgid:") !=3D NULL) { - nsi->tgid =3D (pid_t)strtol(strrchr(statln, '\t'), - NULL, 10); - nsi->nstgid =3D nsi->tgid; + *tgid =3D (pid_t)strtol(strrchr(statln, '\t'), NULL, 10); + *nstgid =3D *tgid; } =20 if (strstr(statln, "NStgid:") !=3D NULL) { nspid =3D strrchr(statln, '\t'); - nsi->nstgid =3D (pid_t)strtol(nspid, NULL, 10); + *nstgid =3D (pid_t)strtol(nspid, NULL, 10); /* * If innermost tgid is not the first, process is in a different * PID namespace. */ - nsi->in_pidns =3D (statln + sizeof("NStgid:") - 1) !=3D nspid; + *in_pidns =3D (statln + sizeof("NStgid:") - 1) !=3D nspid; break; } } @@ -108,7 +113,7 @@ int nsinfo__init(struct nsinfo *nsi) if (snprintf(oldns, PATH_MAX, "/proc/self/ns/mnt") >=3D PATH_MAX) return rv; =20 - if (asprintf(&newns, "/proc/%d/ns/mnt", nsi->pid) =3D=3D -1) + if (asprintf(&newns, "/proc/%d/ns/mnt", UNWRAP_NSI(nsi)->pid) =3D=3D -1) return rv; =20 if (stat(oldns, &old_stat) < 0) @@ -121,24 +126,47 @@ int nsinfo__init(struct nsinfo *nsi) * want to switch as part of looking up dso/map data. */ if (old_stat.st_ino !=3D new_stat.st_ino) { - nsi->need_setns =3D true; - nsi->mntns_path =3D newns; + UNWRAP_NSI(nsi)->need_setns =3D true; + UNWRAP_NSI(nsi)->mntns_path =3D newns; newns =3D NULL; } =20 /* If we're dealing with a process that is in a different PID namespace, * attempt to work out the innermost tgid for the process. */ - if (snprintf(spath, PATH_MAX, "/proc/%d/status", nsi->pid) >=3D PATH_MAX) + if (snprintf(spath, PATH_MAX, "/proc/%d/status", UNWRAP_NSI(nsi)->pid) >= =3D PATH_MAX) goto out; =20 - rv =3D nsinfo__get_nspid(nsi, spath); + rv =3D nsinfo__get_nspid(&UNWRAP_NSI(nsi)->tgid, &UNWRAP_NSI(nsi)->nstgid, + &UNWRAP_NSI(nsi)->in_pidns, spath); =20 out: free(newns); return rv; } =20 +static struct nsinfo *nsinfo__alloc(void) +{ + struct nsinfo *res; +#ifdef REFCNT_CHECKING + res =3D malloc(sizeof(*res)); + if (!res) + return NULL; + + res->orig =3D calloc(1, sizeof(struct original_nsinfo)); + if (!res->orig) { + free(res); + res =3D NULL; + } else + refcount_set(&res->orig->refcnt, 1); +#else + res =3D calloc(1, sizeof(*res)); + if (res) + refcount_set(&res->refcnt, 1); +#endif + return res; +} + struct nsinfo *nsinfo__new(pid_t pid) { struct nsinfo *nsi; @@ -146,70 +174,121 @@ struct nsinfo *nsinfo__new(pid_t pid) if (pid =3D=3D 0) return NULL; =20 - nsi =3D calloc(1, sizeof(*nsi)); - if (nsi !=3D NULL) { - nsi->pid =3D pid; - nsi->tgid =3D pid; - nsi->nstgid =3D pid; - nsi->need_setns =3D false; - nsi->in_pidns =3D false; - /* Init may fail if the process exits while we're trying to look - * at its proc information. In that case, save the pid but - * don't try to enter the namespace. - */ - if (nsinfo__init(nsi) =3D=3D -1) - nsi->need_setns =3D false; - - refcount_set(&nsi->refcnt, 1); - } + nsi =3D nsinfo__alloc(); + if (!nsi) + return NULL; + + UNWRAP_NSI(nsi)->pid =3D pid; + UNWRAP_NSI(nsi)->tgid =3D pid; + UNWRAP_NSI(nsi)->nstgid =3D pid; + UNWRAP_NSI(nsi)->need_setns =3D false; + UNWRAP_NSI(nsi)->in_pidns =3D false; + /* Init may fail if the process exits while we're trying to look at its + * proc information. In that case, save the pid but don't try to enter + * the namespace. + */ + if (nsinfo__init(nsi) =3D=3D -1) + UNWRAP_NSI(nsi)->need_setns =3D false; =20 return nsi; } =20 -struct nsinfo *nsinfo__copy(struct nsinfo *nsi) +struct nsinfo *nsinfo__copy(const struct nsinfo *nsi) { struct nsinfo *nnsi; =20 if (nsi =3D=3D NULL) return NULL; =20 - nnsi =3D calloc(1, sizeof(*nnsi)); - if (nnsi !=3D NULL) { - nnsi->pid =3D nsi->pid; - nnsi->tgid =3D nsi->tgid; - nnsi->nstgid =3D nsi->nstgid; - nnsi->need_setns =3D nsi->need_setns; - nnsi->in_pidns =3D nsi->in_pidns; - if (nsi->mntns_path) { - nnsi->mntns_path =3D strdup(nsi->mntns_path); - if (!nnsi->mntns_path) { - free(nnsi); - return NULL; - } + nnsi =3D nsinfo__alloc(); + if (!nnsi) + return NULL; + + UNWRAP_NSI(nnsi)->pid =3D UNWRAP_NSI(nsi)->pid; + UNWRAP_NSI(nnsi)->tgid =3D UNWRAP_NSI(nsi)->tgid; + UNWRAP_NSI(nnsi)->nstgid =3D UNWRAP_NSI(nsi)->nstgid; + UNWRAP_NSI(nnsi)->need_setns =3D UNWRAP_NSI(nsi)->need_setns; + UNWRAP_NSI(nnsi)->in_pidns =3D UNWRAP_NSI(nsi)->in_pidns; + if (UNWRAP_NSI(nsi)->mntns_path) { + UNWRAP_NSI(nnsi)->mntns_path =3D strdup(UNWRAP_NSI(nsi)->mntns_path); + if (!UNWRAP_NSI(nnsi)->mntns_path) { + nsinfo__put(nnsi); + return NULL; } - refcount_set(&nnsi->refcnt, 1); } =20 return nnsi; } =20 -void nsinfo__delete(struct nsinfo *nsi) +static void nsinfo__delete(struct nsinfo *nsi) { - zfree(&nsi->mntns_path); - free(nsi); + if (nsi) { + WARN_ONCE(refcount_read(&UNWRAP_NSI(nsi)->refcnt) !=3D 0, + "nsinfo refcnt unbalanced\n"); + zfree(&UNWRAP_NSI(nsi)->mntns_path); +#ifdef REFCNT_CHECKING + zfree(&nsi->orig); +#endif + free(nsi); + } } =20 struct nsinfo *nsinfo__get(struct nsinfo *nsi) { - if (nsi) - refcount_inc(&nsi->refcnt); + if (nsi) { +#ifdef REFCNT_CHECKING + struct nsinfo *new_wrapper; +#endif + refcount_inc(&UNWRAP_NSI(nsi)->refcnt); +#ifdef REFCNT_CHECKING + new_wrapper =3D malloc(sizeof(*new_wrapper)); + new_wrapper->orig =3D nsi->orig; + nsi =3D new_wrapper; +#endif + } return nsi; } =20 void nsinfo__put(struct nsinfo *nsi) { - if (nsi && refcount_dec_and_test(&nsi->refcnt)) + if (nsi && refcount_dec_and_test(&UNWRAP_NSI(nsi)->refcnt)) nsinfo__delete(nsi); +#ifdef REFCNT_CHECKING + else if (nsi) { + nsi->orig =3D NULL; + free(nsi); + } +#endif +} + +bool nsinfo__need_setns(const struct nsinfo *nsi) +{ + return UNWRAP_NSI(nsi)->need_setns; +} + +void nsinfo__clear_need_setns(struct nsinfo *nsi) +{ + UNWRAP_NSI(nsi)->need_setns =3D false; +} + +pid_t nsinfo__tgid(const struct nsinfo *nsi) +{ + return UNWRAP_NSI(nsi)->tgid; +} + +pid_t nsinfo__nstgid(const struct nsinfo *nsi) +{ + return UNWRAP_NSI(nsi)->nstgid; +} + +pid_t nsinfo__pid(const struct nsinfo *nsi) +{ + return UNWRAP_NSI(nsi)->pid; +} + +pid_t nsinfo__in_pidns(const struct nsinfo *nsi) +{ + return UNWRAP_NSI(nsi)->in_pidns; } =20 void nsinfo__mountns_enter(struct nsinfo *nsi, @@ -226,7 +305,7 @@ void nsinfo__mountns_enter(struct nsinfo *nsi, nc->oldns =3D -1; nc->newns =3D -1; =20 - if (!nsi || !nsi->need_setns) + if (!nsi || !UNWRAP_NSI(nsi)->need_setns) return; =20 if (snprintf(curpath, PATH_MAX, "/proc/self/ns/mnt") >=3D PATH_MAX) @@ -240,7 +319,7 @@ void nsinfo__mountns_enter(struct nsinfo *nsi, if (oldns < 0) goto errout; =20 - newns =3D open(nsi->mntns_path, O_RDONLY); + newns =3D open(UNWRAP_NSI(nsi)->mntns_path, O_RDONLY); if (newns < 0) goto errout; =20 @@ -309,9 +388,9 @@ int nsinfo__stat(const char *filename, struct stat *st,= struct nsinfo *nsi) =20 bool nsinfo__is_in_root_namespace(void) { - struct nsinfo nsi; + pid_t tgid =3D 0, nstgid =3D 0; + bool in_pidns =3D false; =20 - memset(&nsi, 0x0, sizeof(nsi)); - nsinfo__get_nspid(&nsi, "/proc/self/status"); - return !nsi.in_pidns; + nsinfo__get_nspid(&tgid, &nstgid, &in_pidns, "/proc/self/status"); + return !in_pidns; } diff --git a/tools/perf/util/namespaces.h b/tools/perf/util/namespaces.h index 9ceea9643507..673c7bcdb9b0 100644 --- a/tools/perf/util/namespaces.h +++ b/tools/perf/util/namespaces.h @@ -29,7 +29,12 @@ struct namespaces { struct namespaces *namespaces__new(struct perf_record_namespaces *event); void namespaces__free(struct namespaces *namespaces); =20 -struct nsinfo { +#ifndef REFCNT_CHECKING +struct nsinfo +#else +struct original_nsinfo +#endif +{ pid_t pid; pid_t tgid; pid_t nstgid; @@ -39,6 +44,12 @@ struct nsinfo { refcount_t refcnt; }; =20 +#ifdef REFCNT_CHECKING +struct nsinfo { + struct original_nsinfo *orig; +}; +#endif + struct nscookie { int oldns; int newns; @@ -47,12 +58,18 @@ struct nscookie { =20 int nsinfo__init(struct nsinfo *nsi); struct nsinfo *nsinfo__new(pid_t pid); -struct nsinfo *nsinfo__copy(struct nsinfo *nsi); -void nsinfo__delete(struct nsinfo *nsi); +struct nsinfo *nsinfo__copy(const struct nsinfo *nsi); =20 struct nsinfo *nsinfo__get(struct nsinfo *nsi); void nsinfo__put(struct nsinfo *nsi); =20 +bool nsinfo__need_setns(const struct nsinfo *nsi); +void nsinfo__clear_need_setns(struct nsinfo *nsi); +pid_t nsinfo__tgid(const struct nsinfo *nsi); +pid_t nsinfo__nstgid(const struct nsinfo *nsi); +pid_t nsinfo__pid(const struct nsinfo *nsi); +pid_t nsinfo__in_pidns(const struct nsinfo *nsi); + void nsinfo__mountns_enter(struct nsinfo *nsi, struct nscookie *nc); void nsinfo__mountns_exit(struct nscookie *nc); =20 diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index a504346feb05..40477f4d16fa 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1735,8 +1735,8 @@ static int dso__find_perf_map(char *filebuf, size_t b= ufsz, =20 nsi =3D *nsip; =20 - if (nsi->need_setns) { - snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nsi->nstgid); + if (nsinfo__need_setns(nsi)) { + snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nsinfo__nstgid(nsi)); nsinfo__mountns_enter(nsi, &nsc); rc =3D access(filebuf, R_OK); nsinfo__mountns_exit(&nsc); @@ -1748,8 +1748,8 @@ static int dso__find_perf_map(char *filebuf, size_t b= ufsz, if (nnsi) { nsinfo__put(nsi); =20 - nnsi->need_setns =3D false; - snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nnsi->tgid); + nsinfo__clear_need_setns(nnsi); + snprintf(filebuf, bufsz, "/tmp/perf-%d.map", nsinfo__tgid(nnsi)); *nsip =3D nnsi; rc =3D 0; } --=20 2.35.0.rc0.227.g00780c9af4-goog