[PATCH 07/11] perf tools: Add O_CLOEXEC to open() calls in DSO and ELF code

From: Arnaldo Carvalho de Melo

Date: Mon Jun 08 2026 - 21:13:03 EST


From: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>

open() calls in dso.c and symbol-elf.c omit O_CLOEXEC, which leaks
file descriptors to child processes spawned during symbol resolution
(e.g., addr2line, objdump). This can exhaust the fd limit during
long profiling sessions or when processing many DSOs.

Add O_CLOEXEC to all open() calls in both files (12 call sites).

Fixes: cdd059d731eeb466 ("perf tools: Move dso_* related functions into dso object")
Fixes: e5a1845fc0aeca85 ("perf symbols: Split out util/symbol-elf.c")
Reported-by: sashiko-bot <sashiko-bot@xxxxxxxxxx>
Cc: Jiri Olsa <jolsa@xxxxxxxxxx>
Cc: Namhyung Kim <namhyung@xxxxxxxxxx>
Reviewed-by: Ian Rogers <irogers@xxxxxxxxxx>
Assisted-by: Claude Opus 4.6 <noreply@xxxxxxxxxxxxx>
Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
---
tools/perf/util/dso.c | 4 ++--
tools/perf/util/symbol-elf.c | 20 ++++++++++----------
2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 7dced896c64eafd7..fb2e78fe2aa8eb94 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -344,7 +344,7 @@ int filename__decompress(const char *name, char *pathname,
* descriptor to the uncompressed file.
*/
if (!compressions[comp].is_compressed(name))
- return open(name, O_RDONLY);
+ return open(name, O_RDONLY | O_CLOEXEC);

fd = mkstemp(tmpbuf);
if (fd < 0) {
@@ -1911,7 +1911,7 @@ static const u8 *__dso__read_symbol(struct dso *dso, const char *symfs_filename,
int saved_errno;

nsinfo__mountns_enter(dso__nsinfo(dso), &nsc);
- fd = open(symfs_filename, O_RDONLY);
+ fd = open(symfs_filename, O_RDONLY | O_CLOEXEC);
saved_errno = errno;
nsinfo__mountns_exit(&nsc);
if (fd < 0) {
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 186e6d92ac3d7742..c2bdfd0003df2abe 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -217,7 +217,7 @@ bool filename__has_section(const char *filename, const char *sec)
GElf_Shdr shdr;
bool found = false;

- fd = open(filename, O_RDONLY);
+ fd = open(filename, O_RDONLY | O_CLOEXEC);
if (fd < 0)
return false;

@@ -872,7 +872,7 @@ static int read_build_id(const char *filename, struct build_id *bid)
if (size < BUILD_ID_SIZE)
goto out;

- fd = open(filename, O_RDONLY);
+ fd = open(filename, O_RDONLY | O_CLOEXEC);
if (fd < 0)
goto out;

@@ -935,7 +935,7 @@ int sysfs__read_build_id(const char *filename, struct build_id *bid)
size_t size = sizeof(bid->data);
int fd, err = -1;

- fd = open(filename, O_RDONLY);
+ fd = open(filename, O_RDONLY | O_CLOEXEC);
if (fd < 0)
goto out;

@@ -995,7 +995,7 @@ int filename__read_debuglink(const char *filename, char *debuglink,
if (err >= 0)
goto out;

- fd = open(filename, O_RDONLY);
+ fd = open(filename, O_RDONLY | O_CLOEXEC);
if (fd < 0)
goto out;

@@ -1153,7 +1153,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,

type = dso__symtab_type(dso);
} else {
- fd = open(name, O_RDONLY);
+ fd = open(name, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
*dso__load_errno(dso) = errno;
return -1;
@@ -1952,7 +1952,7 @@ static int kcore__open(struct kcore *kcore, const char *filename)
{
GElf_Ehdr *ehdr;

- kcore->fd = open(filename, O_RDONLY);
+ kcore->fd = open(filename, O_RDONLY | O_CLOEXEC);
if (kcore->fd == -1)
return -1;

@@ -1985,7 +1985,7 @@ static int kcore__init(struct kcore *kcore, char *filename, int elfclass,
if (temp)
kcore->fd = mkstemp(filename);
else
- kcore->fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400);
+ kcore->fd = open(filename, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0400);
if (kcore->fd == -1)
return -1;

@@ -2461,11 +2461,11 @@ static int kcore_copy__compare_files(const char *from_filename,
{
int from, to, err = -1;

- from = open(from_filename, O_RDONLY);
+ from = open(from_filename, O_RDONLY | O_CLOEXEC);
if (from < 0)
return -1;

- to = open(to_filename, O_RDONLY);
+ to = open(to_filename, O_RDONLY | O_CLOEXEC);
if (to < 0)
goto out_close_from;

@@ -2883,7 +2883,7 @@ int get_sdt_note_list(struct list_head *head, const char *target)
Elf *elf;
int fd, ret;

- fd = open(target, O_RDONLY);
+ fd = open(target, O_RDONLY | O_CLOEXEC);
if (fd < 0)
return -EBADF;

--
2.54.0