summaryrefslogtreecommitdiff
path: root/tools/perf/util
AgeCommit message (Collapse)Author
2026-06-22perf bpf: Fix up build failure due to change of btf_vlen() return typeMark Brown
Fix: util/btf.c: In function '__btf_type__find_member_by_name': util/btf.c:19:43: error: comparison of integer expressions of different signedness: 'int' and '__u32' {aka 'unsigned int'} [-Werror=sign-compare] 19 | for (i = 0, m = btf_members(t); i < btf_vlen(t); i++, m++) { | ^ builtin-trace.c: In function 'syscall_arg__strtoul_btf_enum': builtin-trace.c:967:27: error: comparison of integer expressions of different signedness: 'int' and '__u32' {aka 'unsigned int'} [-Werror=sign-compare] 967 | for (int i = 0; i < btf_vlen(bt); ++i, ++be) { | ^ by making the variable the same type as the function. Committer note: Add an extra hunk from Alan Maguire, fixing btf_enum_scnprintf(). Reviewed-by: Alan Maguire <alan.maguire@oracle.com> Signed-off-by: Mark Brown <broonie@kernel.org> Cc: Alexei Starovoitov <ast@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf dso: Set standard errno on decompression failureArnaldo Carvalho de Melo
dso__get_filename() sets errno to a negative custom DSO_LOAD_ERRNO value when kernel module decompression fails: errno = *dso__load_errno(dso); /* e.g. -9996 */ The caller __open_dso() then computes fd = -errno, producing a large positive value (9996) that looks like a valid file descriptor. This can cause close_data_fd() to close an unrelated fd used by another subsystem. Set errno to EIO instead. The detailed error code is already stored in dso__load_errno(dso) for diagnostic messages. Fixes: 1d6b3c9ba756a513 ("perf tools: Decompress kernel module when reading DSO data") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf bpf: Validate array presence before casting BPF prog info pointersArnaldo Carvalho de Melo
Several functions cast bpf_prog_info fields (jited_ksyms, jited_func_lens, jited_prog_insns) from u64 to pointers and dereference them. These fields are only valid pointers if bpil_offs_to_addr() converted their file offsets to addresses, which only happens when the corresponding PERF_BPIL_* bits are set in info_linear->arrays. A crafted perf.data can leave these bits unset while setting non-zero counts and offset values, causing the functions to dereference raw file offsets as pointers. Add array bitmask validation to all perf.data processing paths: - __bpf_event__print_bpf_prog_info(): check JITED_KSYMS and JITED_FUNC_LENS (changed to take struct perf_bpil *) - machine__process_bpf_event_load(): check JITED_KSYMS - bpf_read(): check JITED_INSNS before memcpy from jited_prog_insns - dso__disassemble_filename(): check JITED_INSNS before returning jited_prog_insns pointer Fixes: f8dfeae009effc0b ("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> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf c2c: Fix hist entry and format list leaks in c2c_he_free()Arnaldo Carvalho de Melo
c2c_he_free() calls hists__delete_entries() which only walks the output-sorted entries tree. During c2c resort, when cacheline entries are merged and the redundant entry is freed, the inner hists have not been output-resorted yet, so hists->entries is empty. The actual inner hist_entry objects live in entries_in_array[] and entries_collapsed, which are never walked, leaking all inner hist_entry objects for every merged cacheline. Additionally, the dynamically allocated format entries on hists->list are never unregistered or freed. Fix both issues by switching to hists__delete_all_entries() which walks all rb_root trees, and calling perf_hpp__reset_output_field() to clean up format entries. Fixes: bf0e0d407ea09ce5 ("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 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf cs-etm: Bounds-check CPU in cs_etm__get_queue()Arnaldo Carvalho de Melo
cs_etm__get_queue() indexes etm->queues.queue_array[cpu] without validating that cpu is within nr_queues. When processing AUX_OUTPUT_HW_ID events, the cpu value comes from untrusted perf.data trace payload and flows through cs_etm__process_trace_id_v0_1() and cs_etm__queue_aux_fragment() without bounds checking, allowing an out-of-bounds read with a crafted file. Add a bounds check in cs_etm__get_queue() and NULL checks in all callers. Also add NULL checks for queue_array[i].priv in the queue iteration loops in cs_etm__map_trace_id_v0() and cs_etm__process_trace_id_v0_1() — after auxtrace_queues__grow() new entries are zero-initialized so .priv can be NULL. Add a get_cpu_data() NULL check in cs_etm__process_trace_id_v0_1(), matching the existing check in cs_etm__process_trace_id_v0(). Fixes: 77c123f53e97ad4b ("perf: cs-etm: Move traceid_list to each queue") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: James Clark <james.clark@arm.com> Cc: Leo Yan <leo.yan@linaro.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf cs-etm: Require full global header in auxtrace_info size checkArnaldo Carvalho de Melo
cs_etm__process_auxtrace_info() checks that header.size covers event_header_size + INFO_HEADER_SIZE (16 bytes total), but then accesses ptr[CS_PMU_TYPE_CPUS] at offset 24 from the start of the event. A crafted 16-byte auxtrace_info event passes the size check but reads out-of-bounds. Include CS_ETM_HEADER_SIZE in the minimum size check so that the global header entries (version, pmu_type_cpus, snapshot) are guaranteed to fit within the event. Fixes: 55c1de9973d66516 ("perf cs-etm: Print auxtrace info even if OpenCSD isn't linked") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: James Clark <james.clark@arm.com> Cc: Leo Yan <leo.yan@linaro.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf cs-etm: Validate num_cpu before metadata allocationArnaldo Carvalho de Melo
cs_etm__process_auxtrace_info_full() reads num_cpu from untrusted perf.data and uses it to allocate the metadata pointer array: metadata = zalloc(sizeof(*metadata) * num_cpu); On 32-bit, sizeof(*metadata) is 4, so num_cpu = 0x40000000 overflows the multiplication to 0, causing zalloc(0) to return a valid zero-sized allocation followed by out-of-bounds writes in the population loop. Fix by computing priv_size early and using it to bound num_cpu: each CPU needs at least one u64 metadata entry, so num_cpu cannot exceed the total number of u64 entries in the event's private data area. Fixes: cd8bfd8c973eaff8 ("perf tools: Add processing of coresight metadata") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: James Clark <james.clark@arm.com> Cc: Leo Yan <leo.yan@linaro.org> Cc: Tor Jeremiassen <tor@ti.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf machine: Use snprintf() for guestmount path constructionArnaldo Carvalho de Melo
machines__findnew() and machines__create_guest_kernel_maps() use sprintf() to build paths by prepending symbol_conf.guestmount. Both write into PATH_MAX stack buffers, but guestmount comes from user configuration and is not length-checked. A guestmount path at or near PATH_MAX causes a stack buffer overflow. Switch to snprintf() with sizeof() to prevent overflow. The subsequent access()/fopen() calls will fail on a truncated path. Fixes: a1645ce12adb6c9c ("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>
2026-06-17perf machine: Propagate machine__init() error to callersArnaldo Carvalho de Melo
machine__init() always returns 0 even when memory allocation fails, because commit 81f981d7ec43ed93 ("perf machine: Free root_dir in machine__init() error path") introduced 'int err = -ENOMEM' and an error cleanup path but left the final 'return 0' instead of 'return err'. Fix by returning err, check the return value in __machine__new_host() which was ignoring it, and change machines__init() from void to int so it too can propagate the error to perf_session__new(), aslr_tool__init() and test callers. The error cleanup also used zfree(&machine->kmaps), but kmaps is a refcounted maps structure — use maps__zput() to properly drop the reference, matching machine__exit(). Move dsos__init() and threads__init() before the first fallible allocation (maps__new) so that machine__exit() is safe to call on any machine struct that machine__init() touched, even on early failure. Fixes: 81f981d7ec43ed93 ("perf machine: Free root_dir in machine__init() error path") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Ian Rogers <irogers@google.com> Cc: Jiri Olsa <jolsa@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-16perf evsel: Add lazy-initialized probe type detection helpersArnaldo Carvalho de Melo
Several places in perf need to check whether an evsel is a kprobe or uprobe, which requires looking up the PMU by name via evsel__find_pmu(). This lookup walks the PMU list each time, which is wasteful when the same evsel is checked repeatedly. Add evsel__is_kprobe(), evsel__is_uprobe(), and evsel__is_probe() that resolve the probe type on first call via evsel__pmu_name() and cache the result in a 3-bit field (probe_type) in struct evsel. The field fits in existing padding after the bool fields, so struct size does not grow. The enum uses PROBE__UNKNOWN (0) as the uninitialized sentinel — explicitly set in evsel__init() — so the lookup happens on first use. PROBE__NOPE (1) caches "not a probe" to avoid repeated negative lookups. PMU-based probes (kprobe/uprobe PMU) are detected by PMU name. Ftrace-based dynamic probes (created via tracefs, reported as PMU "tracepoint") are detected by the __probe_ip field that the kernel adds to all dynamic probe formats. This covers kprobes, uprobes, and fprobes regardless of their group/system name. Cc: Aaron Tomlin <atomlin@atomlin.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-16perf evsel: Add no-libtraceevent stubs for evsel__field() and ↵Arnaldo Carvalho de Melo
evsel__common_field() When building without libtraceevent (NO_LIBTRACEEVENT=1), evsel__field() and evsel__common_field() are declared but never defined, causing link errors in any code path that references them. Add inline stubs that return NULL when HAVE_LIBTRACEEVENT is not defined, matching the pattern used by other evsel accessor functions. Cc: Aaron Tomlin <atomlin@atomlin.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf cs-etm: Reject CPU IDs that would overflow signed comparisonArnaldo Carvalho de Melo
metadata[j][CS_ETM_CPU] is a u64 from perf.data, but the comparison with max_cpu casts it to (int). A crafted value like 0xFFFFFFFF becomes -1 after the cast, which compares less than max_cpu (0), so the queue array is never sized to accommodate it. When the value is later passed to cs_etm__get_queue(), it indexes queue_array with the original large value, causing an out-of-bounds access. Validate that CS_ETM_CPU fits in an int before using it in the signed comparison. Fixes: 57880a7966be510c ("perf: cs-etm: Allocate queues for all CPUs") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: James Clark <james.clark@arm.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf bpf: Bounds-check array offsets in bpil_offs_to_addr()Arnaldo Carvalho de Melo
bpil_offs_to_addr() converts offsets stored in perf.data's bpf_prog_info_linear structure into heap pointers by adding the offset to the data allocation base. The offsets come from untrusted file input and are not validated against data_len. If an offset exceeds data_len, the computed address points outside the allocated data buffer. Callers like synthesize_bpf_prog_name() then dereference prog_tags[sub_id] or func_info pointers, reading arbitrary heap memory. Add a bounds check: when an offset exceeds data_len, zero the field and skip the conversion. This prevents out-of-bounds pointer construction from crafted perf.data files. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: 6ac22d036f86c4e2 ("perf bpf: Pull in bpf_program__get_prog_info_linear()") Cc: Dave Marchevsky <davemarchevsky@fb.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf bpf: Reject oversized BPF metadata events that truncate header.sizeArnaldo Carvalho de Melo
bpf_metadata_alloc() computes event_size from the number of BPF metadata variables and stores it in header.size, which is __u16. With 204 or more .rodata variables prefixed "bpf_metadata_", event_size exceeds 65535 and silently truncates. The truncated header.size causes synthesize_perf_record_bpf_metadata() to allocate a buffer sized by the truncated value, then memcpy the full event data into it — a heap buffer overflow. Add a check that event_size fits in __u16 before proceeding. BPF programs with that many metadata variables are exotic enough that silently dropping the metadata is acceptable. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: ab38e84ba9a80581 ("perf record: collect BPF metadata from existing BPF programs") Reviewed-by: Ian Rogers <irogers@google.com> Cc: Blake Jones <blakejones@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf bpf: Validate func_info_rec_size and sub_id in synthesize_bpf_prog_name()Arnaldo Carvalho de Melo
synthesize_bpf_prog_name() computes a pointer into the func_info array using sub_id * info->func_info_rec_size without validating either value. Both come from perf.data and are untrusted: - A func_info_rec_size smaller than sizeof(struct bpf_func_info) means the finfo pointer would reference a truncated entry, reading past it into adjacent data. - A sub_id >= nr_func_info computes an offset past the func_info buffer, causing an out-of-bounds read. Add bounds checks for both values before computing the pointer offset. When validation fails, fall through to the non-BTF name path instead of reading garbage. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: 7b612e291a5affb1 ("perf tools: Synthesize PERF_RECORD_* for loaded BPF programs") Cc: Song Liu <songliubraving@fb.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf hwmon: Fix fd check to accept fd 0 in hwmon_pmu__describe_items()Arnaldo Carvalho de Melo
hwmon_pmu__describe_items() checks 'if (fd > 0)' after openat(), which incorrectly rejects fd 0. While fd 0 is normally stdin, if stdin has been closed (common in daemon/service contexts), the kernel reuses fd 0 for the next open. With fd > 0, the sysfs file is not read and the fd is leaked. Change to 'if (fd >= 0)' to match the standard openat() error check. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: 53cc0b351ec99278 ("perf hwmon_pmu: Add a tool PMU exposing events from hwmon in sysfs") Reviewed-by: Ian Rogers <irogers@google.com> Cc: Ian Rogers <irogers@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf tools: Use snprintf() for root_dir path constructionArnaldo Carvalho de Melo
get_kernel_version() in machine.c and dso__load_guest_kernel_sym() in symbol.c use sprintf() to construct paths by prepending root_dir to "/proc/version" and "/proc/kallsyms" respectively. Both write into PATH_MAX stack buffers, but root_dir comes from --guestmount or KVM configuration and is not length-checked. A root_dir at or near PATH_MAX causes a stack buffer overflow. Switch to snprintf() with sizeof(path) to prevent overflow. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: a1645ce12adb6c9c ("perf: 'perf kvm' tool for monitoring guest performance from host") 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>
2026-06-17perf dso: Set error code when open() fails on uncompressed fallback pathArnaldo Carvalho de Melo
filename__decompress() has an early return for files that are not actually compressed, where it calls open() directly. When open() fails, the function returns -1 but never sets *err. The caller chain (decompress_kmodule → dso__decompress_kmodule_path → dso__get_filename) then reads *dso__load_errno(dso) to set errno, but that field was never populated, so errno gets a stale or zero value. With errno=0, __open_dso() computes fd = -errno = 0, which is non- negative, so callers treat fd 0 (stdin) as a valid DSO file descriptor. Set *err = errno when open() fails on the uncompressed path, matching the error handling on the compressed path at line 354. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: 8b42b7e5e8b5692b ("perf tools: Add is_compressed callback to compressions array") Cc: Jiri Olsa <jolsa@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf dso: Fix heap overflow in dso__get_filename() on decompressed pathArnaldo Carvalho de Melo
dso__get_filename() allocates name with malloc(PATH_MAX), but the dso__filename_with_chroot() path replaces name with an asprintf'd exact-size string (e.g. 8 bytes for "/a/b.ko"). When the DSO needs decompression, dso__decompress_kmodule_path() writes the temp path ("/tmp/perf-kmod-XXXXXX", 22 bytes) into newpath, and strcpy(name, newpath) overflows the smaller allocation. Replace the strcpy with strdup(newpath) + free(name) so the buffer is always correctly sized for its content. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: 1d6b3c9ba756a513 ("perf tools: Decompress kernel module when reading DSO data") Reviewed-by: Ian Rogers <irogers@google.com> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf symbols: Break infinite loop on zero-filled notes in sysfs__read_build_id()Arnaldo Carvalho de Melo
sysfs__read_build_id() iterates ELF note headers from sysfs files in a while(1) loop. If the file contains a zero-filled note header (both n_namesz and n_descsz are 0), the code computes n = namesz + descsz = 0 and calls read(fd, bf, 0). read() with count 0 returns 0, which matches the expected (ssize_t)n value, so the error check passes and the loop repeats — reading the same zero bytes and spinning forever. This can happen with corrupted or zero-padded sysfs pseudo-files. Add a check for n == 0 before the read, since no valid ELF note has both name and description of zero length. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: f1617b40596cb341 ("perf symbols: Record the build_ids of kernel modules too") Reviewed-by: Ian Rogers <irogers@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf symbols: Validate p_filesz before use in filename__read_build_id()Arnaldo Carvalho de Melo
filename__read_build_id() stores ELF p_filesz in a ssize_t variable. A crafted 32-bit ELF with p_filesz = 0xFFFFFFFF produces ssize_t value -1. The comparison `p_filesz > buf_size` evaluates false because signed -1 is less than any non-negative buf_size, so the realloc is skipped and buf remains NULL. The subsequent read(fd, NULL, -1) returns -1, which equals p_filesz, passing the error check. read_build_id() then dereferences the NULL buffer. Add an explicit check for p_filesz <= 0 before using the value, catching both zero-length and sign-wrapped negative sizes from crafted ELF files. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: ba0b7081f7a521d7 ("perf symbol-minimal: Fix ehdr reading in filename__read_build_id") Reviewed-by: Ian Rogers <irogers@google.com> Cc: Ian Rogers <irogers@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-17perf symbols: Fix bswap copy-paste error for 32-bit ELF p_fileszArnaldo Carvalho de Melo
filename__read_build_id() byte-swaps 32-bit ELF program headers on cross-endian files, but line 178 passes p_offset to bswap_32() instead of p_filesz: hdrs.phdr32[i].p_filesz = bswap_32(hdrs.phdr32[i].p_offset); This clobbers p_filesz with the already-swapped p_offset value. The 64-bit path on line 182 is correct and swaps p_filesz from p_filesz. The consequence is that the PT_NOTE segment read uses the wrong size, which can cause either a short read (missing the build-id) or an oversized read (reading past the segment into adjacent data). Fix by swapping the correct field. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: fef8f648bb47726d ("perf symbol: Fix use-after-free in filename__read_build_id") Reviewed-by: Ian Rogers <irogers@google.com> Cc: Ian Rogers <irogers@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-15perf aslr: Strip sample registersIan Rogers
Extend the ASLR tool stripping helpers to drop register dump payloads by masking out the relevant perf_event_attr fields (sample_regs_user, sample_regs_intr) when the delegated tool is handling the data. struct aslr_evsel_priv maintains the original perf_event_attr values and is looked up via the evsel_orig_attrs hashmap so that sample sizes can be properly parsed even when bits are stripped from the pipeline. This is critical for bounded array copying within aslr_tool__process_sample, which relies on orig_sample_type to determine exactly which fields were captured by the kernel before any stripping occurred. This allows us to keep samples that would otherwise be dropped because they contain registers, while still obfuscating the registers. Committer notes: Moved now used variables from the previous patch: struct aslr_evsel_priv *priv = NULL; u64 orig_sample_type; u64 orig_regs_user; u64 orig_regs_intr; Assisted-by: Antigravity:gemini-3.1-pro Co-developed-by: Gabriel Marin <gmx@google.com> Signed-off-by: Gabriel Marin <gmx@google.com> Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: James Clark <james.clark@linaro.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-15perf inject/aslr: Implement sample address remappingIan Rogers
Add the sample address remapping logic to the ASLR tool. This patch implements aslr_tool__process_sample, which parses sample events, remaps IPs, ADDRs, callchains, and branch stacks using the mappings collected from metadata events, and drops potentially leaking raw, register, stack, physical address, and aux samples. Also adds the aslr_tool__remap_address helper function. Note on cross-endian compatibility: 'perf inject' functions as an endianness converter. Input files are read, and their events are byte-swapped to host endianness in memory. When the tool emits its output, it writes a host-endian PERF_MAGIC in the file header, thereby marking the output file as host-endian natively. Because the output file is always written in host endianness, events and payloads must be constructed entirely using host-endian layouts. For this reason, this patch explicitly un-packs and repacks PERF_SAMPLE_TID (and PERF_SAMPLE_CPU) using unions to ensure that the sequential 32-bit layout is correctly aligned in host endianness. Similarly, branch stack flags (which are modified in-place to host-endian bitfields by the parser) are copied directly to the newly synthesized event. When re-parsing the newly synthesized event, 'needs_swap=false' is explicitly used to prevent double swapping the already host-endian fields. Committer notes: Removed several unused variables, they will be reintroduced in the following patches where they are finally used: struct aslr_evsel_priv *priv = NULL; u64 orig_sample_type; u64 orig_regs_user; u64 orig_regs_intr; Also used PRIx64 for two u64 args (addresses) and %zu for a size_t arg (map__size()) to fix the build on 32-bit architectures. Assisted-by: Antigravity:gemini-3.1-pro Co-developed-by: Gabriel Marin <gmx@google.com> Signed-off-by: Gabriel Marin <gmx@google.com> Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: James Clark <james.clark@linaro.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-15perf inject/aslr: Add ASLR tool infrastructure and MMAP trackingIan Rogers
If perf.data files are taken from one machine to another they may leak virtual addresses and so weaken ASLR on the machine they are coming from. Add an aslr option for perf inject that remaps all virtual addresses, or drops data/events, so that the virtual address information isn't leaked. This patch introduces the core ASLR remapping tool infrastructure and implements remapping/tracking for metadata events (MMAP, MMAP2, COMM, FORK, EXIT, KSYMBOL, TEXT_POKE). Sample events are delegated without remapping for now. Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Co-developed-by: Gabriel Marin <gmx@google.com> Signed-off-by: Gabriel Marin <gmx@google.com> Tested-by: James Clark <james.clark@linaro.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-15perf maps: Add maps__mutate_mappingIan Rogers
During kernel ELF symbol parsing (dso__process_kernel_symbol), proc kallsyms image loading (dso__load_kernel_sym, dso__load_guest_kernel_sym), and dynamic kernel memory map alignment updates (machine__update_kernel_mmap), the loader directly modifies live virtual address boundary keys fields on map objects. If these boundaries are mutated while the map pointer actively resides inside the parent maps cache array list (kmaps) outside of any lock closure, an unsafe concurrent window is exposed where parallel worker lookup threads (e.g., inside perf top) can mistakenly assume the cache remains sorted based on stale parameters, executing binary search queries (bsearch) across an unsorted range and triggering lookup failures. Fix this by introducing maps__mutate_mapping() that explicitly acquires the parent maps write semaphore lock, executes an incoming mutation callback block to perform the field updates under lock protection, and invalidates the sorted tracking flags prior to releasing the write lock. This guarantees synchronization invariants, closing the concurrent lookup race window. The adjacent module alignment pass inside machine__create_kernel_maps() is safely preserved as a high-performance lockless pass, as its invocation lifecycle bounds remain strictly single-threaded by contract during session initialization construction. To safely support this unconditional down_write write lock mutator without recursive read-to-write self-deadlock upgrades during lazy symbol loading, we introduce a public maps__load_maps() API. It copies map pointers under a brief read lock and force-loads all modules locklessly outside the lock. Callers (such as perf inject) must pre-load all kernel symbol maps up front at startup using maps__load_maps(), completely bypassing dynamic runtime mutations. Fixes: 39b12f781271 ("perf tools: Make it possible to read object code from vmlinux") Assisted-by: Antigravity:gemini-3.1-pro Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: James Clark <james.clark@linaro.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Gabriel Marin <gmx@google.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-11perf stat: Fix false NMI watchdog warning in aggregation modesChun-Tse Shao
In aggregation modes (e.g. --per-socket, --per-die, etc.), a counter might not be scheduled or counted on specific aggregate groups if it was not assigned to the CPUs belonging to those groups. However, the printout() check triggers the "print_free_counters_hint" logic unconditionally for any supported counter with a missing count. This results in a false "Some events weren't counted. Try disabling the NMI watchdog" warning. Furthermore, the NMI watchdog only reserves performance counters on core PMUs. Uncore PMU events (e.g. CHA, IMC) are not affected by the NMI watchdog, but their failures also falsely triggered this warning. This warning was originally introduced in commit 02d492e5dcb72c00 ("perf stat: Issue a HW watchdog disable hint") To fix this, restrict setting of print_free_counters_hint to only trigger for core PMU events by checking counter->pmu and counter->pmu->is_core. Example before/after: $ perf stat -M lpm_miss_lat --metric-only --per-socket -a -- sleep 1 Before: Performance counter stats for 'system wide': ns lpm_miss_lat_rem ns lpm_miss_lat_loc S0 126 202.3 207.9 S1 126 231.9 259.3 1.006029831 seconds time elapsed Some events weren't counted. Try disabling the NMI watchdog: echo 0 > /proc/sys/kernel/nmi_watchdog perf stat ... echo 1 > /proc/sys/kernel/nmi_watchdog After: Performance counter stats for 'system wide': ns lpm_miss_lat_rem ns lpm_miss_lat_loc S0 126 202.3 207.9 S1 126 231.9 259.3 1.006029831 seconds time elapsed Assisted-by: Gemini:gemini-next Reviewed-by: Ian Rogers <irogers@google.com> Signed-off-by: Chun-Tse Shao <ctshao@google.com> Cc: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf symbols: Add bounds checks to read_build_id() note iteration in minimal ↵Arnaldo Carvalho de Melo
build symbol-minimal.c's read_build_id() iterates ELF notes with the same pattern as symbol-elf.c's elf_read_build_id(): pointer arithmetic driven by n_namesz and n_descsz from 32-bit note header fields, without validating that the name and desc fit within the note section data. A malformed ELF file with oversized note sizes causes out-of-bounds reads past the section data buffer. Add the same bounds check as the libelf path: validate namesz and descsz individually against remaining data before advancing the pointer, avoiding size_t overflow on 32-bit. Fixes: b691f64360ecec49 ("perf symbols: Implement poor man's ELF parser") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf symbols: Add bounds checks to elf_read_build_id() note iterationArnaldo Carvalho de Melo
elf_read_build_id() iterates ELF notes using pointer arithmetic driven by n_namesz and n_descsz from the note headers. Neither the note header read nor the subsequent name/desc advances are checked against the section boundary. A malformed ELF file with oversized note sizes causes out-of-bounds reads past the section data buffer. Add two bounds checks: verify the note header fits within the remaining section data, and verify that namesz + descsz (after alignment) fits before advancing the pointer. Fixes: fd7a346ea292074e ("perf symbols: Filename__read_build_id should look at .notes section too") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf bpf: Fix metadata leak in perf_env__add_bpf_info() on duplicate insertArnaldo Carvalho de Melo
When perf_env__insert_bpf_prog_info() returns false (duplicate program), the error path frees info_linear and info_node but not info_node->metadata. If bpf_metadata_create() had succeeded, the metadata allocation is permanently leaked. Fix by calling bpf_metadata_free() on info_node->metadata before freeing info_node. bpf_metadata_free() handles NULL, so this is safe even when bpf_metadata_create() returned NULL. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: fdc3441f2d317b40 ("perf record: collect BPF metadata from new programs") Cc: Blake Jones <blakejones@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf bpf: Fix map data leak in bpf_metadata_create() on alloc failureArnaldo Carvalho de Melo
bpf_metadata_create() calls bpf_metadata_read_map_data() which allocates map.btf and map.rodata. If the subsequent bpf_metadata_alloc() fails, the code does 'continue' which skips bpf_metadata_free_map_data(), permanently leaking both allocations. Fix by calling bpf_metadata_free_map_data() before continue. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: ab38e84ba9a80581 ("perf record: collect BPF metadata from existing BPF programs") Cc: Blake Jones <blakejones@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf bpf: Add NULL check for btf__type_by_id() in synthesize_bpf_prog_name()Arnaldo Carvalho de Melo
synthesize_bpf_prog_name() calls btf__type_by_id() and immediately dereferences the result via t->name_off without checking for NULL. btf__type_by_id() returns NULL when the type_id is invalid or out of range. When processing perf.data files, finfo->type_id comes from untrusted input, so an invalid ID causes a NULL pointer dereference. Fix by checking t for NULL before dereferencing. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: fc462ac75b36daaa ("perf bpf: Extract logic to create program names from perf_event__synthesize_one_bpf_prog()") Cc: Song Liu <songliubraving@fb.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf tools: Use snprintf() in dso__read_running_kernel_build_id()Arnaldo Carvalho de Melo
dso__read_running_kernel_build_id() uses sprintf() to format a sysfs path from machine->root_dir into a PATH_MAX buffer. If root_dir is close to PATH_MAX in length, appending "/sys/kernel/notes" (18 bytes) overflows the stack buffer. Switch to snprintf() with sizeof(path) to prevent the overflow. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: cdd059d731eeb466 ("perf tools: Move dso_* related functions into dso object") Cc: Jiri Olsa <jolsa@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf hwmon: Guard label read against empty or failed readsArnaldo Carvalho de Melo
hwmon_pmu__read_events() reads label files with read() into a stack buffer, strips trailing newlines, then checks buf[0] == '\0'. When read() returns 0 (empty file) or -1 (error), the buffer is never written, so buf[0] reads uninitialized stack memory. If the garbage byte is non-zero, the code falls through to strdup(buf) which copies arbitrary stack data as the label string. Fix by checking read_len <= 0 before accessing buf contents, closing the fd and skipping the entry. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: 53cc0b351ec99278 ("perf hwmon_pmu: Add a tool PMU exposing events from hwmon in sysfs") Cc: Ian Rogers <irogers@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf tools: Fix uninitialized pathname on uncompressed fallback in ↵Arnaldo Carvalho de Melo
filename__decompress() filename__decompress() has an early return path for files that are not actually compressed. This path returns the fd from open() directly but never writes to the pathname output parameter, leaving the caller with an uninitialized buffer despite a successful return. Callers like dso__decompress_kmodule_path() pass pathname to decompress_kmodule() which uses it to set the decompressed file path. If pathname is uninitialized, subsequent operations on the path produce undefined behavior. Fix by setting pathname to an empty string on the uncompressed path. Callers already check for an empty pathname to distinguish temporary decompressed files (which need unlink) from the original file. Reported-by: sashiko-bot <sashiko-bot@kernel.org> Fixes: 7ac22b088afe26a4 ("perf tools: Add filename__decompress function") Cc: Jiri Olsa <jolsa@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf symbols: Bounds-check descsz in sysfs__read_build_id() GNU fallbackArnaldo Carvalho de Melo
When sysfs__read_build_id() matches NT_GNU_BUILD_ID with the right namesz but the name content is not "GNU", it falls back to reading descsz bytes into the stack buffer bf[BUFSIZ]: } else if (read(fd, bf, descsz) != (ssize_t)descsz) Unlike the else branch which validates namesz + descsz against sizeof(bf), this path passes descsz directly to read() without any bounds check. A crafted sysfs file with a large n_descsz overflows the 8192-byte stack buffer. Add a descsz > sizeof(bf) check before the read, breaking out of the loop on oversized values. Fixes: e5a1845fc0aeca85 ("perf symbols: Split out util/symbol-elf.c") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf hwmon: Fix parse_hwmon_filename() strlcpy buffer overflowArnaldo Carvalho de Melo
parse_hwmon_filename() strips the "_alarm" suffix from event names by copying into a 24-byte stack buffer: strlcpy(fn_type, fn_item, fn_item_len - 5); The third argument is the source length minus the suffix, not the destination buffer capacity. A long event name ending in "_alarm" can have fn_item_len - 5 > sizeof(fn_type), causing strlcpy() to write past the 24-byte fn_type[] array. The assert() only validates that the longest *valid* hwmon item fits, but does not protect against crafted input. Clamp the strlcpy size to min(fn_item_len - 5, sizeof(fn_type)). Fixes: 4810b761f812da3c ("perf hwmon_pmu: Add hwmon filename parser") 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>
2026-06-10perf hwmon: Use scnprintf() in hwmon_pmu__for_each_event()Arnaldo Carvalho de Melo
hwmon_pmu__for_each_event() formats description strings via: len = snprintf(desc_buf, sizeof(desc_buf), "%s in unit %s named %s.", ...); len += hwmon_pmu__describe_items(hwm, desc_buf + len, sizeof(desc_buf) - len, ...); If value->label is long enough to cause snprintf() to truncate, it returns the would-have-been-written count, making len exceed sizeof(desc_buf). The subsequent sizeof(desc_buf) - len underflows to a huge size_t value, disabling bounds checking in hwmon_pmu__describe_items(). The alias_buf snprintf has the same issue. Switch both to scnprintf() which returns actual bytes written. Fixes: 53cc0b351ec99278 ("perf hwmon_pmu: Add a tool PMU exposing events from hwmon in sysfs") 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>
2026-06-10perf hwmon: Fix off-by-one null termination on sysfs readsArnaldo Carvalho de Melo
Three functions read sysfs files into fixed-size stack buffers using the full buffer size, then null-terminate at buf[read_len]. If the read fills the buffer exactly, read_len equals sizeof(buf) and the null byte writes one past the array, corrupting an adjacent stack variable. Fix all three by reading sizeof(buf) - 1 bytes, reserving space for the null terminator: - hwmon_pmu__read_events(): buf[128] - hwmon_pmu__describe_items(): buf[64] - evsel__hwmon_pmu_read(): buf[32] Fixes: 53cc0b351ec99278 ("perf hwmon_pmu: Add a tool PMU exposing events from hwmon in sysfs") 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>
2026-06-10perf tools: Fix thread__set_comm_from_proc() on empty comm fileArnaldo Carvalho de Melo
thread__set_comm_from_proc() calls procfs__read_str() then strips the trailing newline via comm[sz - 1] = '\0'. procfs__read_str() allocates the buffer before reading, so on an empty /proc/pid/comm (reachable during late exit teardown) it returns success with sz = 0 and an unterminated heap buffer. The sz - 1 underflow was the original sashiko finding: it writes a null byte before the allocation. But even with a sz > 0 guard on the newline strip, the unterminated buffer would still be passed to thread__set_comm() which calls strlen() — an unbounded heap read. Fix by treating sz == 0 as failure: free the buffer and return -1. This is consistent with pmu.c's perf_pmu__parse_scale/unit which already treat len == 0 from filename__read_str as an error. Fixes: 2f3027ac28bf6bc3 ("perf thread: Introduce method to set comm from /proc/pid/self") 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>
2026-06-10perf intel-pt: Fix snprintf size tracking bug in insn decoderArnaldo Carvalho de Melo
dump_insn() tracks remaining buffer space with a 'left' variable, but the loop subtracts the cumulative offset 'n' each iteration instead of just the per-iteration delta: n += snprintf(x->out + n, left, "%02x ", inbuf[i]); left -= n; /* BUG: n is cumulative, not the delta */ After two iterations left goes massively negative, wrapping to a huge value when passed as size_t to snprintf(), disabling all bounds checking for the rest of the loop. Switch to scnprintf() accumulation using sizeof(x->out) - n as the remaining space, which is always correct and eliminates the separate 'left' variable entirely. Fixes: 48d02a1d5c137d36 ("perf script: Add 'brstackinsn' for branch stacks") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Andi Kleen <ak@linux.intel.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf tools: Use mkostemp() for O_CLOEXEC on temporary filesArnaldo Carvalho de Melo
mkstemp() creates file descriptors without the close-on-exec flag. These fds leak to child processes spawned during symbol resolution (addr2line, objdump), wasting descriptors and potentially exposing temporary file contents. Replace mkstemp() with mkostemp(tmpbuf, O_CLOEXEC) at all three call sites: - filename__decompress() in dso.c - read_gnu_debugdata() in symbol-elf.c - kcore__init() in symbol-elf.c Fixes: 42b3fa670825983f ("perf tools: Introduce dso__decompress_kmodule_{fd,path}") Fixes: b10f74308e130527 ("perf symbol: Support .gnu_debugdata for symbols") Fixes: afba19d9dc8eba66 ("perf symbols: Workaround objdump difficulties with kcore") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Stephen Brennan <stephen.s.brennan@oracle.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf symbols: Bounds-check .gnu_debuglink section dataArnaldo Carvalho de Melo
filename__read_debuglink() copies .gnu_debuglink section data into a caller-provided buffer via: strncpy(debuglink, data->d_buf, size); where size is PATH_MAX. If the ELF section is smaller than size and lacks a null terminator, strncpy reads past data->d_buf into adjacent memory. A malformed ELF file can trigger this, potentially causing a segfault or leaking heap data. Additionally, strncpy does not guarantee null termination when the source fills the buffer. Replace with an explicit memcpy bounded by both the output buffer size and the actual section data size (data->d_size), followed by explicit null termination. Fixes: e5a1845fc0aeca85 ("perf symbols: Split out util/symbol-elf.c") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf symbols: Fix signed overflow in sysfs__read_build_id() size checkArnaldo Carvalho de Melo
sysfs__read_build_id() reads ELF note headers from sysfs files. The note's namesz and descsz fields are used to compute the skip size: int n = namesz + descsz; if (n > (int)sizeof(bf)) Both namesz and descsz are size_t from NOTE_ALIGN() of 32-bit note header fields. Their sum can exceed INT_MAX, overflowing the signed int n to a negative value. The check n > sizeof(bf) then evaluates false (negative < positive in signed comparison), and read(fd, bf, n) reinterprets the negative n as a huge size_t count — the kernel writes up to MAX_RW_COUNT bytes into the 8192-byte stack buffer. In practice the overflow is bounded by the sysfs file's actual size, so a real sysfs notes file won't trigger it organically. But crafted input (e.g. via a mounted debugfs/sysfs image) could. Fix by validating namesz and descsz individually against the buffer size before summing, and change n to size_t to avoid the signed overflow entirely. Fixes: f1617b40596cb341 ("perf symbols: Record the build_ids of kernel modules too") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf pmu: Fix perf_pmu__parse_scale/unit() OOB access on empty sysfs fileArnaldo Carvalho de Melo
perf_pmu__parse_scale() reads a PMU scale file then accesses scale[sret - 1] to strip a trailing newline. Only sret < 0 is guarded, so an empty file (sret == 0) causes scale[-1] — a stack buffer underflow that reads and potentially writes out of bounds. perf_pmu__parse_unit() has the same pattern: alias->unit[sret - 1] with sret == 0 accesses the byte before the struct member, which may corrupt the adjacent pmu_name pointer field. Change both guards from sret < 0 to sret <= 0 so that empty files are treated as read errors. Fixes: 410136f5dd96b601 ("tools/perf/stat: Add event unit and scale support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Stephane Eranian <eranian@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf pmu: Fix pmu_id() heap underwrite on empty identifier fileArnaldo Carvalho de Melo
pmu_id() calls filename__read_str() then strips the trailing newline via str[len - 1] = 0. If the PMU identifier file is empty, filename__read_str() succeeds with len = 0. len - 1 underflows size_t to SIZE_MAX, writing a null byte before the heap allocation. Add a len == 0 check before the newline stripping. Fixes: 51d548471510843e ("perf pmu: Add pmu_id()") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: John Garry <john.g.garry@oracle.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf jitdump: Fix a build error with ASANNamhyung Kim
I found this error when I pass EXTRA_CFLAGS=-fsanitize=address on Fedora 44 with GCC 16. Fix it by copying one less byte. CC util/jitdump.o util/jitdump.c: In function ‘jit_process’: util/jitdump.c:237:9: error: ‘__builtin_strncpy’ specified bound 4096 equals destination size [-Werror=stringop-truncation] 237 | strncpy(jd->dir, name, PATH_MAX); | ^ cc1: all warnings being treated as errors make[4]: *** [tools/build/Makefile.build:95: util/jitdump.o] Error 1 make[4]: *** Waiting for unfinished jobs.... make[3]: *** [tools/build/Makefile.build:158: util] Error 2 make[2]: *** [Makefile.perf:578: perf-util-in.o] Error 2 make[1]: *** [Makefile.perf:288: sub-make] Error 2 make: *** [Makefile:76: all] Error 2 Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: James Clark <james.clark@linaro.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf cs-etm: Queue context packets for frontendJames Clark
PE_CONTEXT elements update the context ID and exception level, but the decoder may still have prior packets cached for frontend processing. Updating the context immediately in the decoder backend can make those cached packets get consumed with the wrong thread or EL state. Add a CS_ETM_CONTEXT packet carrying the TID and EL to the frontend, this keeps context changes ordered with the rest of the packet stream and avoids mismatches when synthesizing samples from cached packets. Separate the memory access function into one for the frontend and one for decoding. The frontend also needs memory access to attach the instruction to samples. Because the frontend does memory access for both previous and current packets, change all the frontend memory access function signatures to take both a tidq and packet. But backend always uses the current backend EL and thread from the tidq. Treat context packets as a boundary for branch sample generation and remove tidq->prev_packet_thread because it's not possible to branch to a different thread, so only tracking the current thread is required for sample generation. Fixes: e573e978fb12e160 ("perf cs-etm: Inject capabilitity for CoreSight traces") Reported-by: Amir Ayupov <aaupov@meta.com> Closes: https://lore.kernel.org/linux-perf-users/20260515021135.1729028-1-aaupov@meta.com/ Co-authored-by: James Clark <james.clark@linaro.org> Signed-off-by: Leo Yan <leo.yan@arm.com> Cc: Ian Rogers <irogers@google.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: linux-doc@vger.kernel.org Cc: Mike Leach <mike.leach@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Paschalis Mpeis <Paschalis.Mpeis@arm.com> Cc: Robert Walker <robert.walker@arm.com> Cc: Shuah Khan <skhan@linuxfoundation.org> Cc: Suzuki Poulouse <suzuki.poulose@arm.com> Signed-off-by: James Clark <james.clark@linaro.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf pmu: Use scnprintf in buffer offset calculationsAthira Rajeev
Replace snprintf with scnprintf in buffer offset calculations to ensure the 'used' count will not exceed the "len". The current logic in perf_pmu__for_each_event uses an unconditional + 1 increment to buf_used to account for null terminators. This can cause a stack buffer overflow in the subsequent scnprintf call. When the local stack buffer buf (1024 bytes) is full, buf_used can reach 1025. This causes the subsequent remaining space calculation sizeof(buf) - buf_used to underflow. Use sub_non_neg() to see if space actually existed, and only increment the offset if remaining space is present. Changes includes: - Use sub_non_neg to check if space exists - Replacing snprintf with scnprintf to ensure the return value reflects the actual bytes written into the buffer. - Only increment buf_used by 1 if space exists - If a parameterized event uses a built-in perf keyword for its parameter name (eg, config=?), the lexer parses it as a predefined term token, which sets term->config to NULL. Add check to use parse_events__term_type_str() if term->config is NULL. Signed-off-by: Athira Rajeev <atrajeev@linux.ibm.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Hari Bathini <hbathini@linux.vnet.ibm.com> Cc: Ian Rogers <irogers@google.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Madhavan Srinivasan <maddy@linux.ibm.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Shivani Nittor <shivani@linux.ibm.com> Cc: Tanushree.Shah@ibm.com Cc: Tejas.Manhas1@ibm.com Cc: Thomas Richter <tmricht@linux.ibm.com> Cc: Venkat Rao Bagalkote <venkat88@linux.ibm.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2026-06-10perf tools: Fix the check for parameterized field in event termAthira Rajeev
The format_alias() function in util/pmu.c has a check to detect whether the event has parameterized field ( =? ). The string alias->terms contains the event and if the event has user configurable parameter, there will be presence of sub string "=?" in the alias->terms. Snippet of code: /* Paramemterized events have the parameters shown. */ if (strstr(alias->terms, "=?")) { /* No parameters. */ snprintf(buf, len, "%.*s/%s/", (int)pmu_name_len, pmu->name, alias->name); if "strstr" contains the substring, it returns a pointer and hence enters the above check which is not the expected check. And hence "perf list" doesn't have the parameterized fields in the result. Fix this check to use: if (!strstr(alias->terms, "=?")) { With this change, perf list shows the events correctly with the strings showing parameters. Before the fix: # ./perf list|grep -w PM_PAU_CYC hv_24x7/PM_PAU_CYC/ [Kernel PMU event] With this fix: # ./perf list|grep -w PM_PAU_CYC hv_24x7/PM_PAU_CYC,chip=?/ [Kernel PMU event] Reviewed-by: Ian Rogers <irogers@google.com> Signed-off-by: Athira Rajeev <atrajeev@linux.ibm.com> Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Hari Bathini <hbathini@linux.vnet.ibm.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Madhavan Srinivasan <maddy@linux.ibm.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Shivani Nittor <shivani@linux.ibm.com> Cc: Tanushree.Shah@ibm.com Cc: Tejas.Manhas1@ibm.com Cc: Thomas Richter <tmricht@linux.ibm.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>