Commit Graph

10564 Commits

Author SHA1 Message Date
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
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
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
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
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
Arnaldo Carvalho de Melo
d67241d43b perf arm-spe: Reject zero nr_cpu in metadata to prevent division by zero
arm_spe__alloc_metadata() reads nr_cpu from the auxtrace_info priv
array without validation.  When a crafted perf.data provides nr_cpu=0,
the per_cpu_sz calculation divides by zero:

  per_cpu_sz = (metadata_size - (hdr_sz * sizeof(u64))) / (*nr_cpu);

Reject nr_cpu <= 0 early, before the division.  The caller already
treats NULL return with metadata_ver != 1 as a parse failure.

Fixes: 7842a4b6ff ("perf arm-spe: Support metadata version 2")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-03 12:43:10 -07:00
Arnaldo Carvalho de Melo
b9fb822595 perf intel-bts: Fix off-by-one in auxtrace_info minimum size check
Same pattern as the Intel PT fix: min_sz is set to
sizeof(u64) * INTEL_BTS_SNAPSHOT_MODE, but the code accesses
auxtrace_info->priv[INTEL_BTS_SNAPSHOT_MODE], which requires at least
INTEL_BTS_SNAPSHOT_MODE + 1 elements.

Use (INTEL_BTS_SNAPSHOT_MODE + 1) to ensure the highest accessed index
is within bounds.

Fixes: d0170af700 ("perf tools: Add Intel BTS support")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-03 12:43:05 -07:00
Arnaldo Carvalho de Melo
c4362d5e1a perf intel-pt: Fix off-by-one in auxtrace_info minimum size check
min_sz is set to sizeof(u64) * INTEL_PT_PER_CPU_MMAPS, but the code
accesses auxtrace_info->priv[INTEL_PT_PER_CPU_MMAPS], which requires
at least INTEL_PT_PER_CPU_MMAPS + 1 elements.  A file with exactly
min_sz bytes of priv data passes the size check but the access reads
one u64 past the validated region.

Use (INTEL_PT_PER_CPU_MMAPS + 1) to ensure the highest accessed index
is within bounds.

Fixes: 90e457f7be ("perf tools: Add Intel PT support")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-03 12:43:01 -07:00
Arnaldo Carvalho de Melo
96fcc9ea5f perf auxtrace: Fix queue grow overflow and old array leak
auxtrace_queues__grow() has two bugs:

1. When idx is UINT_MAX, the caller passes new_nr_queues = idx + 1 = 0.
   The function skips growing (since any nr_queues >= 0), returns
   success, and the caller accesses queue_array[UINT_MAX] — an OOB
   heap write.  Fix by rejecting new_nr_queues == 0 up front.

2. The function allocates a new queue_array via calloc and copies
   elements from the old array, but never frees the old array.  Fix
   by saving the old pointer and freeing it after the copy.

Fixes: e502789302 ("perf auxtrace: Add helpers for queuing AUX area tracing data")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-03 12:42:53 -07:00
Arnaldo Carvalho de Melo
ab9c84d1cd perf thread-stack: Fix heap buffer overflow on branch stack wrap copy
thread_stack__br_sample() copies the wrap-around portion of the branch
stack ring buffer with:

  nr = min(ts->br_stack_pos, sz);
  memcpy(be, &src->entries[0], bsz * ts->br_stack_pos);

'nr' is correctly bounded to min(br_stack_pos, sz) but the memcpy uses
the unbounded ts->br_stack_pos directly.  When br_stack_pos exceeds
the remaining destination space 'sz', this writes past the destination
buffer.

Use 'nr' (the bounded value) in the memcpy size, matching the pattern
of the first memcpy in the same function.

Fixes: 86d67180b9 ("perf thread-stack: Add branch stack support")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-03 12:42:49 -07:00
Namhyung Kim
dbd2505061 perf build: Fix a build error on 32-bit x86
The commit d7507a94a0 ("KVM: SVM: Treat exit_code as an unsigned
64-bit value through all of KVM") added "ull" suffix to SVM exit codes
and it makes the 32-bit build fail like below.

  In file included from util/kvm-stat-arch/kvm-stat-x86.c:4:
  util/kvm-stat-arch/../../../arch/x86/include/uapi/asm/svm.h:137:32:
             error: conversion from 'long long unsigned int' to 'long unsigned int' changes
                    value from '18446744073709551615' to '4294967295' [-Werror=overflow]
    137 | #define SVM_EXIT_ERR           -1ull
        |                                ^
  util/kvm-stat-arch/../kvm-stat.h:131:17: note: in definition of macro 'define_exit_reasons_table'
    131 |                 symbols, { -1, NULL }                   \
        |                 ^~~~~~~
  util/kvm-stat-arch/../../../arch/x86/include/uapi/asm/svm.h:249:11: note: in expansion of macro 'SVM_EXIT_ERR'
    249 |         { SVM_EXIT_ERR,         "invalid_guest_state" }
        |           ^~~~~~~~~~~~
  util/kvm-stat-arch/kvm-stat-x86.c:12:45: note: in expansion of macro 'SVM_EXIT_REASONS'
     12 | define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS);
        |                                             ^~~~~~~~~~~~~~~~

As the exit_code was unsigned long, the compiler complained about the
truncation.  Let's convert it to u64 to suppress the error.

Fixes: fac520e43a ("tools headers: Sync KVM headers with the kernel sources")
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-02 09:45:18 -07:00
Zhanpeng Zhang
3a13ed3111 perf symbols: Skip dynamic symbols with invalid section indexes
RISC-V post-link processing can remove relocation sections from the final
vmlinux while some .dynsym entries retain stale section indexes. perf
aborts the whole ELF symbol load when elf_getscn() rejects one of them,
discarding otherwise valid .symtab symbols.

Skip only dynamic symbols whose normal section index is outside the final
section table. Keep the existing error path for .symtab, reserved indexes,
and other libelf failures.

On an affected system, the vmlinux symtab matches kallsyms test changes
from Skip to Ok. [unknown] rows in the same perf.data change from 41 to 0.

Signed-off-by: Zhanpeng Zhang <zhangzhanpeng.jasper@bytedance.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-08-02 09:44:58 -07:00
Arnaldo Carvalho de Melo
d04ef71492 perf machine: Check snprintf truncation for guest kallsyms path
machines__create_guest_kernel_maps() builds the guest kallsyms path
with snprintf() without checking the return value.  A truncated path
could pass the access() check if a prefix directory happens to contain
a file named "kallsyms", leading to the wrong file being used for
symbol resolution.

Check for truncation and skip the directory.

Fixes: a1645ce12a ("perf: 'perf kvm' tool for monitoring guest performance from host")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Zhang, Yanmin <yanmin_zhang@linux.intel.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-07-31 16:42:28 -07:00
Arnaldo Carvalho de Melo
f53bf58dcd perf machine: Free scandir entries in guest kernel map creation
machines__create_guest_kernel_maps() calls scandir() which allocates
both the namelist array and each individual dirent entry.  The code
frees the namelist array but not the individual entries, leaking memory
proportional to the number of directories under guestmount.

Free each namelist[i] after it is no longer needed.

Fixes: a1645ce12a ("perf: 'perf kvm' tool for monitoring guest performance from host")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Zhang, Yanmin <yanmin_zhang@linux.intel.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-07-31 16:42:17 -07:00
Arnaldo Carvalho de Melo
29ec46e43f perf machine: Reset errno before strtol in guest kernel map creation
machines__create_guest_kernel_maps() checks errno == ERANGE after
strtol() to detect overflow, but does not clear errno first.  A stale
ERANGE from an earlier library call (e.g. scandir internals) causes
valid numeric directory names to be incorrectly skipped.

Set errno = 0 before strtol() so only the current conversion can
trigger the ERANGE check.

Fixes: a1645ce12a ("perf: 'perf kvm' tool for monitoring guest performance from host")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Zhang, Yanmin <yanmin_zhang@linux.intel.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-07-31 16:42:07 -07:00
Arnaldo Carvalho de Melo
b687e1a418 perf machine: Don't abort guest map creation on first inaccessible dir
machines__create_guest_kernel_maps() jumps to the failure label when one
guest directory's kallsyms file fails access(), skipping all remaining
valid guest directories.  An inaccessible directory is not fatal — other
guests may still be reachable.

Replace 'goto failure' with 'continue' so the loop processes all
directories, and remove the now-unreferenced failure label.

Fixes: a1645ce12a ("perf: 'perf kvm' tool for monitoring guest performance from host")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Zhang, Yanmin <yanmin_zhang@linux.intel.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-07-31 16:41:56 -07:00
Arnaldo Carvalho de Melo
cc6abe0012 perf machine: Check snprintf truncation in machines__findnew()
The guestmount path is built with snprintf() into a PATH_MAX buffer
without checking the return value.  If symbol_conf.guestmount is long
enough to cause truncation, the truncated path could match a different
directory, causing the wrong guest to be associated with the pid.

Check for truncation and bail out early.

Fixes: a1645ce12a ("perf: 'perf kvm' tool for monitoring guest performance from host")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Zhang, Yanmin <yanmin_zhang@linux.intel.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-07-31 16:41:41 -07:00
Arnaldo Carvalho de Melo
e27b96d0a3 perf machine: Guard against NULL strlist in machines__findnew()
The static 'seen' strlist caches guestmount paths that have already
been reported as inaccessible, to avoid repeating the error message.
If strlist__new() fails (OOM), 'seen' stays NULL and the next call
dereferences it via strlist__has_entry() and strlist__add().

Guard both calls so that on allocation failure the error message is
still printed (just not deduplicated) instead of crashing.

Fixes: c80c3c2690 ("perf kvm: Limit repetitive guestmount message to once per directory")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: David Ahern <dsahern@gmail.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-07-31 16:41:38 -07:00
Arnaldo Carvalho de Melo
73ac546bd6 perf machine: Fix NULL parent dereference in fork event processing
machine__process_fork_event() calls machine__findnew_thread() for the
parent thread, which can return NULL on allocation failure.  The code
then dereferences parent via thread__pid(parent) without a NULL check
when validating whether the parent PID matches.  The later NULL check
at thread__fork() does not prevent this earlier dereference.

Add a NULL guard before accessing the parent thread.

Fixes: 5cb73340d9 ("perf tools: Make fork event processing more resilient")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.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-07-31 16:41:35 -07:00
Arnaldo Carvalho de Melo
23010160bb perf machine: Fix fd leak on bounds check in maps__set_modules_path_dir()
The bounds check for root_len >= path_size returns -1 directly without
closing the directory fd opened by io_dir__init() a few lines above.

Jump to the out label instead, which calls close(iod.dirfd).

Fixes: e7af194681 ("perf machine: Reuse module path buffer")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Cc: 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-07-31 16:41:21 -07:00
Sizhe Liu
bec06676f4 perf hisi-ptt: Fix spelling and abbreviation errors
Fix spelling and abbreviation errors in the PTT packet decoder:
- HISI_PTT_FIELD_LENTH -> HISI_PTT_FIELD_LENGTH
- hisi_ptt_8dw_kpt_desc -> hisi_ptt_8dw_pkt_desc
- hisi_ptt_4dw_kpt_desc -> hisi_ptt_4dw_pkt_desc

Reviewed-by: James Clark <james.clark@linaro.org>
Signed-off-by: Sizhe Liu <liusizhe5@huawei.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-07-31 15:48:12 -07:00
Sizhe Liu
d5f9d46232 perf hisi-ptt: Strengthen auxtrace event handling and packet type detection
Fix pre-existing robustness issues in the hisi-ptt auxtrace decoder
reported by Sashiko:

