Commit e54dea69 authored by Ian Rogers's avatar Ian Rogers Committed by Arnaldo Carvalho de Melo

perf dso: Hold lock when accessing nsinfo

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. Fixes test "Lookup mmap thread" when compiled with address
sanitizer.
Signed-off-by: default avatarIan Rogers <irogers@google.com>
Reviewed-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexandre Truong <alexandre.truong@arm.com>
Cc: Alexey Bayduraev <alexey.v.bayduraev@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Andres Freund <andres@anarazel.de>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: André Almeida <andrealmeid@igalia.com>
Cc: Athira Jajeev <atrajeev@linux.vnet.ibm.com>
Cc: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Cc: Colin Ian King <colin.king@intel.com>
Cc: Dario Petrillo <dario.pk1@gmail.com>
Cc: Darren Hart <dvhart@infradead.org>
Cc: Dave Marchevsky <davemarchevsky@fb.com>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Fangrui Song <maskray@google.com>
Cc: Hewenliang <hewenliang4@huawei.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jason Wang <wangborong@cdjrlc.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Kim Phillips <kim.phillips@amd.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Martin Liška <mliska@suse.cz>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Pavithra Gurushankar <gpavithrasha@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Quentin Monnet <quentin@isovalent.com>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Remi Bernon <rbernon@codeweavers.com>
Cc: Riccardo Mancini <rickyman7@gmail.com>
Cc: Song Liu <songliubraving@fb.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Tom Rix <trix@redhat.com>
Cc: Weiguo Li <liwg06@foxmail.com>
Cc: Wenyu Liu <liuwenyu7@huawei.com>
Cc: William Cohen <wcohen@redhat.com>
Cc: Zechuan Chen <chenzechuan1@huawei.com>
Cc: bpf@vger.kernel.org
Cc: llvm@lists.linux.dev
Cc: yaowenbin <yaowenbin1@huawei.com>
Link: https://lore.kernel.org/r/20220826164242.43412-15-irogers@google.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent d8e40b58
...@@ -436,8 +436,10 @@ static struct dso *findnew_dso(int pid, int tid, const char *filename, ...@@ -436,8 +436,10 @@ static struct dso *findnew_dso(int pid, int tid, const char *filename,
} }
if (dso) { if (dso) {
mutex_lock(&dso->lock);
nsinfo__put(dso->nsinfo); nsinfo__put(dso->nsinfo);
dso->nsinfo = nsi; dso->nsinfo = nsi;
mutex_unlock(&dso->lock);
} else } else
nsinfo__put(nsi); nsinfo__put(nsi);
...@@ -620,6 +622,7 @@ static int dso__read_build_id(struct dso *dso) ...@@ -620,6 +622,7 @@ static int dso__read_build_id(struct dso *dso)
if (dso->has_build_id) if (dso->has_build_id)
return 0; return 0;
mutex_lock(&dso->lock);
nsinfo__mountns_enter(dso->nsinfo, &nsc); nsinfo__mountns_enter(dso->nsinfo, &nsc);
if (filename__read_build_id(dso->long_name, &dso->bid) > 0) if (filename__read_build_id(dso->long_name, &dso->bid) > 0)
dso->has_build_id = true; dso->has_build_id = true;
...@@ -633,6 +636,7 @@ static int dso__read_build_id(struct dso *dso) ...@@ -633,6 +636,7 @@ static int dso__read_build_id(struct dso *dso)
free(new_name); free(new_name);
} }
nsinfo__mountns_exit(&nsc); nsinfo__mountns_exit(&nsc);
mutex_unlock(&dso->lock);
return dso->has_build_id ? 0 : -1; return dso->has_build_id ? 0 : -1;
} }
......
...@@ -1697,6 +1697,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil ...@@ -1697,6 +1697,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
*/ */
__symbol__join_symfs(filename, filename_size, dso->long_name); __symbol__join_symfs(filename, filename_size, dso->long_name);
mutex_lock(&dso->lock);
if (access(filename, R_OK) && errno == ENOENT && dso->nsinfo) { if (access(filename, R_OK) && errno == ENOENT && dso->nsinfo) {
char *new_name = filename_with_chroot(dso->nsinfo->pid, char *new_name = filename_with_chroot(dso->nsinfo->pid,
filename); filename);
...@@ -1705,6 +1706,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil ...@@ -1705,6 +1706,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
free(new_name); free(new_name);
} }
} }
mutex_unlock(&dso->lock);
} }
free(build_id_path); free(build_id_path);
......
...@@ -898,11 +898,15 @@ static int filename__read_build_id_ns(const char *filename, ...@@ -898,11 +898,15 @@ static int filename__read_build_id_ns(const char *filename,
static bool dso__build_id_mismatch(struct dso *dso, const char *name) static bool dso__build_id_mismatch(struct dso *dso, const char *name)
{ {
struct build_id bid; struct build_id bid;
bool ret = false;
if (filename__read_build_id_ns(name, &bid, dso->nsinfo) < 0) mutex_lock(&dso->lock);
return false; if (filename__read_build_id_ns(name, &bid, dso->nsinfo) >= 0)
ret = !dso__build_id_equal(dso, &bid);
return !dso__build_id_equal(dso, &bid); mutex_unlock(&dso->lock);
return ret;
} }
static int dso__cache_build_id(struct dso *dso, struct machine *machine, static int dso__cache_build_id(struct dso *dso, struct machine *machine,
...@@ -941,8 +945,10 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine, ...@@ -941,8 +945,10 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine,
if (!is_kallsyms && dso__build_id_mismatch(dso, name)) if (!is_kallsyms && dso__build_id_mismatch(dso, name))
goto out_free; goto out_free;
mutex_lock(&dso->lock);
ret = build_id_cache__add_b(&dso->bid, name, dso->nsinfo, ret = build_id_cache__add_b(&dso->bid, name, dso->nsinfo,
is_kallsyms, is_vdso, proper_name, root_dir); is_kallsyms, is_vdso, proper_name, root_dir);
mutex_unlock(&dso->lock);
out_free: out_free:
free(allocated_name); free(allocated_name);
return ret; return ret;
......
...@@ -501,6 +501,7 @@ static int __open_dso(struct dso *dso, struct machine *machine) ...@@ -501,6 +501,7 @@ static int __open_dso(struct dso *dso, struct machine *machine)
if (!name) if (!name)
return -ENOMEM; return -ENOMEM;
mutex_lock(&dso->lock);
if (machine) if (machine)
root_dir = machine->root_dir; root_dir = machine->root_dir;
...@@ -541,6 +542,7 @@ static int __open_dso(struct dso *dso, struct machine *machine) ...@@ -541,6 +542,7 @@ static int __open_dso(struct dso *dso, struct machine *machine)
unlink(name); unlink(name);
out: out:
mutex_unlock(&dso->lock);
free(name); free(name);
return fd; return fd;
} }
...@@ -559,8 +561,11 @@ static int open_dso(struct dso *dso, struct machine *machine) ...@@ -559,8 +561,11 @@ static int open_dso(struct dso *dso, struct machine *machine)
int fd; int fd;
struct nscookie nsc; struct nscookie nsc;
if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE) if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE) {
mutex_lock(&dso->lock);
nsinfo__mountns_enter(dso->nsinfo, &nsc); nsinfo__mountns_enter(dso->nsinfo, &nsc);
mutex_unlock(&dso->lock);
}
fd = __open_dso(dso, machine); fd = __open_dso(dso, machine);
if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE) if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
nsinfo__mountns_exit(&nsc); nsinfo__mountns_exit(&nsc);
......
...@@ -181,7 +181,10 @@ struct map *map__new(struct machine *machine, u64 start, u64 len, ...@@ -181,7 +181,10 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
if (!(prot & PROT_EXEC)) if (!(prot & PROT_EXEC))
dso__set_loaded(dso); dso__set_loaded(dso);
} }
mutex_lock(&dso->lock);
nsinfo__put(dso->nsinfo);
dso->nsinfo = nsi; dso->nsinfo = nsi;
mutex_unlock(&dso->lock);
if (build_id__is_defined(bid)) { if (build_id__is_defined(bid)) {
dso__set_build_id(dso, bid); dso__set_build_id(dso, bid);
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "color.h" #include "color.h"
#include "map.h" #include "map.h"
#include "maps.h" #include "maps.h"
#include "mutex.h"
#include "symbol.h" #include "symbol.h"
#include <api/fs/fs.h> #include <api/fs/fs.h>
#include "trace-event.h" /* For __maybe_unused */ #include "trace-event.h" /* For __maybe_unused */
...@@ -180,8 +181,10 @@ struct map *get_target_map(const char *target, struct nsinfo *nsi, bool user) ...@@ -180,8 +181,10 @@ struct map *get_target_map(const char *target, struct nsinfo *nsi, bool user)
map = dso__new_map(target); map = dso__new_map(target);
if (map && map->dso) { if (map && map->dso) {
mutex_lock(&map->dso->lock);
nsinfo__put(map->dso->nsinfo); nsinfo__put(map->dso->nsinfo);
map->dso->nsinfo = nsinfo__get(nsi); map->dso->nsinfo = nsinfo__get(nsi);
mutex_unlock(&map->dso->lock);
} }
return map; return map;
} else { } else {
......
...@@ -1791,6 +1791,7 @@ int dso__load(struct dso *dso, struct map *map) ...@@ -1791,6 +1791,7 @@ int dso__load(struct dso *dso, struct map *map)
char newmapname[PATH_MAX]; char newmapname[PATH_MAX];
const char *map_path = dso->long_name; const char *map_path = dso->long_name;
mutex_lock(&dso->lock);
perfmap = strncmp(dso->name, "/tmp/perf-", 10) == 0; perfmap = strncmp(dso->name, "/tmp/perf-", 10) == 0;
if (perfmap) { if (perfmap) {
if (dso->nsinfo && (dso__find_perf_map(newmapname, if (dso->nsinfo && (dso__find_perf_map(newmapname,
...@@ -1800,7 +1801,6 @@ int dso__load(struct dso *dso, struct map *map) ...@@ -1800,7 +1801,6 @@ int dso__load(struct dso *dso, struct map *map)
} }
nsinfo__mountns_enter(dso->nsinfo, &nsc); nsinfo__mountns_enter(dso->nsinfo, &nsc);
mutex_lock(&dso->lock);
/* check again under the dso->lock */ /* check again under the dso->lock */
if (dso__loaded(dso)) { if (dso__loaded(dso)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment