Commit Graph

1463479 Commits

Author SHA1 Message Date
PVS Narasimha Rao
6ae6fb96cc perf test sample-parsing: Validate PERF_FORMAT_GROUP values without LOST
The sample parsing test only validates grouped read values when
PERF_FORMAT_LOST is present.

For PERF_FORMAT_GROUP without PERF_FORMAT_LOST, the contents of
read.group.values[] are not validated, allowing corruption of the parsed
value and id fields to go undetected.

The values are also handed to the synthesis as a plain array of struct
sample_read_value, which always has a 24-byte stride, while
read.group.values is expected to be packed according to read_format --
evsel__parse_sample() points it into the event data.  Without
PERF_FORMAT_LOST the stride is 16, so both the synthesis and the
comparison walk overlapping bytes and the test passes regardless of the
contents.

Validate value and id for grouped reads and continue to validate lost
when PERF_FORMAT_LOST is present, walking the entries with
next_sample_read_value().  Also build the input packed using
sample_read_value_size() so the compared fields are the real ones.

Verified with a deliberate stride bug in copy_read_group_values(): the
test still passes without this change and fails at read_format 0xc with
it applied.

Signed-off-by: PVS Narasimha Rao <venkatasuryapala@gmail.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15 06:37:18 -07:00
Arnaldo Carvalho de Melo
62972e5644 perf dso: Replace assert with runtime check in dso__read_symbol()
dso__read_symbol() asserts that len <= jited_prog_len, where len comes
from sym->end - sym->start (parsed from PERF_RECORD_KSYMBOL in
perf.data).  Both values originate from untrusted file input.

With NDEBUG (production builds), the assert is compiled out, allowing
an out-of-bounds heap read when the BPF program buffer is accessed.
Without NDEBUG, a crafted perf.data crashes perf with an assertion
failure.

Replace the assert with a runtime bounds check that returns NULL with
an appropriate error code, matching the existing error handling
pattern in this function.

Fixes: aa04707f50 ("perf dso: Support BPF programs in dso__read_symbol()")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Cc: Song Liu <song@kernel.org>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15 06:37:14 -07:00
Arnaldo Carvalho de Melo
390a9461cd perf dso: Guard against cache underflow on short reads in dso_cache__memcpy()
dso_cache__memcpy() computes cache_offset = offset - cache->offset,
then cache_size = min(cache->size - cache_offset, size).  The RB tree
lookup in __dso_cache__find() matches using the full
DSO__DATA_CACHE_SIZE window, but cache->size reflects the actual pread
return value from dso_cache__populate().

A short pread (e.g. near end-of-file) makes cache->size smaller than
DSO__DATA_CACHE_SIZE.  If a subsequent access targets an offset past
cache->offset + cache->size but within the DSO__DATA_CACHE_SIZE
window, the cache entry is found but cache_offset exceeds cache->size.
Since both are u64, the subtraction cache->size - cache_offset wraps
to a large value, min() selects the caller's size, and memcpy reads
out of bounds.

Return 0 for an offset past the valid cached data.  For a regular
file a short pread only happens at end-of-file, so 0 is what a direct
pread() at that offset would return: cached_io() stops its read loop
as on EOF.  Re-reading from the backing file would not help — a
second pread at the same offset returns the same short count.

Fixes: 366df72657 ("perf dso: Refactor dso_cache__read()")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15 06:37:09 -07:00
Arnaldo Carvalho de Melo
075d2c3235 perf dso: Use stored fd error instead of stale errno in file_read() and file_size()
file_read() and file_size() use ret = -errno when
dso__data(dso)->fd is negative after try_to_open_dso() fails.  By this
point errno has been through mutex_lock(), nsinfo__mountns_enter(), and
multiple open() attempts inside try_to_open_dso() — it no longer
reflects the actual open failure.  If errno happens to be 0, ret = 0
looks like EOF rather than an error, and file_size() callers like
dso__data_size() would then report a zero-sized file instead of
failing.

dso__data(dso)->fd is always negative on failure — -errno from
__open_dso() when no filename could be built (e.g. -EINVAL, -ENOENT),
or -1 when do_open() itself failed — and never 0, so use it directly
instead of reading the stale global errno.

No assert() or comment is needed after the assignment: the enclosing
if (dso__data(dso)->fd < 0) already guarantees ret < 0
[Namhyung Kim review].

Fixes: 33bdedcea2 ("perf tools: Protect dso cache fd with a mutex")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15 06:37:04 -07:00
Arnaldo Carvalho de Melo
10f452dc2d perf dso: Guard close() against invalid fd in dso__decompress_kmodule_path()
dso__decompress_kmodule_path() unconditionally calls close(fd) on the
return value of decompress_kmodule().  When decompression fails or the
DSO is not compressed, decompress_kmodule() returns -1.  close(-1)
fails with EBADF and clobbers errno, which callers up the chain
(dso__get_filename → __open_dso) depend on for error propagation.

Guard the close() call with fd >= 0 so only valid file descriptors are
closed.

Fixes: 42b3fa6708 ("perf tools: Introduce dso__decompress_kmodule_{fd,path}")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15 06:37:00 -07:00
Arnaldo Carvalho de Melo
51a7a9ddcb perf dso: Guard against errno==0 when dso__get_filename() returns NULL
__open_dso() computes fd = -errno when dso__get_filename() returns NULL.
Some failure paths in dso__get_filename() (e.g. binary type mismatch)
return NULL without making a syscall, leaving errno at 0 from a prior
successful call.  fd = -0 = 0, which is stdin — subsequent code treats
it as a valid file descriptor.

Fall back to ENOENT when errno is 0, ensuring fd is always negative on
failure.

The forced ENOENT stays in errno for the callers that check it after a
negative fd.  It must not misdirect the try_to_open_dso() fallback
loop, though: dso__get_filename()'s chroot fallback used to accept a
stale ENOENT even when stat() succeeded on a non-regular file (e.g. a
directory).  Re-stat() there and only take the chroot path when
stat() actually failed with ENOENT [sashiko-bot review of PATCH 1/5].