1. Endianness in hisi_ptt_check_packet_type(): The first 32-bit word was
read with a host-endian memory cast (*(uint32_t *)buf). On big-endian
hosts analyzing a little-endian trace, the bit[31:11] 8DW magic check
fails and every 8DW packet is misclassified as 4DW. Read the header
with get_unaligned_le32().

2. Heap out-of-bounds read: hisi_ptt_dump() called
hisi_ptt_check_packet_type() which dereferenced 4 bytes of the buffer
without any size check. A malformed or truncated event with
auxtrace.size in {0,1,2,3} may cause a heap OOB read. Pass the buffer
length to hisi_ptt_check_packet_type() and return (defaulting to
4DW) when the buffer is shorter than HISI_PTT_FIELD_LENTH.

3. Integer truncation: event->auxtrace.size is __u64 but was stored in
an int. Traces larger than 2GB became negative (malloc failure), and
huge sizes wrapping to a small positive caused a short readn() that
left unread payload in the pipe and permanently desynchronized the
stream. Use u64 for the size, reject anything larger than SSIZE_MAX
before malloc (same bound used by auxtrace_copy_data()), and compare
readn()'s return value against (ssize_t)size to detect truncation.

Signed-off-by: Sizhe Liu <liusizhe5@huawei.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-07-31 15:48:12 -07:00
Sizhe Liu
2b8a2e5d42 perf hisi-ptt: Fix PTT trace TLP header parsing
TLP Headers traced by HiSilicon PCIe tune and trace device (PTT) in
4DW format are shown in the document as below:
bits [31:30] [ 29:25 ][24][23][22][21][    20:11   ][    10:0    ]
     |-----|---------|---|---|---|---|-------------|-------------|
DW0  [ Fmt ][  Type  ][T9][T8][TH][SO][   Length   ][    Time    ]
DW1  [                     Header DW1                            ]
DW2  [                     Header DW2                            ]
DW3  [                     Header DW3                            ]

Problem:
The DW0 bit field layout of the hisi_ptt_4dw union does not match the
actual bit ordering in little-endian memory, causing incorrect field
decoding.

Test on Kunpeng 930 SOC, generating data flow with `iperf` commands:
- server side:
    iperf -s
- client side:
    iperf -c $ip_addr -t 30

Trace the TLP headers with hisi_ptt on server side at the same time:
  perf record -e hisi_ptt12_0/type=4,filter=0x05101,direction=2,format=0/ \
  --max-size 50M -o perf.data &
The trace aims to capture completion TLPs, learn more in the document:
  https://docs.kernel.org/trace/hisi-ptt.html

Decode perf.data with hisi_ptt decoder:
  perf report -D

The hisi_ptt decoder produces the following result:
[...perf headers and other information]
. ... HISI PTT data: size 8388608 bytes
.  00000000: 68 87 20 94                                 Format 3 Type 1a T9 0 T8 1 TH 1 SO 1 Length 10 Time 4a1
.  00000004: 40 00 00 00                                 Header DW1
.  00000008: 40 00 01 51                                 Header DW2
.  0000000c: 00 00 00 00                                 Header DW3
[...other hisi_ptt TLP headers]

According to PCIe r5.0 sec 2.2.1, the Fmt & Type of Cpl/CplD is supposed
to be 8b'00001010' / 8b'01001010'
However, the Format & Type decoder analyzing result is 8b'01111010'.
It does not match field encodings of any TLP.

Correct decoder result should be:
[...perf headers and other information]
. ... HISI PTT data: size 8388608 bytes
.  00000000: 94 20 87 68                                 Format 2 Type a T9 0 T8 0 TH 0 SO 1 Length 10 Time 768
.  00000004: 00 00 00 40                                 Header DW1
.  00000008: 51 01 00 40                                 Header DW2
.  0000000c: 00 00 00 00                                 Header DW3
[...other hisi_ptt TLP headers]

To solve the problem:
1. Drop the union and C bitfield struct, store the raw DW value in
a plain uint32_t, and extract the fields with FIELD_GET() against
GENMASK/BIT masks declared in the header so they can be reused by
other translation units. The masks are portable across endianness and
compilers.

2. Print all DW hex values in big-endian byte order for readability,
matching the bit field layout shown in the 4DW format diagram.

3. Read the DW value with get_unaligned_le32() instead of an unaligned
pointer cast, avoiding both strict-aliasing violations and
alignment hazards on hosts that do not support unaligned access.

Cc: stable@vger.kernel.org
Fixes: 5e91e57e68 ("perf auxtrace arm64: Add support for parsing HiSilicon PCIe Trace packet")
Reviewed-by: James Clark <james.clark@linaro.org>
Signed-off-by: Sizhe Liu <liusizhe5@huawei.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-07-31 15:48:12 -07:00
Michael Liang
022bcb6ba2 perf libdw: Fix outer-frame name resolution and spurious "(inlined)" tag
cu_walk_functions_at() calls libdw_a2l_cb() with the containing
DW_TAG_subprogram DIE first, then each DW_TAG_inlined_subroutine
nested inside.  The callback treated both the same way, causing two
bugs:

  1) die_name() returns the unqualified DW_AT_name, so every C++
     frame lost its namespace/class prefix (ns::Class::method
     collapsed to method).

  2) new_inline_sym() re-uses base_sym only when funcname matches
     base_sym->name exactly; otherwise it fabricates a fake symbol
     tagged "(inlined)".  Any mismatch between the DWARF name and
     the ELF symbol name mis-tags an outer, non-inline frame as
     inlined.  This hits C++ (die_name()'s unqualified output never
     matches the demangled ELF symbol) and it also hits C functions
     that GCC IPA-cloned (foo vs foo.isra.0 / .constprop / .part /
     .cold), since DW_AT_linkage_name doesn't reflect those renames.

Fix both:

  * Prefer die_get_linkage_name() (mangled, fully qualified),
    falling back to die_name() when absent (C, extern "C").
    new_inline_sym() already demangles via dso__demangle_sym().

  * For DW_TAG_subprogram DIEs, use base_sym directly -- the DIE
    tag already tells us it is the outer function, sidestepping
    the name comparison entirely for both C++ qualification and
    GCC IPA-clone renames.

Fixes: 88c51002d0 ("perf addr2line: Add a libdw implementation")
Signed-off-by: Michael Liang <mliang@purestorage.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-07-31 15:47:28 -07:00
Alessio Podda
f2effca1ef perf unwind-libdw: Fix unwinding of multi-threaded processes
The libdw callback API has two levels: dwfl_getthread_frames() first finds
the requested thread using the next_thread() or get_thread() callback and
then walks its stack.

Since perf only has a snapshot of the stack of a single thread, it
provides a stubbed-out API that always returns the pid the Dwfl was
attached with (i.e. whatever was passed to dwfl_attach_state()), rather
than the actual sampled thread's TID.

Commit 6b2658b3f3 ("perf unwind-libdw: Don't discard loaded ELF/DWARF
after every unwind") changed libdw unwinding from recreating the Dwfl
object for each sample to caching it in struct maps, which is shared by
every thread in the process. It left next_thread() unchanged.

Since the pid passed to dwfl_attach_state() is only set at creation, only
the thread of the first sample is ever found. As a result,
dwfl_getthread_frames() fails with ESRCH when asked to unwind a sample
from another thread.

Make next_thread() return the current sample's TID, provide get_thread()
so libdw can find it directly, and pass the process PID expected by
dwfl_attach_state(). This allows libdw to unwind samples from every thread
in a multi-threaded process.

Add a shell regression test that records a four-thread workload and
verifies that libdw recovers the worker callchain for every worker TID.

Fixes: 6b2658b3f3 ("perf unwind-libdw: Don't discard loaded ELF/DWARF after every unwind")
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Alessio Podda <aleph.pi.gh@gmail.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-07-31 15:31:20 -07:00
Ian Rogers
b84e081e07 perf annotate: Be robust to annotating without a thread
If a thread isn't given to map_symbol__get_arch(), try harder to determine
the arch for disassembly. Do this by utilizing fallback paths such as
reading the e_machine from a map's DSO ELF header for user-space libraries.
Additionally, rely on map__kmaps() and maps__machine() to reliably extract
the recorded machine environment and e_machine for kernel and kallsyms maps,
perfectly preventing silent, incorrect host fallbacks to uname() during
cross-platform Capstone annotation sessions.

At the same time, ensure all remaining uses of a map_symbol's thread pointer
do not assume it is non-NULL to eliminate UI segmentation faults, and remove
the fragile, redundant thread__get_arch() function to streamline the
annotate and disassembly subsystem architecture.

Fixes: 0e26ba5a87 ("perf disasm: Refactor arch__find and initialization of arch structs")
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-07-27 17:30:46 -07:00
Ian Rogers
ad7620a2b9 perf ui hists: Fix stack use-after-return in symbol_filter_str
In evsel__hists_browse(), the local stack array 'buf' is assigned
directly to the persistent 'hists->symbol_filter_str' pointer. When the
browser returns or is exited, this dangling pointer remains active in
the 'hists' struct and is read asynchronously by the perf top background
timer, triggering a stack use-after-return.

Fix it by properly duplicating the input string using strdup(), safely
invoking zfree() to prevent memory leaks when overwriting, and cleanly
resetting and freeing the symbol filter string upon exiting the browser.

Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-07-27 17:13:08 -07:00
Aaron Tomlin
89493fe58c perf trace: Correct default cpumask formatting to hexadecimal
Currently, dynamic non-array fields such as 'cpumask_t' are mishandled in
'perf trace', causing the raw length and offset descriptors to be interpreted
and displayed as a literal integer (e.g., "cpumask: 524320" instead of the
actual mask data).

Correct the parsing of dynamic fields that do not have the
TEP_FIELD_IS_ARRAY flag set by introducing helper functions
format_field__get_raw_data() and format_field__get_cpumask().
Using these helpers, resolve the pointer to the raw bits within the
payload and format the cpumask as a zero-padded hexadecimal string by default.

Fixes: c5e006cdbd ("perf trace: Support tracepoint dynamic char arrays")
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-07-23 22:59:42 -07:00
Ian Rogers
1fa8d81be1 perf python: Clean up and restructure setup.py
Clean up and restructure the python setup script to resolve pylint
warnings, improve code quality, and increase robustness and
readability, targeting Python 3.9+ (the Linux kernel build minimum
Python version).

Changes:
- Restructure the script to use a `main()` function as the entry point,
  leaving only imports, classes, and pure functions at module level.
- Eliminate all global/module-level variables, making them local to
  `main()` or the respective classes/functions.
- Make `clang_has_option` a pure function by passing all necessary
  parameters explicitly.
- Extract clang compiler flag filtering into a new
  `filter_clang_options` helper function. This function uses a loop
  over a tuple of options, replacing ~30 lines of repetitive blocks
  and reducing branch/statement complexity in the main flow.
- Cleanly define attributes in `__init__` for `BuildExt` and
  `InstallLib` and read environment variables dynamically within the
  methods (including `srctree` in `InstallLib.run`), removing their
  dependency on global variables.
- Replace legacy Popen with subprocess.run for safer process handling.
- Use quote-aware flag filtering (`shlex.split`, filter, `shlex.join`)
  on sysconfig CFLAGS and OPT instead of regex `re.sub` substitutions.
  This avoids boundary bugs and safely handles quoted arguments and
  options with values.
- Rely on setuptools to handle user CFLAGS from the environment
  directly rather than manually prepending them to extra_compile_args.
- Safely parse `CC` env var using `shlex.split` to handle quotes and
  pass compiler arguments as `list[str]` lists to helper functions,
  avoiding redundant string formatting and parsing.
- Remove unused `import re`.
- Rename setuptools command subclasses to PascalCase (BuildExt,
  InstallLib).
- Add type annotations to functions and methods.
- Add missing docstrings for module, functions, and classes.
- Split long lines to adhere to standard limits.

Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-07-23 22:49:39 -07:00
Ian Rogers
87ec3437f3 perf cap: Remove used_root parameter and simplify capability checks
Refactor perf_cap__capable() to completely remove the used_root out-parameter
as requested by the maintainer. Relying on an explicit used_root boolean
poisoned sequential capability checks (e.g. failing CAP_SYS_ADMIN checks
poisoning the flag for subsequent CAP_PERFMON evaluations for unprivileged
users) and created redundant complexity across check_ftrace_capable(),
symbol__read_kptr_restrict(), and perf_event_paranoid_check().

Streamline the capability API to perform a pure true/false boolean
evaluation. The function checks the Effective set using SYS_capget; if
the syscall is missing or fails on legacy kernels, it cleanly falls back
to checking EUID == 0. This perfectly preserves modern capability-aware host
sessions, guarantees transparent fallback for older kernels, and correctly
rejects privileged operations for containerized root processes that have
explicitly dropped their capability bounding and permitted sets.

Fixes: e25ebda78e ("perf cap: Tidy up and improve capability testing")
Suggested-by: Namhyung Kim <namhyung@kernel.org>
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-07-23 22:46:33 -07:00
Leo Yan
ec99be8a31 perf cs-etm: Avoid truncating AUX buffer sizes to int
cs_etm__get_trace() returns an int, but it used to return etmq->buf_len
on success. That value comes from auxtrace_buffer::size, which is a
size_t. For a large AUX trace block, returning the byte count through an
int can overflow and make a valid buffer look like a negative error.

The callers do not need the actual byte count from cs_etm__get_trace().
The buffer length is already stored in the etmq->buf_len. The callers
only need to distinguish three states:

  < 0: error
  = 0: no more AUX buffers
  > 0: data is available

Make cs_etm__get_trace() return 0 for all non-error cases and use
etmq->buf_len to indicate whether a new buffer was found. Then make
cs_etm__get_data_block() return 1 whenever data is available, instead of
returning the buffer length.

Also refactor cs_etm__get_data_block() to make its return value
semantics clearer.

Reported-by: Suyash Mahar <smahar@meta.com>
Fixes: 8224531cf5 ("perf cs-etm: Modularize auxtrace_buffer fetch function")
Signed-off-by: Leo Yan <leo.yan@arm.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-07-22 22:42:25 -07:00
Aaron Tomlin
64724095a3 perf stat: Add --hide-zero-events option to suppress zero-count events
When monitoring a large number of events (e.g., with wildcards such as
--event 'syscalls:sys_enter_*'), many matched events will return a count
of zero. This clutters the output, making it difficult to spot the
active events.

Add a new option --hide-zero-events to suppress printing events that
have a count of zero.

To prevent formatting and diagnostic issues, the zero-skipping logic
implements the following rules:

    1. In metric-only mode (i.e., --metric-only), columns must remain
       aligned in the output grid. We evaluate config->metric_only first
       to avoid skipping zero-valued columns, preventing values from
       shifting left and aligning under incorrect headers

    2. For explicitly requested events, we ensure they are not silently
       hidden if they are unsupported. We only hide a zero-count event
       if counter->supported is true, ensuring that unsupported explicit
       events still report "<not supported>"

Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
2026-07-19 21:49:30 -07:00