[PATCH v3 04/22] perf dso: Hold lock when accessing nsinfo

Ian Rogers
2022-02-11T10:34:47Z

There may be threads racing to update dso->nsinfo:
https://lore.kernel.org/linux-perf-users/CAP-5=fWZH20L4kv-BwVtGLwR=Em3AOOT+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@google.com/
of there being a missing nsinfo__put now that the accesses are data race
free.

Signed-off-by: Ian Rogers <irogers@google.com>
---
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,
}

if (dso) {
+ BUG_ON(pthread_mutex_lock(&dso->lock) != 0);
nsinfo__put(dso->nsinfo);
dso->nsinfo = nsi;
+ pthread_mutex_unlock(&dso->lock);
} else
nsinfo__put(nsi);

@@ -547,7 +549,9 @@ static int dso__read_build_id(struct dso *dso)
if (dso->has_build_id)
return 0;

+ BUG_ON(pthread_mutex_lock(&dso->lock) != 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 = 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 *machine)
int fd;
struct nscookie nsc;

- if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
+ if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE) {
+ BUG_ON(pthread_mutex_lock(&dso->lock) != 0);
nsinfo__mountns_enter(dso->nsinfo, &nsc);
+ pthread_mutex_unlock(&dso->lock);
+ }
fd = __open_dso(dso, machine);
if (dso->binary_type != 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 start, u64 len,
if (!(prot & PROT_EXEC))
dso__set_loaded(dso);
}
+ BUG_ON(pthread_mutex_lock(&dso->lock) != 0);
+ nsinfo__put(dso->nsinfo);
dso->nsinfo = nsi;
+ pthread_mutex_unlock(&dso->lock);

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)

map = dso__new_map(target);
if (map && map->dso) {
+ BUG_ON(pthread_mutex_lock(&map->dso->lock) != 0);
nsinfo__put(map->dso->nsinfo);
map->dso->nsinfo = 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 = dso->long_name;

+ BUG_ON(pthread_mutex_lock(&dso->lock) != 0);
perfmap = strncmp(dso->name, "/tmp/perf-", 10) == 0;
if (perfmap) {
if (dso->nsinfo && (dso__find_perf_map(newmapname,
@@ -1783,7 +1784,6 @@ int dso__load(struct dso *dso, struct map *map)
}

nsinfo__mountns_enter(dso->nsinfo, &nsc);
- BUG_ON(pthread_mutex_lock(&dso->lock) != 0);

/* check again under the dso->lock */
if (dso__loaded(dso)) {
--
2.35.1.265.g69c8d7142f-goog