From: sashiko-bot@kernel.org
To: "Namhyung Kim" <namhyung@kernel.org>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v2 06/10] perf tools: Factor out dso__find_binary_type()
Date: Wed, 07 Oct 2026 00:04:51 +0000 [thread overview]
Message-ID: <sashiko-outbox-162548@kernel.org> (raw)
In-Reply-To: <20261006234315.920817-7-namhyung@kernel.org>
Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [High] perf: Guest kernel modules fail to open due to hardcoded root_dir
- [High] perf: Strict .text section check breaks data-only DSOs and NO_LIBELF builds
- [High] perf: Concurrent Read-Modify-Write data race on struct dso bitfields
- [High] perf: Use-After-Free of dso->nsinfo in __dso__find_binary_type due to missing dso__lock
- [Medium] perf: Explicitly resolved binary types are unconditionally overwritten
- [Medium] perf: Bypassing do_open() permanently caches EMFILE failures as NOT_FOUND
- [Low] perf: Redundant double decompression of compressed kernel modules
--
commit 8b41de1355b0e2f1d37b604c80238237fc833f0f
Author: Namhyung Kim <namhyung@kernel.org>
perf tools: Factor out dso__find_binary_type()
Separate out the logic to detect binary type of a DSO. It checks if the
candidate file contains ".text" section. It should be called under the
_dso__data_open_lock.
Introduce bintype_searched flag and it accessors to prevent repeated
(failed) search.
> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> index 913877b84b2d4..f5054c18a2e93 100644
> --- a/tools/perf/util/dso.c
> +++ b/tools/perf/util/dso.c
> @@ -833,7 +833,7 @@ void dso__data_close(struct dso *dso)
> mutex_unlock(dso__data_open_lock());
> }
>
> -static void try_to_open_dso(struct dso *dso, struct machine *machine)
> +static enum dso_binary_type __dso__find_binary_type(struct dso *dso)
> EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock)
> {
> enum dso_binary_type binary_type_data[] = {
> @@ -842,25 +842,103 @@ static void try_to_open_dso(struct dso *dso, struct machine *machine)
> DSO_BINARY_TYPE__NOT_FOUND,
> };
> int i = 0;
> - struct dso_data *dso_data = dso__data(dso);
> + char *path;
> + bool found = false;
> + bool decomp = false;
>
> - if (dso_data->fd >= 0)
> - return;
> + if (dso__bintype_searched(dso))
> + return dso__binary_type(dso);
> + dso__set_bintype_searched(dso);
[Severity: High]
Does this code introduce a data race on the struct dso bitfields?
The dso__set_bintype_searched() function modifies the bintype_searched
bitfield under the global _dso__data_open_lock. However, adjacent bitfields
like debuginfo_searched and long_name_allocated share the same memory
location and are modified under different locks (dso__lock(dso) and
dsos->lock).
Concurrent execution could cause compiler-generated read-modify-write
operations to overlap, resulting in dropped flags or memory leaks if
long_name_allocated is clobbered.
[ ... ]
> + case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
> + case DSO_BINARY_TYPE__BUILD_ID_CACHE:
> + /* We don't expect these are set; fall through */
> + case DSO_BINARY_TYPE__NOT_FOUND:
> + /* Let's find it out (for user DSOs or kernel modules) */
> + break;
[Severity: Medium]
Does this fall-through discard valid binary types that have already been
resolved elsewhere in the system?
When symbol.c successfully resolves and sets the binary type (such as
DSO_BINARY_TYPE__SYSTEM_PATH_DSO or DSO_BINARY_TYPE__BUILD_ID_CACHE),
this switch statement deliberately falls through. The loop below then
unconditionally overwrites the previously valid binary type.
If the fallback types lack a .text section (such as data-only DSOs), the
state is permanently left as NOT_FOUND, preventing perf from reading them.
[ ... ]
> do {
> dso__set_binary_type(dso, binary_type_data[i++]);
>
> - dso_data->fd = open_dso(dso, machine);
> - if (dso_data->fd >= 0)
> - goto out;
> + path = dso__get_filename(dso, "", &decomp, dso__binary_type(dso));
[Severity: High]
Does hardcoding the root directory to an empty string break path resolution
for guest kernel modules?
When the fallback logic looks up types like DSO_BINARY_TYPE__GUEST_KMODULE,
it passes "" to dso__get_filename() instead of machine->root_dir.
This causes dso__get_filename() to construct an invalid path missing the
guest's root directory. The file cannot be found, filename__has_section()
fails, and subsequent calls to open_dso() will fail.
[Severity: High]
Does calling dso__get_filename() without holding dso__lock(dso) cause a
use-after-free of dso->nsinfo?
The new __dso__find_binary_type() helper executes with only the global
_dso__data_open_lock held. It calls dso__get_filename(), which invokes
dso__filename_with_chroot() and dereferences dso->nsinfo to read the
process ID.
Concurrently, another thread could call dso__set_nsinfo() (which acquires
dso__lock(dso)), replacing the nsinfo pointer and freeing the old one via
nsinfo__put(). Since this read path ignores dso__lock(dso), it can read
the freed pointer.
> + if (path == NULL)
> + continue;
> +
> + found = filename__has_section(path, ".text");
[Severity: High]
Does this strict .text section check break data-only DSOs and NO_LIBELF
builds?
Prior to this patch, try_to_open_dso() discovered the DSO by calling
open_dso(). If the file existed and was readable, the open succeeded. This
patch introduces a strict requirement that a DSO must contain a .text
section.
Perf commonly profiles memory data accesses (like perf mem or perf c2c)
hitting data-only DSOs. For these files, filename__has_section() evaluates
to false, forcing the binary type to NOT_FOUND. Furthermore, if perf is
compiled without libelf (NO_LIBELF=1), filename__has_section() is stubbed
to unconditionally return false, breaking user DSO loading entirely.
[Severity: Medium]
Can this bypass of do_open() permanently cache EMFILE failures as NOT_FOUND?
The filename__has_section() function uses a raw open() without the FD limit
(EMFILE) handling and LRU eviction logic normally provided by do_open() and
close_first_dso().
If perf hits RLIMIT_NOFILE, open() returns -1, and filename__has_section()
silently returns false. __dso__find_binary_type() then assumes the binary
is invalid, sets bintype_searched = 1, and permanently caches
DSO_BINARY_TYPE__NOT_FOUND, breaking data access to the DSO for the rest
of the execution.
[ ... ]
> +static void try_to_open_dso(struct dso *dso, struct machine *machine)
> + EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock)
> +{
> + struct dso_data *dso_data = dso__data(dso);
> +
> + if (dso_data->fd >= 0)
> + return;
> +
> + __dso__find_binary_type(dso);
> + dso_data->fd = open_dso(dso, machine);
[Severity: Low]
Does this result in redundant double decompression of compressed kernel
modules?
The call to dso__get_filename() in __dso__find_binary_type() decompresses
a compressed kernel module to a temporary file. After checking for a .text
section, dso__put_filename() unlinks this temporary file.
Immediately after returning, try_to_open_dso() calls open_dso(), which
ultimately calls dso__get_filename() again, forcing a second decompression
of the exact same kernel module.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261006234315.920817-1-namhyung@kernel.org?part=6
next prev parent reply other threads:[~2026-10-07 0:04 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-06 23:43 [PATCH v2 00/10] perf symbol: Properly set DSO binary/symtab types Namhyung Kim
2026-10-06 23:43 ` [PATCH v2 01/10] perf tools: Remove redundant dso data init Namhyung Kim
2026-10-06 23:49 ` sashiko-bot
2026-10-06 23:43 ` [PATCH v2 02/10] perf tools: Try linked debug files for DSO debug info Namhyung Kim
2026-10-06 23:54 ` sashiko-bot
2026-10-10 5:38 ` Namhyung Kim
2026-10-06 23:43 ` [PATCH v2 03/10] perf symbol: Update symtab type of vmlinux from build-id cache Namhyung Kim
2026-10-06 23:54 ` sashiko-bot
2026-10-06 23:43 ` [PATCH v2 04/10] perf symbol: Set binary/symtab type for split kallsyms Namhyung Kim
2026-10-06 23:58 ` sashiko-bot
2026-10-10 5:42 ` Namhyung Kim
2026-10-06 23:43 ` [PATCH v2 05/10] perf symbol: Set dso symtab type for libbfd Namhyung Kim
2026-10-06 23:57 ` sashiko-bot
2026-10-10 5:49 ` Namhyung Kim
2026-10-06 23:43 ` [PATCH v2 06/10] perf tools: Factor out dso__find_binary_type() Namhyung Kim
2026-10-07 0:04 ` sashiko-bot [this message]
2026-10-10 6:17 ` Namhyung Kim
2026-10-06 23:43 ` [PATCH v2 07/10] perf symbol: Set binary type for JIT map DSOs Namhyung Kim
2026-10-06 23:51 ` sashiko-bot
2026-10-06 23:43 ` [PATCH v2 08/10] perf symbol: Do not set binary type from symtab type Namhyung Kim
2026-10-06 23:57 ` sashiko-bot
2026-10-10 6:41 ` Namhyung Kim
2026-10-06 23:43 ` [PATCH v2 09/10] perf annotate: Simplify symbol__disassemble() with dso binary_type Namhyung Kim
2026-10-07 0:01 ` sashiko-bot
2026-10-10 6:47 ` Namhyung Kim
2026-10-06 23:43 ` [PATCH v2 10/10] perf test: Fix dso data tests Namhyung Kim
2026-10-06 23:59 ` sashiko-bot
2026-10-10 6:48 ` Namhyung Kim
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-162548@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=namhyung@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.