Fixes: eba5102d2f ("perf tools: Add global list of opened dso objects")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-15 06:36:55 -07:00
Arnaldo Carvalho de Melo
d17c5b7709 perf build: install-build-deps: add RHEL family devel package mapping
With the Fedora mapping in place, this patch extends it to the RHEL
family (RHEL, CentOS Stream, Rocky Linux, AlmaLinux, Oracle Linux),
which shares most Fedora package names and runs dnf (RHEL 8 and
later).  The names that differ are handled by probing the enabled
repos:

  - zlib.h comes from zlib-ng-compat-devel on the RHEL 10 family,
    zlib-devel on RHEL 9 and earlier;
  - there is no java-latest-openjdk-devel: the JDK devel package is
    versioned per release, java-21-openjdk-devel on the RHEL 10
    family, java-17-openjdk-devel on RHEL 9, java-11-openjdk-devel
    on RHEL 8;
  - libbpf-devel and capstone-devel live in the CRB repo on RHEL and
    CentOS Stream 10, in EPEL on RHEL 9 and earlier;
  - libbabeltrace2-devel is not packaged on the RHEL 10 family.

Packages not available on the enabled repos are skipped instead of
aborting the dnf transaction, and are listed at the end of the run, with
the repo that provides them pointed out in the header comment and help
text: a distro with CRB/EPEL enabled gets the full set, one without them
still installs what it can.

This also holds for the base set: e.g.  'rust' exists only as the
rust-toolset AppStream module on RHEL 8 and 9, where it is not
installable as a plain package, so it is skipped and noted there instead
of failing the whole dnf transaction.

The base set lists pkgconf-pkg-config instead of pkgconfig: both
families have been on pkgconf since Fedora 26 / RHEL 8, where
'pkgconfig' lives only as a virtual Provides of that subpackage, and
a minimal RHEL-family container may not have it preinstalled.

Validated on a fresh CentOS Stream 10 distrobox container, with the
CRB repo enabled, so the host system is not modified:

    distrobox create --image quay.io/centos/centos:stream10
    distrobox enter centos-stream10
    dnf config-manager --set-enabled crb
    make -C tools/perf install-build-deps

which installed the 28 available mapped packages; libbabeltrace2-devel, the
only mapped package with no RHEL 10 package, is reported at the end
of the run.

A subsequent 'make -C tools/perf feature-dump' enabled every feature
with an external dependency the RHEL 10 family provides, including
libbpf and libcapstone from the CRB repo, with only
babeltrace2-ctf-writer left out along with the deliberately unmapped
opt-in features.

Re-running the target is a no-op (dnf reports "Nothing to do"); with the
CRB repo disabled, the skipped packages are instead listed in the
end-of-run note, whose header comment and help text point out which repo
provides them.

Members of the family without dnf (RHEL 7 and earlier, e.g. Oracle
Linux 7, a yum-only distro) are rejected with an explicit error while
the dnf-based members get the full mapping.

Example of its --list:

  $ grep PRETTY_NAME /etc/os-release
  PRETTY_NAME="Fedora Linux 44 (Toolbx Container Image)"
  $ tools/perf/scripts/install-build-deps.sh --list --distro rhel
  bison
  capstone-devel
  clang-devel
  elfutils-debuginfod-client-devel
  elfutils-devel
  elfutils-libelf-devel
  flex
  gcc
  gcc-c++
  glibc-devel
  java-latest-openjdk-devel
  kernel-headers
  libbabeltrace2-devel
  libbpf-devel
  libpfm-devel
  libstdc++-devel
  libtraceevent-devel
  libzstd-devel
  llvm-devel
  make
  numactl-devel
  openssl-devel
  pkgconf-pkg-config
  python3-devel
  python3-setuptools
  rust
  slang-devel
  systemtap-sdt-devel
  xz-devel
  zlib-ng-compat-devel
  $

