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

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.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent d8e40b58
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -436,8 +436,10 @@ static struct dso *findnew_dso(int pid, int tid, const char *filename,
	}

	if (dso) {
		mutex_lock(&dso->lock);
		nsinfo__put(dso->nsinfo);
		dso->nsinfo = nsi;
		mutex_unlock(&dso->lock);
	} else
		nsinfo__put(nsi);

@@ -620,6 +622,7 @@ static int dso__read_build_id(struct dso *dso)
	if (dso->has_build_id)
		return 0;

	mutex_lock(&dso->lock);
	nsinfo__mountns_enter(dso->nsinfo, &nsc);
	if (filename__read_build_id(dso->long_name, &dso->bid) > 0)
		dso->has_build_id = true;
@@ -633,6 +636,7 @@ static int dso__read_build_id(struct dso *dso)
		free(new_name);
	}
	nsinfo__mountns_exit(&nsc);
	mutex_unlock(&dso->lock);

	return dso->has_build_id ? 0 : -1;
}
+2 −0
Original line number Diff line number Diff line
@@ -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);

		mutex_lock(&dso->lock);
		if (access(filename, R_OK) && errno == ENOENT && dso->nsinfo) {
			char *new_name = filename_with_chroot(dso->nsinfo->pid,
							      filename);
@@ -1705,6 +1706,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
				free(new_name);
			}
		}
		mutex_unlock(&dso->lock);
	}

	free(build_id_path);
+9 −3
Original line number Diff line number Diff line
@@ -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)
{
	struct build_id bid;
	bool ret = false;

	if (filename__read_build_id_ns(name, &bid, dso->nsinfo) < 0)
		return false;
	mutex_lock(&dso->lock);
	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,
@@ -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))
		goto out_free;

	mutex_lock(&dso->lock);
	ret = build_id_cache__add_b(&dso->bid, name, dso->nsinfo,
				    is_kallsyms, is_vdso, proper_name, root_dir);
	mutex_unlock(&dso->lock);
out_free:
	free(allocated_name);
	return ret;
+6 −1
Original line number Diff line number Diff line
@@ -501,6 +501,7 @@ static int __open_dso(struct dso *dso, struct machine *machine)
	if (!name)
		return -ENOMEM;

	mutex_lock(&dso->lock);
	if (machine)
		root_dir = machine->root_dir;

@@ -541,6 +542,7 @@ static int __open_dso(struct dso *dso, struct machine *machine)
		unlink(name);

out:
	mutex_unlock(&dso->lock);
	free(name);
	return fd;
}
@@ -559,8 +561,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) {
		mutex_lock(&dso->lock);
		nsinfo__mountns_enter(dso->nsinfo, &nsc);
		mutex_unlock(&dso->lock);
	}
	fd = __open_dso(dso, machine);
	if (dso->binary_type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
		nsinfo__mountns_exit(&nsc);
+3 −0
Original line number Diff line number Diff line
@@ -181,7 +181,10 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
			if (!(prot & PROT_EXEC))
				dso__set_loaded(dso);
		}
		mutex_lock(&dso->lock);
		nsinfo__put(dso->nsinfo);
		dso->nsinfo = nsi;
		mutex_unlock(&dso->lock);

		if (build_id__is_defined(bid)) {
			dso__set_build_id(dso, bid);
Loading