Assisted-by: opencode:deepseek-v4-flash-free
Assisted-by: claude:claude-opus-4-7
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-12 06:17:49 -07:00
Arnaldo Carvalho de Melo
b60f6bc128 perf build: Remove leftover feature tests for removed cxx and clang support
56b11a2126 ("perf bpf: Remove support for embedding clang for
compiling BPF events (-e foo.c)") removed the test-cxx.cpp and
test-clang.cpp sources, but left behind their entries in the feature
test FILES list, the build rules and the cxx and clang entries in
FEATURE_TESTS_EXTRA.

Since the sources no longer exist, those rules would always fail,
making the artificial feature-cxx and feature-clang results to be
perpetually disabled/absent, remove the leftover entries, making the
feature test scripts list match the available sources.

Fixes: 56b11a2126 ("perf bpf: Remove support for embedding clang for compiling BPF events (-e foo.c)")
Cc: Ian Rogers <irogers@google.com>
Assisted-by: opencode:deepseek-v4-flash-free
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-12 06:17:49 -07:00
Arnaldo Carvalho de Melo
01c7a389d1 perf build: install-build-deps: add Debian devel package mapping
With the Fedora and Ubuntu mappings in place, this patch adds Debian
support: Debian installs the same devel packages, under the same
names, as the Ubuntu mapping, so it reuses debian_pkg_for() and
debian_base_pkgs as-is, with only auto-detection in detect_distro()
(and the shared apt-get install path) added, keeping the script's
per-distro dispatch ready for distros with their own package names.

Validated on a fresh Debian 13 (trixie) container so the host system
is not modified:

    distrobox create --image debian:trixie
    distrobox enter debian-trixie
    make -C tools/perf install-build-deps

which installed the 29 mapped packages; re-running the target is a
no-op (apt-get reports "0 newly installed").  A subsequent clean build
enabled the same feature set as Ubuntu: 'perf version --build-options'
shows every feature with an external dependency Debian has a package
for [on], including the BPF skeletons compiled with clang/llvm
(libLLVM), the python binding and the C++-based features, with only
the deliberately unmapped libbfd family, libperl, libunwind and the
CoreSight (libopencsd) packages [OFF].

RHEL, whose package mapping is largely similar to Fedora's, is the
remaining planned distro, to be enabled once that mapping is
validated on it.

Example of its --list:

  $ grep PRETTY_NAME /etc/os-release
  PRETTY_NAME="Fedora Linux 44 (Toolbx Container Image)"
  $ tools/perf/scripts/install-build-deps.sh --list --distro debian
  bison
  clang
  default-jdk
  flex
  g++
  gcc
  libbabeltrace2-dev
  libbpf-dev
  libc6-dev
  libcapstone-dev
  libdebuginfod-dev
  libdw-dev
  libelf-dev
  liblzma-dev
  libnuma-dev
  libpfm4-dev
  libslang2-dev
  libssl-dev
  libtraceevent-dev
  libzstd-dev
  linux-libc-dev
  llvm-dev
  make
  pkg-config
  python3-dev
  python3-setuptools
  rustc
  systemtap-sdt-dev
  zlib1g-dev
  $

Assisted-by: opencode:deepseek-v4-flash-free
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-12 06:17:48 -07:00
Arnaldo Carvalho de Melo
1331bb5106 perf build: install-build-deps: add Ubuntu devel package mapping
With the framework and Fedora mapping in place, this patch adds the
Ubuntu (apt) mapping: same feature-to-package correspondence as the
Fedora one, adapted to Debian packaging conventions (libfoo-dev), on
a per-distro dispatch so future distros can pick their own mapping or
reuse one of these (Debian shares the Ubuntu mapping).

Notable differences from Fedora:

  - base set: g++ (ships libstdc++-*-dev, covering cxa-demangle),
    pkg-config (installed implicitly by Fedora's default toolchain
    metapackage, but not by Ubuntu's), linux-libc-dev and libc6-dev
    instead of kernel-headers and glibc-devel, and rustc for rust;
  - cxa-demangle maps to nothing, covered by g++'s libstdc++;
  - the clang-bpf-co-re test needs the clang compiler binary (Fedora's
    clang-devel provides it transitively), and llvm-dev, which also
    brings llvm-config (deps on the llvm package), used by the
    llvm/llvm-perf tests;
  - libslang maps to libslang2-dev and jvmti to default-jdk;
  - the install command runs 'apt-get update' first since a fresh
    container has no package indexes, unlike dnf.

Validated on a fresh Ubuntu 26.04 distrobox container so the host
system is not modified:

    distrobox create --image ubuntu:26.04
    distrobox enter ubuntu-26-04
    make -C tools/perf install-build-deps

which installed the 29 mapped packages; a subsequent clean O= build
enabled every feature with an external dependency Ubuntu has a
package for: perf's build-options then showed all of them [on],
including the BPF skeletons requiring clang/llvm, the python binding
and the C++-based features, with only the deliberately unmapped
(deprecated) libbfd family, libperl and libunwind [OFF], and the
build linked libpfm, libbabeltrace2-ctf-writer, libcapstone,
libtraceevent, libslang, libnuma, libdw and libssl.  Re-running the
target is a no-op (apt-get reports "0 newly installed").

Debian (trixie) is the next planned distro: it shares this Ubuntu
mapping, so enabling it reuses it as-is, once it gets validated on a
Debian release.

Example of its --list:

  $ grep PRETTY_NAME /etc/os-release
  PRETTY_NAME="Fedora Linux 44 (Toolbx Container Image)"
  $ tools/perf/scripts/install-build-deps.sh --list --distro ubuntu
  bison
  clang
  default-jdk
  flex
  g++
  gcc
  libbabeltrace2-dev
  libbpf-dev
  libc6-dev
  libcapstone-dev
  libdebuginfod-dev
  libdw-dev
  libelf-dev
  liblzma-dev
  libnuma-dev
  libpfm4-dev
  libslang2-dev
  libssl-dev
  libtraceevent-dev
  libzstd-dev
  linux-libc-dev
  llvm-dev
  make
  pkg-config
  python3-dev
  python3-setuptools
  rustc
  systemtap-sdt-dev
  zlib1g-dev
  $

Assisted-by: opencode:deepseek-v4-flash-free
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-12 06:17:48 -07:00
Arnaldo Carvalho de Melo
9f83597eb5 perf build: install-build-deps: add Fedora devel package mapping
With the framework from the previous commit in place, this patch adds
the per-feature mapping for Fedora/dnf: for each feature test in
tools/build/feature/, the Fedora devel package providing the headers
or library the test compiles against, kept explicit in the script
next to the test that requires it.

Special cases:

  - test-libdebuginfod.c includes <elfutils/debuginfod.h>, provided
    by elfutils-debuginfod-client-devel, not elfutils-devel;
  - the cxa-demangle test links against libstdc++'s builtin demangler,
    pulling in libstdc++-devel;
  - the BPF-oriented features (bpf, clang-bpf-co-re) get their headers
    from the base packages and clang-devel.

Tests with no Fedora equivalent (bionic, compile-32, compile-x32) and
the opt-in/deprecated ones (libbfd disassembler family, GTK2, LIBPERL,
LIBUNWIND, CoreSight, and the tests perf itself doesn't check, like
libcpupower) are deliberately not mapped.

Validated on a fresh Fedora 44 toolbx container, so the host OS is not
modified:

    toolbox create fedora:44
    toolbox enter fedora:44
    make -C tools/perf install-build-deps

which installed the 29 mapped packages; a subsequent clean O= build
enabled every feature with an external dependency Fedora provides
(feature tests went to 1, except bionic/compile-32/compile-x32, which
have no Fedora equivalent, and the libunwind-debug-frame tests, whose
symbols Fedora's libunwind does not export), linking libpfm,
libbabeltrace2-ctf-writer, libcapstone, libtraceevent, libslang and
libnuma, as well as building the BPF skeletons requiring clang/llvm.
Re-running the target is a no-op (dnf reports "Nothing to do").

RHEL and its derivatives share most Fedora package names but are
refused by the script until this mapping is validated on them.

Example of its --list option:

  $ grep PRETTY_NAME /etc/os-release
  PRETTY_NAME="Fedora Linux 44 (Toolbx Container Image)"
  $ tools/perf/scripts/install-build-deps.sh --list
  bison
  capstone-devel
  clang-devel
  elfutils-debuginfod-client-devel
  elfutils-devel
  elfutils-libelf-devel
  flex
  gcc
  gcc-c++
  glibc-devel
  java-latest-openjdk-devel
  kernel-headers
  libbabeltrace2-devel
  libbpf-devel
  libpfm-devel
  libstdc++-devel
  libtraceevent-devel
  libzstd-devel
  llvm-devel
  make
  numactl-devel
  openssl-devel
  python3-devel
  python3-setuptools
  rust
  slang-devel
  systemtap-sdt-devel
  xz-devel
  zlib-devel
  $

Assisted-by: opencode:deepseek-v4-flash-free
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-12 06:17:48 -07:00
Arnaldo Carvalho de Melo
bc3fdd6adb perf build: Add install-build-deps framework to install devel packages
Installing the development packages needed to build perf is
error-prone on a fresh distro install: the packages are scattered
across the feature tests in tools/build/feature/, each checking for a
specific header/library, and the build only tells you what's missing
after failing a check.

This series adds a 'make -C tools/perf install-build-deps' target to
install them in one go, deriving the package list from the feature tests
themselves.

This commit adds the framework, on top of the parse-time compiler
probe guard from the previous commit:

- the install-build-deps target in tools/perf/Makefile.perf, exempted
  from the config/feature detection pass, since it must run in a fresh
  container, before gcc or pkg-config exist, to install them;
- the install-build-deps.sh script, with --list, --dry-run and
  --distro options, distro detection (Fedora and Ubuntu), dnf and
  apt-get drivers, root/passwordless-sudo handling, and the base
  packages common to any build: compiler, C++ compiler, make, flex,
  bison, libc and kernel headers, python3-setuptools (needed by the
  python binding) and rust (checked by the rust feature test);
- the parse-time probes for optional tools, like pkg-config, use
  'command -v' with stderr discarded, so a fresh container without
  them gets no 'which: no pkg-config in (...)' spew from make;
- the script does not rely on 'set -e': its error paths are explicit,
  since the make target runs it via $(SHELL), where a shebang option
  would be ignored anyway, so direct and make-driven runs behave the
  same.

The per-feature mappings, from each feature test to the devel package
providing its headers on a given distro, are added by the follow-up
patches, one per distro, together with the validation of each mapping
in a fresh container: until then the target installs just the base
toolchain.

Assisted-by: opencode:deepseek-v4-flash-free
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-12 06:17:48 -07:00
Arnaldo Carvalho de Melo
380e3f23bb tools build: Only probe the compiler at parse time when it is installed
Two parse-time probes still invoke $(CC) unconditionally:

- LP64 in tools/scripts/Makefile.arch, probing with
  $(CC) -E -x c, pulled in twice by tools/perf/Makefile.perf;
- CC_NO_CLANG in tools/scripts/Makefile.include, probing with
  $(CC) -dM -E -x c /dev/null.

In the corner case where gcc is not yet installed, the very setup the
install-build-deps target, added in the next patch of this series, is
meant for, these probes make even targets that never compile parse-time
spew errors like:

    /bin/sh: 1: gcc: not found
    /bin/sh: 1: gcc: not found
    /bin/sh: 1: gcc: not found

Guard both probes with 'command -v' using the first word of CC so a
missing compiler is handled silently with the same result as a failing
probe (CC_NO_CLANG and LP64 unset/0), and with no behavior change when
the compiler is installed.

Only the first word is consulted because CC may carry arguments such as
'ccache gcc', and shell implementations differ in how 'command -v'
handles multiple words (dash only checks the first, bash any of them),
so validating the whole CC value would silently disable both probes on
some make SHELLs.

Assisted-by: opencode:deepseek-v4-flash-free
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-12 06:17:48 -07:00
Michalis Niarchos
65785fb650 perf kvm: Fix memory leak in cmd_kvm()
Set the thread private data destructor.

Signed-off-by: Michalis Niarchos <michael.niarchos@gmail.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-12 06:04:18 -07:00
Michalis Niarchos
8564e01efb perf kvm: Fix memory leak in process_sample_event()
machine__resolve() indirectly acquires a thread reference via
machine__findnew_thread(). Release it, as suggested by the documentation
of the former.

Signed-off-by: Michalis Niarchos <michael.niarchos@gmail.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-12 06:04:16 -07:00
Ian Rogers
16a12a54e9 perf synthetic-events: Fix divide by zero in perf_event__synthesize_threads
If scandir() finds no matching tasks in /proc, n is 0. If thread_nr is > 1,
we bypass the single-thread fast path and then clamp thread_nr to n, making
it 0. This results in a divide by zero when calculating num_per_thread.

Handle n <= 1 early to use the single-thread fast path and prevent the
crash.

Fixes: 340b47f510 ("perf top: Implement multithreading for perf_event__synthesize_threads")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 22:02:42 -07:00
Ian Rogers
1ec13016ba perf python: Fix memory leak in pyrf__metrics_cb
In pyrf__metrics_cb, PyDict_SetItem does not steal the reference of the
key and value, so they need to be decref'ed after successful insertion
to avoid memory leaks.

Fixes: 47b3e95728 ("perf python: Add metrics function")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 22:02:41 -07:00
Ian Rogers
cb45ede21d perf python: Fix count_values memory leak in pyrf_evsel__read
In pyrf_evsel__read, if PyArg_ParseTuple fails, the allocated count_values
is leaked. Move the allocation of count_values after the PyArg_ParseTuple
call to prevent the memory leak.

Fixes: 739621f657 ("perf python: Add evsel read method")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 22:02:41 -07:00
Ian Rogers
b9514a9a13 perf python: Fix MetricGroup return type in perf.pyi
The metrics() function can return a dictionary where the value is either
a string or a list of strings, so the type signature in the stub file
should be Union[str, List[str]].

Fixes: 430da3cd03b4 ("perf python: Add perf.pyi stubs file")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 22:02:41 -07:00
Ian Rogers
b3d7c6c1a9 perf python: Add thread and PMU uninitialized checks
Add CHECK_INITIALIZED checks to the thread attribute getters
(get_pid, get_tid, get_ppid) to prevent crashes if they are accessed
before being properly initialized.

Fixes: 3b96bf7af60d ("perf python: Add python session abstraction wrapping perf's session")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 22:02:38 -07:00
Ian Rogers
b365402cd5 perf python: Zero initialize perf_data in pyrf_data__init
Replace path clearing with memset so the entire struct is zeroed,
preventing uninitialized fields from causing errors later.

Fixes: 4cd0142f7dec ("perf python: Add wrapper for perf_data file abstraction")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 21:58:11 -07:00
Ian Rogers
0b274050c4 perf python: Validate attribute setters in pyrf_evsel
If val is NULL when setting an attribute, PyErr_SetString should be
called as deleting the attribute isn't supported. In addition, ensure
PyErr_Occurred is checked before setting the attribute to avoid setting
a garbage value.

Fixes: 877108e42b ("perf tools: Initial python binding")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 21:58:11 -07:00
Ian Rogers
9a142beb1e perf python: Validate CPU and thread maps in pyrf_evsel__open
Add explicit Py_TYPE checks to ensure the arguments passed are
actually of the correct pyrf_thread_map and pyrf_cpu_map types.

Fixes: 877108e42b ("perf tools: Initial python binding")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 21:58:11 -07:00
Ian Rogers
612aca22a9 perf python: Check counts_values size in set_values
The set_values function incorrectly assumed the list contained exactly
5 elements. Add a check to prevent out-of-bounds access.

Fixes: 877108e42b ("perf tools: Initial python binding")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 21:58:11 -07:00
Ian Rogers
44e82c4d2f perf test: Fix skiplist leak in cmd_test
Fix a memory leak in cmd_test() where skiplist was not freed on
exit paths.

Assisted-by: Antigravity:gemini-3.1-pro
Fixes: 2ae828786c ("perf test: Allow skipping tests")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 21:58:11 -07:00
Ian Rogers
54ba44db4d perf synthetic-events: Fix uninitialized pthread_join
In perf_event__synthesize_threads(), fix an uninitialized pthread_join()
call when thread creation fails by only joining the successfully
created threads.

Assisted-by: Antigravity:gemini-3.1-pro
Fixes: 340b47f510 ("perf top: Implement multithreading for perf_event__synthesize_threads")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 21:58:11 -07:00
Ian Rogers
38d778acbe perf python: Fix memory leak in pyrf_evlist__get_pollfd
Fix a Python list object leak in pyrf_evlist__get_pollfd() by adding
a missing Py_DECREF on the error exit path.

Assisted-by: Antigravity:gemini-3.1-pro
Fixes: 877108e42b ("perf tools: Initial python binding")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 21:58:11 -07:00
Ian Rogers
08e96e3c73 perf tools: Fix sb_evlist leaks in top and record
Fix a memory leak in cmd_top() where top.sb_evlist was not freed if
evlist__add_bpf_sb_event() fails. Note that evlist__start_sb_thread() and
evlist__stop_sb_thread() take ownership of the evlist and free it, so
we must only free it if we fail before starting the thread. Also set
top.sb_evlist to NULL to prevent use-after-free bugs.

Apply the same fix to builtin-record.c to avoid leaking rec->sb_evlist
and calling pthread_join on uninitialized threads in the error path.

Assisted-by: Antigravity:gemini-3.1-pro
Fixes: b38d85ef49 ("perf bpf: Decouple creating the evlist from adding the SB event")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 21:58:10 -07:00
Ian Rogers
340641a4b5 perf stat: Fix evsel_list leak in cmd_stat
Fix a memory leak in cmd_stat() where evsel_list is leaked if an error
occurs while opening the output file.

Assisted-by: Antigravity:gemini-3.1-pro
Fixes: 361c99a661 ("perf evsel: Introduce perf_evlist")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 21:58:10 -07:00
Ian Rogers
d4171c7740 perf script: Fix metric_evlist leak in script_find_metrics
Fix a memory leak in script_find_metrics() where metric_evlist is leaked
when returning early on error paths.

Assisted-by: Antigravity:gemini-3.1-pro
Fixes: 3622990efa ("perf script: Change metric format to use json metrics")
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-09 21:58:10 -07:00
Aaron Tomlin
bf10e6ee2a perf sched latency: Add histogram and time interval options
While 'perf sched latency' reports task runtime and delay statistics
(average and maximum delay), it does not provide a visual representation
of how task wait times are distributed across latency ranges between
snapshots (start and finish of the analysis window).

The --histogram option collects CPU wait latencies (time between when
a task becomes runnable and when it gets scheduled onto a CPU) into 22
latency buckets, displaying an ASCII bar chart distribution.

The --hist-mode option configures the bucketing scheme:
  - log (default). Logarithmic latency buckets ranging from
    sub-microsecond (< 1 us) up to >= 1.05 seconds

  - linear. Equal-width linear latency buckets
    (i.e., 100 us steps up to >= 2.1 ms)

The --time option allows filtering trace event processing to a
specific time interval [start,stop].

Example histogram output excerpt:

    ❯ sudo perf sched latency --histogram --CPU 0

     CPU Wait Latency Distribution Histogram (between snapshots) (total samples: 36114)
     -------------------------------------------------------------------
      Latency Range    |      Count |    Pct | Histogram Graph
     -------------------------------------------------------------------
      < 1 us           |         17 |   0.0% | #
      2 - 4 us         |        673 |   1.9% | #
      4 - 8 us         |       6237 |  17.3% | ######
      8 - 16 us        |       3224 |   8.9% | ###
      16 - 32 us       |       1388 |   3.8% | #
      32 - 64 us       |        709 |   2.0% | #
      64 - 128 us      |        690 |   1.9% | #
      128 - 256 us     |        789 |   2.2% | #
      256 - 512 us     |        541 |   1.5% | #
      512 - 1024 us    |       2256 |   6.2% | ##
      1 - 2 ms         |       3577 |   9.9% | ###
      2 - 4 ms         |      13259 |  36.7% | ##############
      4 - 8 ms         |       2523 |   7.0% | ##
      8 - 16 ms        |        222 |   0.6% | #
      16 - 32 ms       |         10 |   0.0% | #
      >= 1.05 s        |          3 |   0.0% | #
     -------------------------------------------------------------------

Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-07 10:56:23 -07:00
Aaron Tomlin
19ea850c02 perf sched latency: Auto-scale latency and runtime display units
Currently, 'perf sched latency' displays task runtime and delay values
exclusively in milliseconds (ms). This can be hard to read when
latencies are very small (in the microsecond or nanosecond range) or
unusually large (seconds).

Introduce auto-scaling for latency and runtime display columns. Values
are dynamically scaled and output with the most appropriate unit:
nanoseconds (ns), microseconds (us), milliseconds (ms), or seconds (s).

Additionally, rename column headers from "Runtime ms", "Avg delay ms",
and "Max delay ms" to "Runtime", "Avg delay", and "Max delay"
respectively, adjust spacing to maintain column alignment and stripe
redundant prefix strings from each row's format string to produce a
clean, tabular output.

For illustrative purposes, a comparison of the latency table header
before and after this change is shown below:

Before:
 -------------------------------------------------------------------------------------------------------------------------------------------
  Task                  |   Runtime ms  |  Count   | Avg delay ms    | Max delay ms    | Max delay start           | Max delay end          |
 -------------------------------------------------------------------------------------------------------------------------------------------
  kworker/2:2-mm_:154757 |      0.033 ms |        1 | avg:   0.829 ms | max:   0.829 ms | max start: 169486.543205 s | max end: 169486.544034 s

After:
 ------------------------------------------------------------------------------------------------------------------------------------------
  Task                    |    Runtime     |  Count   |    Avg delay    |    Max delay    |      Max delay start  |     Max delay end     |
 ------------------------------------------------------------------------------------------------------------------------------------------
  kworker/2:2-mm_:154757  |      32.873 us |        1 |      829.347 us |      829.347 us |       169486.543205 s |       169486.544034 s |

Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-07 10:56:23 -07:00
Aaron Tomlin
44f8dd1ee1 perf sched: Handle missing trace samples in pipe mode
For pipe mode streams, event attributes are received dynamically during
event processing, meaning session->evlist is not populated prior to
perf_session__process_events(). To handle pipe input correctly:
  - Register the missing .attr, .tracing_data, .build_id, and .feature
    callbacks in cmd_sched()

  - Promote the handlers array to file-scope (latency_handlers[]) and
    dynamically assign matching tracepoint handlers
    (or process_sched_ignore) inside
    perf_sched__process_tracepoint_sample() when evsel->handler is NULL;
    replace process_sched_wakeup_ignore() with process_sched_ignore()

  - Perform the trace check post-processing when handling pipe data

Fixes: 27295592c2 ("perf session: Share the common trace sample_check routine as perf_session__has_traces")
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-07 10:56:22 -07:00
Aaron Tomlin
4a81d59a9d perf sched: Suppress latency table output when trace samples are missing
When 'perf sched latency' is executed on a perf.data file that lacks
tracepoint samples (i.e., a file recorded without the -R flag or
containing only non-tracepoint events), perf_session__has_traces()
correctly outputs an error message. However, perf_sched__read_events()
subsequently falls through and returns 0 (success).

Consequently, caller functions such as perf_sched__lat() assume event
processing succeeded and proceed to render empty latency header tables
and total summary statistics.

Fix this behaviour by ensuring perf_sched__read_events() aborts early and
returns a suitable error code when perf_session__has_traces() evaluates
to false.

Additionally, validate thread__get_runtime() against NULL in
map_switch_event() to prevent potential null-pointer dereferences.

Fixes: 27295592c2 ("perf session: Share the common trace sample_check routine as perf_session__has_traces")
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-07 10:56:22 -07:00
Ian Rogers
006a6f0f6e perf synthetic-events: Fix bounds and union member access in mmap2 build_id synthesis
Modify bounds and union member access in mmap2 build_id synthesis. Bound
max_filename_len against the minimum of filename array capacity and the
outer union stack layout minus sample ID trailers. This prevents both
-E2BIG overruns and _FORTIFY_SOURCE array bounds aborts on strlcpy even
if the enclosing union expands.

Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-07 09:43:36 -07:00
Ian Rogers
b97c535768 perf synthetic-events: Fix bounds, stale state, and misc flags in kernel module synthesis
Clamp long DSO names to mmap/mmap2 filename boundaries accounting for
sample ID headers to prevent buffer overruns in
perf_event__synthesize_modules_maps_cb(). Explicitly clear misc flags and
union padding to prevent stale Build-ID state from leaking between module
synthesis events, and cast event buffer pointers to avoid _FORTIFY_SOURCE
array bounds aborts when zeroing padding trailers.

Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-07 09:43:36 -07:00
Ian Rogers
093f58e60e perf synthetic-events: Fix stack buffer overflow and bounds in cgroup synthesis
Fix a pre-existing stack buffer overflow bug in
perf_event__synthesize_cgroup() where an in-place null padding loop wrote
bytes past the end of the cgrp_root stack array buffer during cgroup tree
traversal. Eliminate in-place path mutation, use PERF_ALIGN for path_len,
clamp raw_path_len to prevent sample ID header trailer overruns, and use
strlcpy with combined zero padding for alignment and sample ID headers.

Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-07 09:43:36 -07:00
Ian Rogers
505a498a37 perf synthetic-events: Fix line synchronization, bounds, and truncation bugs in proc maps reader
Fix critical logic and boundary bugs in read_proc_maps_line() and caller.
Ensure any mid-line hex/dec/char parsing failure invokes io__drain_line()
safely, using a do-while loop to read and discard remaining characters
until a newline or EOF is reached. Clamp pathname extraction size to
account for trailing sample ID headers, use standard '//toolong' fallback
literal for over-length pathnames, emit timeout flags for truncated entries
securely via goto out;, and cast event buffer pointers to avoid
_FORTIFY_SOURCE array bounds aborts across synthesis handlers.

Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-07 09:43:36 -07:00
Ian Rogers
e46a9b8150 perf find-map: Remove PATH_MAX 128-byte stack array restriction
Use getline() to dynamically allocate the required line buffer for maps
parsing, guaranteeing bounds safety and avoiding compiler warnings
by evaluating the return value in the loop condition directly.

Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-07 09:43:36 -07:00
Tanushree Shah
43a163494f perf trace-event: Fix infinite loop in skip()
skip() ignores do_read()'s return value and unconditionally
subtracts the requested chunk size from 'size' on every iteration.
This was previously bounded by size being 'int': a maliciously
large 64-bit value was truncated on assignment, capping the loop
early by accident.

Now that size is size_t, a crafted file supplying a very large
size causes skip() to keep requesting BUFSIZ-sized reads and
subtracting BUFSIZ from size regardless of whether do_read()
actually succeeds, spinning indefinitely even after EOF or a read
error.

Check do_read()'s return value and break out of the loop on
failure or EOF, so forward progress is only counted when a read
actually succeeds.

Signed-off-by: Tanushree Shah <tshah@linux.ibm.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-07 09:43:36 -07:00
Tanushree Shah
c291f143cc perf trace-event: Fix heap overflows in read_ftrace_printk()/read_saved_cmdline()
Both functions read an attacker-controlled size directly from the
input file and pass size + 1 to malloc() before reading size bytes
into the result:

read_ftrace_printk(): size is an unsigned int from read4(). When
size == UINT_MAX, size + 1 overflows to 0, so malloc(0) returns a
minimal allocation while size itself remains UINT_MAX.

read_saved_cmdline(): size is an unsigned long long from read8().
When size == ULLONG_MAX, size + 1 overflows to 0 the same way.

In both cases, do_read(buf, size) then attempts to read the full,
unwrapped size into the tiny allocated buffer, a heap buffer
overflow.

This was previously masked by do_read()'s size parameter being
'int': passing these values truncated them, which the read()
syscall's own boundary checks rejected before any data was read.
Fixing that truncation (widening do_read() to size_t) is correct
on its own, but it removes this accidental protection and exposes
the pre-existing missing bounds check in both functions.

Reject the one value that causes the overflow before it's used, in
each function.

Signed-off-by: Tanushree Shah <tshah@linux.ibm.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-07 09:43:36 -07:00
Tanushree Shah
6c07d49ef3 perf trace-event: Avoid double free and leak in trace_event__cleanup()/trace_event__init()
trace_event__cleanup() frees t->pevent but never clears the
pointer. It can be called twice on the same trace_event: once
from trace_report()'s error path, and again from
perf_session__delete() during session teardown, resulting in a
double free / use-after-free.

Separately, trace_event__init() overwrites t->pevent/t->plugin_list
without releasing any existing handle, leaking memory if it's
called more than once on the same struct. eg. via a perf.data
file with multiple PERF_RECORD_HEADER_TRACING_DATA headers.

Guard against re-entry by returning early if t->pevent is already
NULL, and clear it after cleanup so a repeat call is a safe no-op.
Call trace_event__cleanup() at the start of trace_event__init(),
so a repeated init releases any existing handle before allocating
a new one.

Signed-off-by: Tanushree Shah <tshah@linux.ibm.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-07 09:43:36 -07:00
Tanushree Shah
c108c1391b perf trace-event: Fix integer truncation in do_read() and skip()
The do_read() and skip() functions use 'int' for size parameters,
truncating 64-bit sizes from callers. This causes two issues:

1. Uninitialized memory dump: do_read() reads fewer bytes than
   allocated, leaving uninitialized heap memory that gets written
   to output files.

2. Out-of-bounds read: Parsing functions process the full 64-bit
   size while only partial data was read into the buffer.

Change do_read(), __do_read(), and skip() to use size_t for size
parameters and ssize_t for return values (where applicable), matching
read()/write() system calls.
Update callers to use ssize_t for storing return values.

Fixes: 4a31e56599 ("perf tools: Get rid of read_or_die() in trace-event-read.c")
Signed-off-by: Tanushree Shah <tshah@linux.ibm.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-07 09:40:15 -07:00
Tanushree Shah
1121a7af18 perf trace-event: Fix buffer overflow in read_string()
read_string() writes into buf[BUFSIZ] one byte at a time without
checking 'size' against the buffer bound before each write. A
string longer than BUFSIZ in the input overflows the stack buffer.

Add a bounds check before each write to prevent overflow. On
overflow the function returns NULL, matching its other error paths.

Fixes: 9215545e99 ("perf: Convert perf tracing data into a tracing_data event")
Signed-off-by: Tanushree Shah <tshah@linux.ibm.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-06 09:13:15 -07:00
Arnaldo Carvalho de Melo
6d421f609b perf c2c: Clean up registered formats on c2c_hists__init() and c2c_hists__reinit() failure
When c2c_hists__init() or c2c_hists__reinit() calls hpp_list__parse()
and it fails partway through, format structures registered via
perf_hpp_list__column_register() and perf_hpp_list__register_sort_field()
are left on the hpp_list.

In c2c_hists__init(), only one of the callers, c2c_he__alloc_hists(),
handled this with perf_hpp__reset_output_field(), while perf_c2c_report()
did not, leaking the partially registered entries.

In c2c_hists__reinit(), neither perf_c2c_report() nor resort_cl_cb()
clean up on failure.

Fix by adding cleanup inside both functions themselves, so all callers
are protected, and remove the now redundant reset in c2c_he__alloc_hists().

Fixes: 78b2754378 ("perf c2c report: Add sample processing")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Assisted-by: Claude:claude-opus-4.6
Assisted-by: Opencode:mimo-v2.5-free
Assisted-by: Opencode:DeepSeek-V4-Flash-free
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-05 21:50:45 -07:00
Arnaldo Carvalho de Melo
f53f5c2437 perf c2c: Fix error masking, OOM, and unchecked caller errors in hpp_list__parse()
hpp_list__parse() has three bugs:

1. The PARSE_LIST macro resets ret = 0 at the start of each invocation,
   so an error from output parsing is silently overwritten when the sort
   parsing block runs.  The function returns success with partially
   initialized state.

2. When the caller passes a non-NULL output_ or sort_ string, but
   strdup() returns NULL due to OOM, NULL is passed to PARSE_LIST which
   treats it as empty input (the "if (!_list) break" branch).  No error
   is returned.

3. When the called _fn function fails and returns something other than
   -ESRCH or -EINVAL (-ENOMEM, for instance) it was not bailing out of
   the strtok loop.

Fix them by checking strdup() return values before proceeding and adding
a cleanup label so that ret from each PARSE_LIST call is checked before
the next runs, preserving the first error.

The early exits now skip perf_hpp__setup_output_field(), which means
c2c_hists__reinit() can return a non-zero value in cases that previously
always succeeded silently.  Both callers discarded its return:
resort_cl_cb() continued into hists__collapse_resort() on a broken list,
and perf_c2c__report() proceeded with uninitialised hists.  Fix the full
chain: check and propagate the error in resort_cl_cb() -- hists__iterate_cb()
already stops iteration and returns the callback error -- and check both
c2c_hists__reinit() and hists__iterate_cb() in perf_c2c__report().

Also turn PARSE_LIST into a function, using a switch to catch other
errors, converting the called functions to return an appropriate errno
instead of -1 on failure.

Also make the two callers that iterate sort_dimension__add() and
output_field_add() handle the newly propagated errors: setup_sort_list()
and setup_output_list() only checked for -EINVAL and -ESRCH, so an
-ENOMEM from a failed allocation was silently overwritten by the next
loop iteration.  Break out of the loop and propagate any other error.

The hpp_list__parse() fixes were developed with AI assistance from
Claude:claude-sonnet-4.6, and the setup_sort_list()/setup_output_list()
caller fixes with AI assistance from Opencode:mimo-v2.5-free and
Opencode:DeepSeek-V4-Flash-free.

Fixes: 2d388bd0c9 ("perf c2c report: Add stdio output support")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Assisted-by: Claude:claude-sonnet-4.6
Assisted-by: Opencode:mimo-v2.5-free
Assisted-by: Opencode:DeepSeek-V4-Flash-free
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-05 21:50:45 -07:00
Arnaldo Carvalho de Melo
fe3ab00d55 perf libbfd: Fix memory leaks and NULL fclose in BPF disassembly
symbol__disassemble_bpf_libbfd() has four resource management bugs:

1. free(prog_linfo) leaks internal arrays.  bpf_prog_linfo contains
   raw_linfo, raw_jited_linfo, nr_jited_linfo_per_func, and
   jited_linfo_func_idx pointers that are only freed by the proper
   destructor bpf_prog_linfo__free().

2. open_memstream(&buf, &buf_size) allocates a dynamic buffer that the
   caller must free after fclose().  The function calls fclose(s) but
   never free(buf), leaking the stream buffer on every call.

3. args->line = strdup(srcline) is immediately consumed by
   disasm_line__new(args) which internally calls strdup(args->line)
   again via annotation_line__init().  The first strdup result is then
   overwritten by args->line = buf + prev_buf_size without being freed.

4. If open_memstream() fails, the error path jumps to 'out:' which
   calls fclose(s) with s == NULL — undefined behavior.

Fix by using bpf_prog_linfo__free(), initializing buf to NULL, adding
free(buf) after fclose(s), guarding fclose() against NULL, and removing
the redundant strdup since annotation_line__init() makes its own copy.

Fixes: 6987561c9e ("perf annotate: Enable annotation of BPF programs")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Song Liu <songliubraving@fb.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-05 11:20:03 -07:00
Arnaldo Carvalho de Melo
38ba525335 perf bpf: Add PROG_TAGS to required arrays in __bpf_event__print_bpf_prog_info()
synthesize_bpf_prog_name() unconditionally dereferences prog_tags[sub_id]
(line: u8 (*prog_tags)[BPF_TAG_SIZE] = (void *)(uintptr_t)(info->prog_tags))
but __bpf_event__print_bpf_prog_info() only requires JITED_KSYMS and
JITED_FUNC_LENS in its required_arrays bitmask.

If a crafted perf.data has the PROG_TAGS bit cleared (or the array was
invalidated by bpil_offs_to_addr() bounds checking), info->prog_tags
contains either zero or a raw file offset.  Dereferencing it causes a
NULL pointer dereference or an arbitrary memory read.

Add PERF_BPIL_PROG_TAGS to required_arrays so the function returns early
when prog_tags was not present or failed validation.

Fixes: f8dfeae009 ("perf bpf: Show more BPF program info in print_bpf_prog_info()")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Song Liu <songliubraving@fb.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-05 11:20:02 -07:00
Arnaldo Carvalho de Melo
60f2f5b765 perf header: Use write lock when translating BPF prog info pointers
write_bpf_prog_info() holds a read lock while temporarily mutating
info_linear via bpil_addr_to_offs()/bpil_offs_to_addr().  Between these
two calls, the pointers in info_linear contain file offsets instead of
heap addresses.  Concurrent readers holding the same read lock see the
file offsets and dereference them as pointers.

Use down_write()/up_write() instead of down_read()/up_read() to exclude
concurrent readers during the addr-to-offset-to-addr translation window.

Fixes: 63ac7968a1fb ("perf bpf: Save bpf_prog_info information as headers to perf.data")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Song Liu <songliubraving@fb.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-05 11:20:02 -07:00
Arnaldo Carvalho de Melo
01765b456f perf libbfd: Validate BPF prog info arrays before pointer cast
symbol__disassemble_bpf_libbfd() casts info_linear->info.jited_prog_insns
and info_linear->info.jited_ksyms to pointers without checking whether
bpil_offs_to_addr() actually converted the file offsets.  A crafted
perf.data with PERF_BPIL_* bits unset but non-zero counts causes raw
file offsets to be dereferenced as pointers.

Add bitmask checks for PERF_BPIL_JITED_INSNS and PERF_BPIL_JITED_KSYMS
before the casts, matching the validation added to bpf-event.c call
sites.

Fixes: 6987561c9e ("perf annotate: Enable annotation of BPF programs")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Song Liu <songliubraving@fb.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-05 11:20:02 -07:00